Lazy loaded image
🌉开发框架搭建
开发框架11-在线 IAP 升级应用
Words 3731Read Time 10 min
2024-10-15
2024-11-8
type
date
slug
category
icon
password
 

参考

STM32CubeMx开发之路—在线升级OTA讲解在线升级 IAP 的基础知识, 主要是针对 IAP 从原理分析分区划分, 到代码编写实验验证等过程阐述这一过程. 帮助大家加深对在线升级的认识。
 
BSP视频教程第22期:基于串口的XYZmodem文件传输协议实现,含上位机和下位机全开源,制作了一个Ymodem方式固件更新(2022-08-08)

FAQs

固件升级经验总结 鱼鹰谈单片机
APP程序怎么跳转到BootLoader程序?
  1. BootLoader 跳转到 APP 通过指针进行跳转
  1. APP 复位跳转到开始位置运行 BootLoader(通过指针跳转不可行)。关于复位可以参考这里
    1. 内核复位:只复位内核,不复位外设(CMSIS-DAP是内核复位,KEIL 调试)
      1. 系统复位:芯片内核和外设均复位,如同按了复位按键
        1. 上电复位:和系统复位、按键复位一致,但需要增加额外硬件
      APP程序和BootLoader之间是否会互相影响 ⭐⭐⭐
      1. 系统复位无需考虑外设影响
      1. 内核复位需考虑
        1. Bootloder 和 app 设置了不同的串口配置
          1. APP 在配置串口之前,可以先复位串口,再进行配置
          2. 让 BootLoade 程序在使用串口之前先进行复位
          3. XXX_DeInit()
        2. APP 跳转到 BootLoader,导致控制加热程序未控制,一定要做好切换的状态保护
      APP和BootLoader之间如何传递参数?
      1. Bootloader 增加冷启动过程(时间短暂)判断升级命令,单片机中暂时没有APP程序,也能够实现固件升级过程。是一种强制升级方法。
      1. App 决定升级,需要在进入BootLoader之前给它传递一个参数,告诉它,这次复位需要升级,不能直接跳到APP中运行。
        1. Flash中(擦除一个扇区,保存地址放在APP区还是BootLoader区)
        2. 后备域保存参数(需电池)
        3. 外部的FLASH空间,支持字节编程(具备这种芯片,并增加驱动代码)
        4. RAM传参(同名变量不行,指针直接操作)一旦使用完这个参数,必须清零
      固件更新一到一半,因为某种原因失败了(通信错误、掉电),该如何处理?
      1. 保存两份APP程序,升级不成功,恢复成原来的系统
      1. BootLoader 程序判断是否升级成功,检查bin文件的大小。APP需用掉电不丢失的参数来保存是否升级成功。
      1. 跳过前8个字节,写入APP程序。最后再对前面8个字节写入,这样一来,就保证了程序的完整性,如果说你中途数据中断了(掉电或上位机中断),那么前面那8个字节肯定不会写入,也就无法正常进入APP中运行了。
      如何确保更新的APP是你需要的APP,而不是别的一个APP
      1. 编写程序,增加标志,程序标志放在向量表的后面。当BootLoader在写前面8个字节前,只要再判断这个地址的标志位是否正确即可。
      1. 在 bin 文件中加几个字节标着文件的特殊性,测试阶段,更新频繁。
      NVIC_SetVectorTable 偏移值设置注意事项
      注意1:根据 boot bin文件大小,要扩展到0x200倍数,比如21633字节,设置为0x5500,就不行,跳到APP中运行会出现异常。
      函数内部
      SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80);
      notion image
      7:28 保存偏移值,因此&0x1FFFFF80
      ARM Cortex-M3权威指南(中文) P113
      ARM Cortex-M3权威指南(中文) P113
      打开工程的启动文件,有60个普通中断,另外有16个系统中断,一起是74个中断,由于74大于2的6次方(也就是64,),所以幂向上加1也就是2的7次方,即128,然后一个地址占用四个字节,所以得出128*4=512,也就是我苦苦寻觅的0x200。
       
      1. 方便扩充中断向量表
        1. 解释:比如现在需要48个中断向量那我就分配它48*4个字节空间,但是以后需要49个捏?考虑到拓展性所以还是多留空间的好
      1. 方便编程时的 FLASH 擦写
        1. 解释:给出一个 Offset 的相对固定的值,方便程序员在编程时提高效率,试想如果设置一个非常复杂的 boot 长度地址,每次修改都会浪费不少时间
       
      实战技能分享,一劳永逸的解决BOOT跳转APP失败问题,含MDK AC5,AC6和IAR,同时制作了一个视频操作说明 https://www.armbbs.cn/forum.php?mod=viewthread&tid=109595
      notion image
      1. 如何设置 BOOT 和 APP 都使用的变量,防止编译器优化
       

      一、基础知识

      1.1 上电启动

      notion image
      notion image
      1. M3,M4内核芯片上电复位后,要固定从 0x0000 0000 地址读取中断向量表,获取复位中断服务程序的入口地址后,进入复位中断服务程序,其中0x0000 0000是栈顶地址0x0000 0004存的是复位中断服务程序地址
        1. notion image
          notion image
      1. 既然ARM规定了M3,M4内核要从地址0x0000 0000读取中断向量表,而STM32设置Flash地址到0x0800 0000怎么办?STM32支持了个内存重映射功能,将地址0x0800 0000开始的内容重映射到首地址0x0000 0000中,这样就解决了从0x0000 0000读取中断向量表的问题。
        1. 图示,以STM32F407IGT6为例,0x0000 0000和0x0800 0000开始的程序对比:
          notion image
          你怎么保证0x08000 0000首地址存的就是中断向量表,我们不可以随意设置吗?
          MDK对应的xxx.sct分散加载里面通过下面这句将这个RESET段放在了0x0800 0000优先存储。
          • 对于M3、M4内核,不能更改 IROM1 地址,将前面扇区当作参数存储,这样程序就会找不到复位中断函数的运行地址。
            • notion image
          • 一旦程序开始运行后,我们就可以随意设置中断向量表的位置了,中断向量表存到内部SRAM,我们就可以操作寄存器SCB->VTOR 重新安排,然后将 0x0800 0000 的内容复制到设置的地址内即可。
          既然设置到0x0800 0000这么麻烦,为什么不直接使用0x0000 0000?
          这是因为STM32不仅可以从内部Flash启动,还可以从系统存储器(可以实现串口ISP,USB DFU等程序下载方式,这个程序是ST固化好的程序代码)和从内部SRAM启动,
          我们将内部Flash安排到0x0000 0000显然是不行的。这样会导致系统存储器或者内部SRAM无法重映射到0x0000 0000了。
          notion image
          了解了M3和M4,M7是怎么个执行情况呢?
          M7内核芯片比较灵活了,改变了固定从0x0000 0000地址读取中断向量表的问题,以STM32H7为例,可以从 0x0000 0000 到 0x3FFF 0000 所有地址进行启动。
          专门安排了个选项字节来配置。
          notion image
          H7里面没有重映射了,它的首地址0x0000 0000安排给ITCM RAM空间使用了。

      1.2 跳转配置

      1. 将APP程序加载到支持运行程序的 Flash 或者 RAM中
      1. 复位 RCC 时钟
      1. 复位所有开启的外设
      1. 关闭滴答(在复位 RCC 时钟之后)
      1. 关闭所有中断
      1. 设置跳转PC、SP和 Control 寄存器
      1. 裸机和RTOS跳转的异同
       
      notion image
      notion image

      1.3 APP 程序问题

      1. APP 程序入口依然是复位中断服务程序。
      1. 注意设置 APP 的中断向量表地址。
      1. BOOT 占用的RAM空间可以全部被APP使用。
      1. APP程序版本号和程序完整性问题(CRC校验或者MD5校验实现)
       
      1. 固件加密。
      1. APP调回到BOOT,使用 NVIC_SystemReset 软件复位。

      1.4 调试下载

      1. 大家仅需将BOOT下载进去后,就可以传统方式调试APP的程序。
      1. APP或者BOOT程序排查问题。

      1.5 开源玩法

      stm32-iap-uart-boot
      havenxieUpdated Mar 12, 2025
      notion image

      二、基于 NAND、eMMC、SD 卡和 U 盘的 bootloader 实战

       
      notion image
       

      2.1 APP 生成说明

      1. 修改中断向量表偏移
        1. IROM 配置对应一致

        2.2 程序完整性检测 - CRC校验

        1. 拷贝位置
        1. hex 文件转化位 bin 文件
        1. 获取 bin 文件大小并显示
        1. 在bin文件末尾添加CRC校验码
          1. -crop 0 %indexdx% 从头到尾
          2. -STM32_Little_Endian 针对硬件CRC小端
          3. %indexdx% 生成CRC添加位置
        运行日志

        2.3 APP 程序版本控制

        startup_stm32f40_41xxx.s 中保留位可以存储版本号,用于实现版本控制。
        startup_stm32f40_41xxx.s
        startup_stm32f40_41xxx.s
        打开 hex 文件,0x02010000 小端序存储版本号。
        notion image

        2.4 NAND、eMMC、SD 卡和 U 盘驱动

        1. 16GB 以上,大于 32GB,使用 exFAT
        1. 消费机和工业级
        CPU Flash 使用高版本 HAL 库

        三、AES 加密实战

        notion image
        增加了临时 APP 分区,解密验证有效在复制到APP运行,即使复制过程掉电了。还可以运行临时APP,起到双备份的作用。
         

        四、CANFD,I2C,SPI和串口方式更新APP

         
        协议说明
        notion image
         
         

        五、升级案例

        IAP升级程序使用补充说明

        Xmodem协议

        notion image

        内存分区(最简化的分区方式,不带备份区)

        notion image

        代码编写

        Bootloader

        • 发送USART数据和printf重定向
        • Flash的读写
        • 程序跳转指令,可以参考如下代码:

        APP

        • 发送USART数据和printf重定向
        • Flash的读写
        • 串口的DMA收发
        • YModem协议相关
         

        代码烧写

        bootloader 烧写

        bootloader 烧写
        bootloader 烧写

        APP 烧写

        notion image
        notion image
         
         
        新单兵IAP升级流程
        • PC APP需过滤数据,目前PC APP无法调整,待网络通讯调整后设计
        • WAN口设计增加
         
        上一篇
        开发框架10-设备低功耗框架
        下一篇
        常用接口协议-Modbus TCP 协议模拟测试

        Comments
        Loading...