打印
[应用相关]

STM32F4单片机bootloader及在线升级IAP基本原理

[复制链接]
手机看帖
扫描二维码
随时随地手机跟帖
41

使用特权

评论回复
42
发给她更好fh|  楼主 | 2023-9-30 23:56 | 只看该作者
单区模式,用自定义的BootLoader代替原厂的,操作方便,通过正常逻辑代码中的外设进行指令级别的跳转无需配置boot引脚电平。缺点是无备份功能,在大容量flash单片机中有些空间未被使用,不用来做程序旧版本保存太浪费。

使用特权

评论回复
43
发给她更好fh|  楼主 | 2023-9-30 23:56 | 只看该作者
自定义bootloader+app1+app2、

使用特权

评论回复
44
发给她更好fh|  楼主 | 2023-9-30 23:57 | 只看该作者
双区模式,代码备份功能具备,当然对应的对于小容量产品就显的比较占用空间。双区模式又根据APP区的用法分为两种:一种是APP1只作为运行区域的代码,APP2只做备份区。另外一种是,APP1和APP2均可作为运行区域的代码区,随意切换,APP1运行时APP2区便作为备份区。

使用特权

评论回复
45
发给她更好fh|  楼主 | 2023-9-30 23:57 | 只看该作者
第一种比较好实现,缺点就是每次升级都需要做一次代码的对调。第二种比较难以实现,因为flash中中断向量表地址偏移是固定的以及中断向量地址也是固定的,每一次编译后地址不会更改。简单点说就是同一份代码更改向量表偏移地址,生成的flash烧写文件BIN文件不一样,因此每次升级需要在单片机中更改源码文件。

使用特权

评论回复
46
发给她更好fh|  楼主 | 2023-9-30 23:57 | 只看该作者
iap升级实例
这里以我测试用的双区模式为例,使用一个标志位进行APP1和APP2区域的切换。只讲基本过程,具体的串口升级协议没有添加,大家仅供参考。

使用特权

评论回复
47
发给她更好fh|  楼主 | 2023-9-30 23:57 | 只看该作者
flash分区

使用特权

评论回复
48
发给她更好fh|  楼主 | 2023-9-30 23:57 | 只看该作者
首先需要根据flash的情况进行分区确定每个扇区的功能,这次采用双BootLoader的设置,使用BootLoader1跳过sector1的分区,直接引导至BootLoader2,这样做的好处是把标志位放在了一个较小的分区,尽量减少空间浪费,正常Flag标志也存不了几个量。

使用特权

评论回复
49
发给她更好fh|  楼主 | 2023-9-30 23:57 | 只看该作者
BootLoader2占空扇区2-4,大小96k。sector5-7存储APP1,sector8-10存储APP2.最后sector11预留使用。

使用特权

评论回复
50
发给她更好fh|  楼主 | 2023-9-30 23:57 | 只看该作者
标志位区内容、

使用特权

评论回复
51
发给她更好fh|  楼主 | 2023-9-30 23:58 | 只看该作者
目前标志位存两个变量,一个是用于跳转的flag当值为0x11时BootLoader2引导跳转至APP1区,当值为0x22时跳转至APP2区,其它值不跳转,,vetOffLen存储向量表偏移值,APP1对应0x20000,APP2对应0x40000。

使用特权

评论回复
52
发给她更好fh|  楼主 | 2023-9-30 23:58 | 只看该作者
升级方案设计
升级方案如下图所示

使用特权

评论回复
53
发给她更好fh|  楼主 | 2023-9-30 23:58 | 只看该作者
BootLoader设计
然后是BootLoader设计,BootLoader1的功能就是引导跳转至BootLoader2区,跳过flag区。

使用特权

评论回复
54
发给她更好fh|  楼主 | 2023-9-30 23:58 | 只看该作者

使用特权

评论回复
55
发给她更好fh|  楼主 | 2023-9-30 23:58 | 只看该作者
源码如下:

int main(void)
{

        while(1)
        {
                        if(((*(vu32*)(0x08008000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
                        {         
                                iap_load_app(0x08008000);//执行FLASH APP代码
                        }
        }  
}

使用特权

评论回复
56
发给她更好fh|  楼主 | 2023-9-30 23:58 | 只看该作者
BootLoader2的方案也很简单根据跳转标志跳转至APP1还是APP2,否则停留在当前BootLoader2中,同时进行将相对应的的中断向量表偏移长度写进flag区中。

使用特权

评论回复
57
发给她更好fh|  楼主 | 2023-9-30 23:58 | 只看该作者

使用特权

评论回复
58
发给她更好fh|  楼主 | 2023-9-30 23:58 | 只看该作者
源码:
#include <string.h>
#include "stm32_flash.h"  
#include "App_Init.h"

int main(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
        Sysint();//系统初始化
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
  /* GPIO初始化 */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_Init(GPIOF, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_Init(GPIOF, &GPIO_InitStructure);
       
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
  /* GPIO初始化 */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_Init(GPIOE, &GPIO_InitStructure);       
  GPIO_SetBits(GPIOF, GPIO_Pin_9);
  GPIO_ResetBits(GPIOF, GPIO_Pin_10);       
       
        while(1)
        {
                delay_ms(100);               
                ReadFlagTable(&Flag_Table);//将标志位的表读       
       
                if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0)
                {
                                Flag_Table.ull_updaterun_flag =0x00000011;//写入APP1的向量表偏移长度               
                }
                else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)
                {
                                Flag_Table.ull_updaterun_flag =0x00000022;//写入APP1的向量表偏移长度               
                }               
                switch (Flag_Table.ull_updaterun_flag)
                                {
                                        case 0x00000011://跳转APP1
                                                                {
                                                                        if(((*(vu32*)(STM32_FLASH_APP1_BASE+4))&0xFF000000)==0x08000000)//判断是否为Flash区域
                                                                        {       
                                                                                        if(Flag_Table.ull_vetofflen!=0x20000)
                                                                                        {
                                                                                                Flag_Table.ull_vetofflen =0x20000;//写入APP1的向量表偏移长度
                                                                                                WriteFlagTable(&Flag_Table);//将标志位的表写入       
                                                                                        }                                                                                               
                                                                                iap_load_app(STM32_FLASH_APP1_BASE);//程序跳转
                                                                        }
                                                       
                                                                }
                                                break;
                                        case 0x00000022://跳转APP2
                                                                {
                                                                        if(((*(vu32*)(STM32_FLASH_APP2_BASE+4))&0xFF000000)==0x08000000)//判断是否为Flash区域
                                                                        {         
                                                                                        if(Flag_Table.ull_vetofflen!=0x40000)
                                                                                        {
                                                                                                Flag_Table.ull_vetofflen =0x40000;//写入APP1的向量表偏移长度
                                                                                                WriteFlagTable(&Flag_Table);//将标志位的表写入       
                                                                                        }                                                               
                                                                                iap_load_app(STM32_FLASH_APP2_BASE);//程序跳转
                                                                        }               
                                                                       
                                                                }                                               
                                                break;
                                        default://默认在当前BootLoader中
                                                                {

                                                                        GPIO_ToggleBits(GPIOF, GPIO_Pin_9);
                                                                        GPIO_ToggleBits(GPIOF, GPIO_Pin_10);                                                                       
                                                                }
                                               
                                                break;
                                }
        }

}

使用特权

评论回复
59
发给她更好fh|  楼主 | 2023-9-30 23:59 | 只看该作者
这个增加了一个按键选择功能,帮助测试APP1和APP2区代码的跳转。

使用特权

评论回复
60
发给她更好fh|  楼主 | 2023-9-30 23:59 | 只看该作者
APP中升级处理
讲APP中升级处理前,先将一下APP区代码的结构,如下所示,不同分区中每一份代码都要包含三部分,第一部分中断向量表,表中存储了各个中断函数的地址;第二部分为中断函数;第三部分为主逻辑代码,可理解为main函数。正常中断的执行过程是:发生中断,单片机查询中断向量表,通过中断向量表找到中断函数的地址,执行中断函数后跳回源main函数中。每一APP代码只能使用自己中断向量表以及中断函数,因此有一个向量表偏移长度,让单片机能够通过相对于0X0800 0000的偏移找到对应APP代码的中断函数。
————————————————
版权声明:本文为CSDN博主「蜗牛Jay」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43058521/article/details/125355343

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则