本帖最后由 穿西装的强子 于 2024-4-8 11:45 编辑
#申请原创# 以STM32F407VET6为例,片上FLASH共有1MBytes大小,分为12个扇区,按datasheet图所示,Main memory
升级主要流程
按不同需求分为几个部分
1.bootloader程序
2.APP程序
3.升级缓存
4.备份(可选)
5.数据存储
一、BootLoader程序及流程
流程图如下:
FLASH分区
以标黄的部分作为自定义的FLASH分区
1.bootloader程序区
2.APP程序区
3.升级缓存区
4.备份区(可选)
5.数据存储区
以上五个部分进行分区
a)bootloader一般10~20Kbytes大小,以64K大小为例,使用扇区0~3;
b)APP程序区,根据不同的代码有不同的大小,若需要备份区,则代码根据剩余的大小平均分3份,例如(1024-32)/3 =330.6666666666667,但是从扇区5开始都是128Kbytes的大小,所以我们暂定256Kbytes大小,那么从扇区5~扇区6为APP区;
c)升级缓存区,该区域是将升级的文件接收到之后放置在该区域,所以该区域的大小是与APP程序区的大小一致,因此分配扇区7~扇区8;
d)备份区,该区域作为软件备份使用,将APP程序备份在此区域,若需要恢复出厂设置或者回退版本则需要将此处数据复制到APP区即可,因此分配扇区9~扇区10;
e)数据存储区,该区域作为自定义数据存储和升级数据的存储区域,一般不会太大,使用扇区4或者扇区11~扇区12均可;
不同的芯片不同的FLASH大小均可按此种方式进行分配;
BootLoader升级代码流程
一、检测是否有APP标志或者找到APP地址上是否有数据
- void DevUpdate_Handle(void)
- {
- if( gfirmbuff->gProtocolFirmware.App_flag == TRUE || (*(__IO uint32_t *)FLASH_APP_ADDR) != 0xFFFFFFFF)
- {
- if( gfirmbuff->gProtocolFirmware.Update_active == Active_reload ) // 如果有回退标记
- {
- if( gfirmbuff->gProtocolFirmware.Backoff_flag == TRUE) // 如果备份区有数据则回退,否则正常进入系统
- {
- DevUpdate_Realod();
- }
- else
- gfirmbuff->gProtocolFirmware.Update_active = Active_none;
- }
- else if( gfirmbuff->gProtocolFirmware.Update_active == Active_update) // 如果有更新标记
- {
- DevUpdate_Update();
- }
- else if( gfirmbuff->gProtocolFirmware.Update_active == Active_none) // 无更新,无回退并且有APP则直接进入系统
- {
- DevUpdate_JumpToApp();
- }
- }
- }
二、更新数据到APP地址
- void DevUpdate_Update(void)
- {
- INT32U i = 0;
- INT32U buff[10];
- INT32U buff_2;
- DrvFlash_ReadWords(FLASH_DATA_ADDR,&buff_2,1);
- if( buff_2 != 0xFFFFFFFF)
- {
- // 将缓存数据复制到FLASH内
- for(i = 0; i < APP_ROM_SIZE/40; i++)
- {
- DrvFlash_ReadWords(FLASH_DATA_ADDR+i*40,buff,10);
- DrvFlash_WriteWords(FLASH_APP_ADDR+i*40,buff,10);
- }
-
- gfirmbuff->gProtocolFirmware.firmwaresize = 0;
- gfirmbuff->gProtocolFirmware.Update_active = Active_none;
- DevProtocol_SaveUpdateParameter(); // 记录数据
- }
- else
- gfirmbuff->gProtocolFirmware.Update_active = Active_none;
- }
三、跳转到APP
- void DevUpdate_JumpToApp(void)
- {
- DevProtocol_SaveUpdateParameter();
- DrvTimer_Disable(Timer2);
- DrvUart_Disable(UartPort1);
- __disable_irq();
-
- /* Test if user code is programmed starting from address "ApplicationAddress" */
- if (((*(__IO uint32_t *)FLASH_APP_ADDR) & 0x2FFE0000) == 0x20000000) //检查栈顶地址是否合法
- {
- /* Jump to user application */
- JumpAddress = *(__IO uint32_t *)(FLASH_APP_ADDR + 4);
- Jump_To_Application = (pFunction)JumpAddress;
- /* Initialize user application's Stack Pointer */
- __set_MSP(*(__IO uint32_t *)FLASH_APP_ADDR);
-
- //Jump to APP
- Jump_To_Application();
- }
- }
bin文件通过串口或者其它通信,将bin转换为16进制数据,将数据发送到缓存区内,通过校验后,将缓存区的数据复制到APP区,跳转到APP区的起始地址,再将msp设置到APP区的起始地址,整个流程就算完成;
二、APP程序
APP只需要处/3个地方
1、起始地址和大小的配置
2、生成BIN文件
3、设置FLASH的偏移
这样便完成整个IAP升级的流程。
|