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

[复制链接]
6537|87
 楼主| 发给她更好fh 发表于 2023-9-30 23:54 | 显示全部楼层
原厂BootLoader在0x1fff 0000 - 0x1fff 77ff的stm32内部存储器内,大小为30K。通过boot引脚设置 boot0= 1;boot1= 0即可进入。
 楼主| 发给她更好fh 发表于 2023-9-30 23:54 | 显示全部楼层
 楼主| 发给她更好fh 发表于 2023-9-30 23:54 | 显示全部楼层
STM32F407支持串口、can、USB进行自举升级程序。具体升级协议可自行参考stm32F407中文参考手册。原厂bootloader与flash的组合构成一种基本的升级模式,但会覆盖源程序。
 楼主| 发给她更好fh 发表于 2023-9-30 23:54 | 显示全部楼层
自定义BootLoader
此部分位于用户操作的flash区域,定义为执行用户逻辑程序APP前的一段引导。
 楼主| 发给她更好fh 发表于 2023-9-30 23:55 | 显示全部楼层
 楼主| 发给她更好fh 发表于 2023-9-30 23:55 | 显示全部楼层

这部分可以引导具体执行从flash中哪个地址开始的程序。但基本流程是烧写两短代码BootLoader段和APP段。
 楼主| 发给她更好fh 发表于 2023-9-30 23:55 | 显示全部楼层
跳转代码很简单,执行一个函数即可,如下:
 楼主| 发给她更好fh 发表于 2023-9-30 23:55 | 显示全部楼层
iapfun jump2app; //定义函数指针
//跳转到应用程序段
//appxaddr:用户代码起始地址.
void iap_load_app(u32 appxaddr)
{
        if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)        //检查栈顶地址是否合法.
        {
                jump2app=(iapfun)*(vu32*)(appxaddr+4);                //用户代码区第二个字为程序开始地址(复位地址)               
                MSR_MSP(*(vu32*)appxaddr);                                        //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
                jump2app();                                                                        //跳转到APP.
        }
}       
 楼主| 发给她更好fh 发表于 2023-9-30 23:55 | 显示全部楼层
总的来说是两个操作,一个是将复位函数地址赋值给函数指针,设置堆栈栈顶的地址,第二个是执行函数指针指向的复位函数的地址。
flash源码文件的正确执行就是要正确设置PC和堆栈指针。PC指针指向当前运行的函数,如复位函数;主堆栈指针MSP与函数的嵌套有关,没有这个函数之间的嵌套跳转无法实现。
 楼主| 发给她更好fh 发表于 2023-9-30 23:55 | 显示全部楼层
具体使用可以这样,根据不同标志位跳转不同flash区域的代码,起到了一个引导加载不同程序的作用。

 楼主| 发给她更好fh 发表于 2023-9-30 23:55 | 显示全部楼层
                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中                                               
                                                break;
                                }
 楼主| 发给她更好fh 发表于 2023-9-30 23:55 | 显示全部楼层
iap升级
单片机程序的烧录除了使用烧写器下载(ICP)和原厂BootLoader通过串口等外设烧录(ISP)外便是在源程序正常运行的过程中进行修改内部FLASH进行升级操作(IAP),如果对接IAP的外设是无线网模块则可实现远程空中升级(OTA)。
 楼主| 发给她更好fh 发表于 2023-9-30 23:55 | 显示全部楼层
IAP升级意味着需要在程序运行过程中进行升级跳转,无需操作boot引脚,实现更加自由灵活的升级方式。
 楼主| 发给她更好fh 发表于 2023-9-30 23:56 | 显示全部楼层
基本原理
IAP升级的基本原理就是流程图的后半段,通过BootLoader确定是否升级,升级的话去读写flash将代码写进入,不升级就跳转运行正常逻辑代码。
 楼主| 发给她更好fh 发表于 2023-9-30 23:56 | 显示全部楼层
 楼主| 发给她更好fh 发表于 2023-9-30 23:56 | 显示全部楼层
升级模式
升级模式大致分为以下几种更多的均在此基础上进行的演变。
 楼主| 发给她更好fh 发表于 2023-9-30 23:56 | 显示全部楼层
原厂bootloader+app
 楼主| 发给她更好fh 发表于 2023-9-30 23:56 | 显示全部楼层
 楼主| 发给她更好fh 发表于 2023-9-30 23:56 | 显示全部楼层
此部分常用的名字叫做ISP自举下载。常规项操作,使用不方便需要操作外部boot的电平高低,基本不推荐。

 楼主| 发给她更好fh 发表于 2023-9-30 23:56 | 显示全部楼层
、自定义bootloader+app
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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