[STM32]

基于STM32 bootloader跳转APP的问题总结

[复制链接]
1838|4
手机看帖
扫描二维码
随时随地手机跟帖
dfgggf|  楼主 | 2023-5-25 19:30 | 显示全部楼层 |阅读模式
本帖最后由 dfgggf 于 2024-1-12 14:23 编辑

MCU:STM32F030CCT6
编程软件:MDK5
使用的ST库:Hal库


在编程的过程中,原本的方案是将bootloader与app结合到一个工程里,然后实现OTA功能。(ACU项目)
该方案的设计流程是
    1.将通过蓝牙将新的固件分页发送给MCU。(一页为128个字节,按照1个字节1个字节的传输)
    2.MCU将接收到的固件2k的数据后转存到Flash的指定地址(如0x8020000)内。(2K即2048个字节,即16*128即16页)
    3.当MCU接收到完整的固件后跳转到新的APP程序内。

出现的问题:
    1. 在将固件的数据存入Flash时出现报错,出现无法写入的问题
           (使用的函数:uint32_t FLASH_If_Write(__IO uint32_t* FlashAddress, uint64_t* Data ,uint16_t DataLength)  )
    2. 在写入Flash后,再次写入是报错。
    3. 该方案的弊端:bootloader成功跳转到APP后,存在一个问题:下一次更新APP时,无法直接覆盖当前的程序,否则会出现故障。
分析及处理:
    1. 存入Flash时报错,是由于写入的数据一定时64bit,或者要将Flash的地址对齐。
            此处采用了将写入的数据转成64bit的数据,因为FLASH_If_Write函数的Data 形参定义为64bit的。也是由于我不会地址对齐,网上查了一些,就是看不懂就          采用了这种方式。
     2. 第二个问题的出现,最大的原因就是我不懂Flash的读写的原理。经过网上的查找,结果就是Flash在写入已经存过数据的地址,需要先擦除这个地址存在的               Flash页,也就是说写入Flash,最好是一整页一整页的写入。否则擦除Flash页时会别擦除掉。
     3. 第三个问题,经过查证,bootloader与APP分开做成两个工程来进行编程。在测试时,可以通过烧录不同的起始地址来进行烧录,且将debug的Erase Sectors选           上即可。
96552646f3db91e683.png



第二个方案:bootloader与APP1分成两个工程
出现的问题:
       1. 按照上一个方案的第3点解决方案,将APP1与bootloader分成两个不同的起始地址(APP1烧录到Flash的APP1区域)进行烧录。boot loader工程内不对APP进             行操作,只负责跳转app1。此时bootloader是可以跳转到APP1内的。
                  此时通过将APP1烧录到新的Flash地址(APP2区域)后,bootloader负责将Flash的APP2区域的数据复制到Flash的APP1区域内,但不擦除Flash的APP2区             域的数据。此时bootloader也能跳转到APP1。
                  但此时,bootloader一旦对Flash的APP2区域的数据进行擦除,bootloader就无法正常跳转。
59077646f4072d82a6.png
       2. APP跳转到bootloader时无法让bootloader正常运行,会出现卡死现象。

分析及处理:
       1. 通过参考网上资料发现。当我将APP的起始地址如上图设定好之后,那么程序里的Flash地址就确定下来了,无论是烧录在哪个地址,当bootloader跳转到APP             时,MCU都会寻找到当初设定好的起始地址。所以一旦将APP的数据擦除后,就无法寻址,就会报硬件错误 (HardFault_Handler)。
                  处理办法:通过Keil设定APP的起始地址(如Flash的APP2区域),再通过烧录工具(STM32 ST-LINK Utility)对指定的Flash区域(Flash的APP1区域)进             行烧录。这样,bootloader在检测到Flash的APP1区域内有程序,则会将Flash的APP1区域的数据覆盖到Flash的APP2区域内,由于APP的起始地址就在Flash的             APP2区域内,那么bootloader就可以正常的跳转了。
       2. 在boot loader与APP相互跳转之前,需要将程序的中断都关闭了再进行跳转。
                  增加一下两条程序
                  //重置RCC
                  __HAL_RCC_PWR_CLK_DISABLE();
                  HAL_RCC_DeInit();







总结:在做boot跳转APP时需要注意的点:
         1. 需要算好boot的大小,和app的大小。因为在更新程序时,会同时存在3个工程的程序。
         2. 在写入Flash前需要对Flash页进行擦除。
         3. 设定程序的起始地址是boot需要跳转的地址。而不是存放的地址。在调试时需要测试boot对新程序进行更新,则通过别的方式进行指定地址的烧录。


在这次问题处理上,存在诸多的不足。对Flash原理的不了解,对OTA的实现方式不了解。总以为时擦除Flash导致boot无法跳转。


参考网址:
https://blog.csdn.net/JosephGodVim/article/details/127075018?spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-blog-2~default~ESQUERY~Rate-2-127075018-bbs-392135754.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-blog-2~default~ESQUERY~Rate-2-127075018-bbs-392135754.264^v3^pc_relevant_bbs_down_v2_default

重点:
53879646f46c482a14.png

20240112
问题更新:由bootloader跳转APP2 改为bootloader跳转APP1时,出现无法进入中断,导致程序无法运行。
问题原因:由于bootloader跳转到APP时,APP中的中断向量表初始化未进行修改,依然才有APP2地址的中断向量表,因此导致无法进入跳转。
问题出处: 1557365a0d9a21884f.png

修      改: 3355465a0d9d2f22f3.png

笔记:
1. 初始化中断向量表步骤
6001565a0da4992209.png
2.memcpy((void*)0x20000000, (void*)APPLICATION_ADDRESS1, 0xB8);中的0xB8为中断向量表的大小(最后一个地址)
2784265a0daa54d694.png
1148665a0dab43431a.png



使用特权

评论回复

相关帖子

nongshengjiang| | 2023-5-27 17:20 | 显示全部楼层
本帖最后由 nongshengjiang 于 2023-5-27 17:21 编辑

我用国产芯*的m0,官方给的IAP例子,上位机,太烂了,写一下死 ,问技术员。啥毛不懂,说什么APP部分不能用KEIL直接下载,还好自己摸出来,上位机也自己弄,下载顺滑得很。可是到后来的i2C速度太快,作为从机偶尔不响应,用的51单片都没这回事,问技术干脆不回复。我太难了

使用特权

评论回复
田舍郎| | 2023-5-27 18:37 | 显示全部楼层
及时总结是个好习惯

使用特权

评论回复
yangjiaxu| | 2023-5-31 09:21 | 显示全部楼层
跳转这块属实很重要的,因为这里涉及到的是指针,如果弄不好就是升级失败,反复重启之类的,而且还不好找原因

使用特权

评论回复
dfgggf|  楼主 | 2024-1-12 14:24 | 显示全部楼层
nongshengjiang 发表于 2023-5-27 17:20
我用国产芯*的m0,官方给的IAP例子,上位机,太烂了,写一下死 ,问技术员。啥毛不懂,说什么APP部分不能用 ...

不知道这个对你有没有帮助,我这也是花了好长时间摸索出来的,担心下次遇到了忘记怎么处理的了

使用特权

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

本版积分规则

2

主题

3

帖子

0

粉丝