HAL_STM32F407_快速IAP_keil版
基于正点原子探索者开发板
先用CUBEMX准备一个带串口的工程
Copy文件
打开stm32固件包的存放地址
这里选F4的最新包
从这些官方例程里找到带IAP的例程,以STM324x9I_EVAL为例,进入“STM32Cube_FW_F4_V1.28.0\Projects\STM324x9I_EVAL\Applications\IAP\IAP_Main”
复制相关的.c和.h文件
把上面的文件复制到一开始的工程模板中
代码修改
编译一下看一下程序占用大小
根据IAP程序大小修改跳转地址
接下来准备APP工程
根据IAP中APP的跳转地址设置APP工程偏移
设置ROM大小
生成APP的bin文件,
感兴趣的话可以看一下
这里是引用keil使用记录
使用
使用支持YModem的工具,这里以WinTerm为例。
开发板复位显示下面字符。
下载(1)
上传(2)
进入APP(3)
开启/关闭FLASH保护(3)
输入1上传
找到APP的bin文件
传输完成
输入3跳转进入APP。
注意APP部分大于256的情况
/**
* @brief Receive a file using the ymodem protocol with CRC16.
* @param p_size The size of the file.
* @retval COM_StatusTypeDef result of reception/programming
*/
COM_StatusTypeDef Ymodem_Receive ( uint32_t *p_size )
{
uint32_t i, packet_length, session_done = 0, file_done, errors = 0, session_begin = 0;
uint32_t flashdestination, ramsource, filesize;
uint8_t *file_ptr;
uint8_t file_size[FILE_SIZE_LENGTH], tmp, packets_received;
COM_StatusTypeDef result = COM_OK;
/* Initialize flashdestination variable */
flashdestination = APPLICATION_ADDRESS;
volatile int8_t is_first_pack = 1;
while ((session_done == 0) && (result == COM_OK))
{
packets_received = 0;
file_done = 0;
while ((file_done == 0) && (result == COM_OK))
{
switch (ReceivePacket(aPacketData, &packet_length, DOWNLOAD_TIMEOUT))
{
case HAL_OK:
errors = 0;
switch (packet_length)
{
case 2:
/* Abort by sender */
Serial_PutByte(ACK);
result = COM_ABORT;
break;
case 0:
/* End of transmission */
Serial_PutByte(ACK);
file_done = 1;
break;
default:
/* Normal packet */
if (aPacketData[PACKET_NUMBER_INDEX] != packets_received)
{
Serial_PutByte(NAK);
}
else
{
if (packets_received == 0)
{
/* File name packet */
if (aPacketData[PACKET_DATA_INDEX] != 0)
{
if(is_first_pack==1){
/* File name extraction */
i = 0;
file_ptr = aPacketData + PACKET_DATA_INDEX;
while ( (*file_ptr != 0) && (i < FILE_NAME_LENGTH))
{
aFileName[i++] = *file_ptr++;
}
/* File size extraction */
aFileName[i++] = '\0';
i = 0;
file_ptr ++;
while ( (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH))
{
file_size[i++] = *file_ptr++;
}
file_size[i++] = '\0';
Str2Int(file_size, &filesize);
/* Test the size of the image to be sent */
/* Image size is greater than Flash size */
if (*p_size > (USER_FLASH_SIZE + 1))
{
/* End session */
tmp = CA;
HAL_UART_Transmit(&UartHandle, &tmp, 1, NAK_TIMEOUT);
HAL_UART_Transmit(&UartHandle, &tmp, 1, NAK_TIMEOUT);
result = COM_LIMIT;
}
/* erase user application area */
FLASH_If_Erase(APPLICATION_ADDRESS);
*p_size = filesize;
Serial_PutByte(ACK);
Serial_PutByte(CRC16);
is_first_pack = 0;
}
else
{
ramsource = (uint32_t) & aPacketData[PACKET_DATA_INDEX];
if (FLASH_If_Write(flashdestination, (uint32_t*) ramsource, packet_length/4) == FLASHIF_OK)
{
flashdestination += packet_length;
Serial_PutByte(ACK);
}
else
{
Serial_PutByte(CA);
Serial_PutByte(CA);
result = COM_DATA;
}
}
}
/* File header packet is empty, end session */
else
{
Serial_PutByte(ACK);
file_done = 1;
session_done = 1;
break;
}
}
else /* Data packet */
{
ramsource = (uint32_t) & aPacketData[PACKET_DATA_INDEX];
/* Write received data in Flash */
if (FLASH_If_Write(flashdestination, (uint32_t*) ramsource, packet_length/4) == FLASHIF_OK)
{
flashdestination += packet_length;
Serial_PutByte(ACK);
}
else /* An error occurred while writing to Flash memory */
{
/* End session */
Serial_PutByte(CA);
Serial_PutByte(CA);
result = COM_DATA;
}
}
packets_received ++;
packets_received=packets_received%256;
session_begin = 1;
}
break;
}
break;
case HAL_BUSY: /* Abort actually */
Serial_PutByte(CA);
Serial_PutByte(CA);
result = COM_ABORT;
break;
default:
if (session_begin > 0)
{
errors ++;
}
if (errors > MAX_ERRORS)
{
/* Abort communication */
Serial_PutByte(CA);
Serial_PutByte(CA);
}
else
{
Serial_PutByte(CRC16); /* Ask for a packet */
}
break;
}
}
}
return result;
}
/**
* @brief This function does an erase of all user flash area
* @param start: start of user flash area
* @retval FLASHIF_OK : user flash area successfully erased
* FLASHIF_ERASEKO : error occurred
*/
uint32_t FLASH_If_Erase(uint32_t start)
{
uint32_t NbrOfPages = 0;
uint32_t PageError = 0;
FLASH_EraseInitTypeDef pEraseInit;
HAL_StatusTypeDef status = HAL_OK;
/* Unlock the Flash to enable the flash control register access *************/
HAL_FLASH_Unlock();
/* Get the sector where start the user flash area */
// NbrOfPages = (USER_FLASH_END_ADDRESS - start)/FLASH_PAGE_SIZE;
NbrOfPages=0XFA;
pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
pEraseInit.PageAddress = start;
pEraseInit.Banks = FLASH_BANK_1;
pEraseInit.NbPages = NbrOfPages;
status = HAL_FLASHEx_Erase(&pEraseInit, &PageError);
/* Lock the Flash to disable the flash control register access (recommended
to protect the FLASH memory against possible unwanted operation) *********/
HAL_FLASH_Lock();
if (status != HAL_OK)
{
/* Error occurred while page erase */
return FLASHIF_ERASEKO;
}
return FLASHIF_OK;
}
其他型号
1、stm32f103c8t6
PM0075_STM32F10xxx单片机编程手册_ENV2.2
stm32f103c8t6
程序完整性校验
参考
硬汉嵌入式