[应用相关] STM32F4单片机bootloader及在线升级IAP基本原理

[复制链接]
6536|87
 楼主| 发给她更好fh 发表于 2023-9-30 23:59 | 显示全部楼层
 楼主| 发给她更好fh 发表于 2023-9-30 23:59 | 显示全部楼层
偏移设置原位置在启动文件中对应的系统初始化void SystemInit(void)中,因此在每一份程序的main函数要要增加一行代码设置向量表偏移,如下所示在flash基地址0x0800 0000 基础上偏移0x20000:
 楼主| 发给她更好fh 发表于 2023-9-30 23:59 | 显示全部楼层
SCB->VTOR = FLASH_BASE | Flag_Table.ull_vetofflen; /* Vector Table Relocation in
 楼主| 发给她更好fh 发表于 2023-9-30 23:59 | 显示全部楼层
示例如下:
int main(void)
{
        ReadFlagTable(&Flag_Table);//将标志位的表读       
        SCB->VTOR = FLASH_BASE | Flag_Table.ull_vetofflen; /* Vector Table Relocation in Internal FLASH */               
        Sysint();//系统初始化
        while(1)
        {
        }
 楼主| 发给她更好fh 发表于 2023-9-30 23:59 | 显示全部楼层
APP中升级方案如下:

 楼主| 发给她更好fh 发表于 2023-9-30 23:59 | 显示全部楼层
 楼主| 发给她更好fh 发表于 2023-9-30 23:59 | 显示全部楼层
前半部分为正常逻辑流程,后半部分为升级流程,当单片机收到升级指令后,将升级文件写到另外一个APP区,最后根据发送的校验信息完成最终flag标志位的写入然后进行复位操作。
 楼主| 发给她更好fh 发表于 2023-10-1 00:00 | 显示全部楼层
测试代码如下:
单片机中将bin形式的升级文件接收到数组auch_UartRxBuf[]中,接收完成将标志位uch_updateflag置位,主循环中判断成功后,将数组auch_UartRxBuf[]写入另外一个APP对应的flash区域内。写入成功后将运行标志ull_updaterun_flag以及偏移长度ull_vetofflen写入flag分区中。然后关中断重启即可。
————————————————
版权声明:本文为CSDN博主「蜗牛Jay」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43058521/article/details/125355343
 楼主| 发给她更好fh 发表于 2023-10-1 00:00 | 显示全部楼层
int main(void)
{       
        ReadFlagTable(&Flag_Table);//将标志位的表读       
        SCB->VTOR = FLASH_BASE | Flag_Table.ull_vetofflen; /* Vector Table Relocation in Internal FLASH */               
        Sysint();//系统初始化
        for(int i=0;i<5;i++)
        {
                delay_ms(500);
                GPIO_ToggleBits(GPIOF, GPIO_Pin_9);       
        }               
        while(1)
        {
                delay_ms(1000);       
                GPIO_ToggleBits(GPIOF, GPIO_Pin_9);                               
                if(uch_updateflag==1)
                {
                        uch_updateflag=0;                       
                        if(Flag_Table.ull_updaterun_flag==0x00000011)
                        {
                                ull_vetselect = 0x40000;//更换BIN文件中的偏移                               
                                if(WriteAppBinToFlash2(STM32_FLASH_APP2_BASE,auch_UartRxBuf,uch_updataLen))
                                {
                                        Flag_Table.ull_updaterun_flag=0x00000022;
                                        Flag_Table.ull_vetofflen = 0x40000;
                                        WriteFlagTable(&Flag_Table);//将标志位的表写入       
                                        INTX_DISABLE();//close interupt
                                        NVIC_SystemReset();//重启                                                               
                                }       
                        }
                        else if(Flag_Table.ull_updaterun_flag==0x00000022)
                        {
                                ull_vetselect = 0x20000;//更换BIN文件中的偏移
                                if(WriteAppBinToFlash2(STM32_FLASH_APP1_BASE,auch_UartRxBuf,uch_updataLen))
                                {               
                                        Flag_Table.ull_updaterun_flag=0x00000011;
                                        Flag_Table.ull_vetofflen = 0x20000;                                       
                                        WriteFlagTable(&Flag_Table);//将标志位的表写入       
                                        INTX_DISABLE();//close interupt                                       
                                        NVIC_SystemReset();//重启                                                                       
                                }       
       
                        }
                }
}
 楼主| 发给她更好fh 发表于 2023-10-1 00:00 | 显示全部楼层
因为不同烧写地址偏移对应的bin文件不同(最大不同是向量表地址都是固定的),所以在升级文件写入flash时要更改源码文件。
更改程序烧写首地址如图所示。
 楼主| 发给她更好fh 发表于 2023-10-1 00:00 | 显示全部楼层
 楼主| 发给她更好fh 发表于 2023-10-1 00:00 | 显示全部楼层
相同源码更改烧写地址后bin文件的不同。

8567165184622524ad.png
 楼主| 发给她更好fh 发表于 2023-10-1 00:00 | 显示全部楼层
通过对比发现固定不同的是偏移,图中左边偏移为0x40000右边为0x20000,如果想要将不同的bin文件从APP1移动到APP2所在的flash区域,只需要将bin文件中的偏移更改掉即可。更改方式如下:
 楼主| 发给她更好fh 发表于 2023-10-1 00:00 | 显示全部楼层
  1. //将升级代码写入临时存储区
  2. u32 WriteAppBinToFlash2(u32 appxaddr,u8 *appbuf,u32 appsize)
  3. {
  4.         u32 t;
  5.         u32 iapbuf[UpdatePacketMaxLen/4];//缓存
  6.         u16 i=0;
  7.         u32 temp;
  8.         u32 fwaddr=appxaddr;//当前写入的地址
  9.         u8 *dfu=appbuf;
  10.         memset(&iapbuf,0xff,sizeof(iapbuf));
  11.         for(t=0;t<appsize;t+=4)
  12.         {                                                  
  13.                 temp=(u32)dfu[3]<<24;   
  14.                 temp|=(u32)dfu[2]<<16;   
  15.                 temp|=(u32)dfu[1]<<8;
  16.                 temp|=(u32)dfu[0];          
  17.                 dfu+=4;//偏移4个字节
  18.                 if((((temp)&0xFFFF0000)==(FLASH_BASE | Flag_Table.ull_vetofflen))&&(((temp)&0x0000FFFF)!=0X00000000))
  19.                 {
  20.                         temp = ((temp)&0x0000FFFF)|(FLASH_BASE|ull_vetselect);               
  21.                 }
  22.                 iapbuf[i++]=temp;            
  23.                 if(i==UpdatePacketMaxLen/4)
  24.                 {
  25.                         i=0;
  26.                         if(STMFLASH_Write(fwaddr,iapbuf,UpdatePacketMaxLen/4))
  27.                           fwaddr+=UpdatePacketMaxLen;//偏移  UpdatePacketMaxLen=N*4
  28.                         else
  29.                                 return FALSE;
  30.                 }
  31.         }
  32.         if(i)
  33.         {
  34.                 if(!STMFLASH_Write(fwaddr,iapbuf,i))//将最后的一些内容字节写进去.
  35.                         return FALSE;
  36.         }
  37.   return fwaddr;
  38. }
Henryko 发表于 2023-10-10 13:21 | 显示全部楼层
bootloader该怎么自己写啊
AloneKaven 发表于 2023-10-10 17:34 | 显示全部楼层
地址映射是怎么实现的啊
Stahan 发表于 2023-10-11 20:38 | 显示全部楼层
main地址放在哪里合适啊
 楼主| 发给她更好fh 发表于 2024-1-31 20:30 | 显示全部楼层
在读取每个4字节数据时判断偏移量是否为当前APP区域的偏移,等于就改写偏移。

                if((((temp)&0xFFFF0000)==(FLASH_BASE | Flag_Table.ull_vetofflen))&&(((temp)&0x0000FFFF)!=0X00000000))
                {
                        temp = ((temp)&0x0000FFFF)|(FLASH_BASE|ull_vetselect);               
                }
 楼主| 发给她更好fh 发表于 2024-1-31 20:30 | 显示全部楼层
最后补充一下boot表以及bin文件生成的知识点。
bin文件的生成需要设置一下 7297965ba3d7f3048f.png
 楼主| 发给她更好fh 发表于 2024-1-31 20:31 | 显示全部楼层
红色圈中文件需要对应你们工程目录中的.axf文件。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部