这个 BootLoader 系列写到后面,内容已经不只是“怎么从 BootLoader 跳到 APP”了。

刚开始做的时候,大家一般关心的是三个问题:APP 放到哪里、BootLoader 怎么跳过去、串口能不能把固件写进去。等真正放到项目里,就会发现问题变多了:升级中途断电怎么办,Flash 擦错区域怎么办,旧版本能不能覆盖新版本,现场升级失败后还能不能恢复,上位机怎么把错误说清楚。

所以这篇文章不再单独讲某一个功能,而是把前面 12 篇按一条完整路线串起来。你可以把它当成这个专栏的入口:刚入门的按顺序看,已经在做项目的可以直接跳到对应章节。

先说阅读顺序

如果你是第一次做 STM32 BootLoader,我建议不要一上来就看 A/B 分区、签名校验这些内容。先把最小闭环跑通,比什么都重要。

比较稳的顺序是:

  1. 先让 BootLoader 能从 0x08000000 启动,并能跳到 APP。
  2. 再把 APP 的链接地址、中断向量表和升级标志处理清楚。
  3. 然后做串口 YMODEM,把固件真正写进 Flash。
  4. 接着补 Flash 擦写适配,避免不同芯片之间直接套代码。
  5. 再做固件头、CRC、版本号和断电恢复。
  6. 最后再考虑 A/B 分区、签名校验、上位机工具和量产排查。

BootLoader 很容易一开始写得很热闹,但只要地址、分区、校验、记录这几件事没理顺,后面问题都会绕回来。

第一部分:先把 APP 跳转跑通

第一篇是整个系列的入口:

《STM32 BootLoader 入门教程:从原理到 APP 跳转实现》

这篇主要讲 BootLoader 为什么要放在 0x08000000,APP 为什么要偏移,以及跳转前要设置哪些东西。

这里最容易误解的一点是:BootLoader 不是随便放一个 Flash 地址就能启动。STM32 上电后会从 Flash 起始地址取栈顶和复位入口,所以真正接管启动流程的程序应该放在 0x08000000。APP 放到后面以后,APP 工程的链接地址也要跟着改,中断向量表也要重新指向 APP 自己的位置。

如果这一步没做对,后面串口升级、网口升级、A/B 分区都没有意义。因为固件就算写进去了,也可能一跳转就 HardFault。

第二篇接着解决 APP 偏移后的工程配置问题:

《STM32 BootLoader 实战(二):APP 偏移配置、固件校验与升级标志设计》

这一篇更偏工程落地。比如 Keil、CubeIDE、IAR 里 APP 起始地址怎么改,BootLoader 怎么判断 APP 是否有效,升级标志放在哪里比较合适,固件头为什么不能直接盖在 APP 向量表上。

这两篇看完,至少要能做到:BootLoader 上电运行,检查 APP 地址合法,然后稳定跳到 APP,APP 的串口、定时器中断也能正常工作。

第二部分:让固件真的能升级进去

第三篇开始进入升级流程:

《STM32 BootLoader 实战(三):串口 YMODEM 升级 APP 固件》

我个人比较建议先做串口 YMODEM,再做网口升级。原因很简单:串口链路直观,日志好抓,问题也容易定位。先把接收固件、擦除 APP 区、写 Flash、校验、跳转这一套流程跑通,后面换成 TCP 或其他通信方式就不会乱。

串口升级这部分要特别注意 YMODEM 第 0 包。里面一般带文件名和文件大小,BootLoader 不能只顾着收数据,还要判断文件大小是不是超过 APP 分区,起始地址是不是正确,擦写范围有没有碰到 BootLoader 自己。

第四篇是 Flash 适配:

《STM32 BootLoader 实战(四):F103、F407、G473 的 Flash 擦写适配与分区保护》

这篇很关键。F103 是 Page 擦写,F407 是不等大小 Sector,G473 又要考虑 Bank 和 Page。如果直接把 F103 的擦写思路搬到 F407 上,很容易把分区边界算错。

BootLoader 里最怕的不是写失败,而是写到了不该写的地方。尤其是 BootLoader 区、参数区、升级记录区,一旦擦错,现场恢复会很麻烦。

第五篇讲 W5500 网口升级:

《STM32 BootLoader 实战(五):基于 W5500 网口的 YMODEM 升级 APP 固件》

网口升级适合现场维护,但它比串口多一个坑:TCP 是字节流,一次 send 不等于下位机一次 recv。所以 YMODEM over TCP 不能假设每次都刚好收到一个完整包,要在接收缓存里按协议重新拼包。

如果串口版已经写得比较干净,网口版其实就是把“读一个字节”的接口从串口换成 TCP 缓存。这个思路比重新写一套网络升级协议更稳。

第三部分:让升级过程更可靠

能升级,不代表能放心用。

第六篇讲固件头、CRC、版本号和防回滚:

《STM32 BootLoader 实战(六):APP 固件头、CRC 校验、版本号与防回滚设计》

我不建议 BootLoader 直接接收一个裸 app.bin 就往 Flash 里写。更稳的方式是上位机先把固件打包,包里带上固件头、APP 大小、目标芯片、目标板卡、版本号、CRC 等信息。BootLoader 收到以后先判断,再决定是否擦写。

这里的重点不是多加几个字段,而是让 BootLoader 知道“这份固件是不是给我用的”“是不是完整的”“版本是否允许升级”。不然现场拿错固件,BootLoader 也照样写进去,后面就很难解释了。

第七篇讲状态机、错误码和异常恢复:

《STM32 BootLoader 实战(七):升级状态机、错误码与异常恢复设计》

Demo 代码里经常是一条流程走到底,但项目里不行。升级过程中可能超时、断线、取消、重复升级、Flash 写失败、CRC 失败,也可能写到一半断电。

所以 BootLoader 里最好有清晰的状态机。比如等待升级、接收固件、擦除 Flash、写入 Flash、校验固件、写升级记录、准备跳转。每个阶段失败,都应该有对应错误码。这样上位机和现场人员才能知道问题出在哪里。

第八篇讲 A/B 双分区:

《STM32 BootLoader 实战(八):A/B 双分区升级、启动选择与失败回滚设计》

单 APP 分区最大的问题是:一旦开始擦 APP,旧程序就没了。这个时候如果断电或者写入失败,设备只能留在 BootLoader 里等重新升级。

A/B 双分区解决的是这个问题。设备当前运行 A 区,就把新固件写到 B 区;B 区校验通过后,下一次启动先试运行 B。APP 运行起来以后再确认成功。如果新 APP 起不来,BootLoader 还能回到旧分区。

当然,A/B 也不是所有项目都适合。Flash 太小的芯片,比如一些 F103C8T6 项目,做完整 A/B 会比较吃紧。这个时候可以考虑“下载缓存区 + 固定 APP 区”的折中方案。

第四部分:产品化以后要考虑安全和工具

第九篇讲固件加密和签名:

《STM32 BootLoader 实战(九):固件加密、签名校验与防篡改设计》

CRC 只能说明传输过程中数据有没有错,不能说明固件是不是你发的。别人改了固件以后重新算一个 CRC,BootLoader 仍然可能认为它是正确的。

所以产品阶段要区分几个概念:CRC 负责完整性,签名负责防篡改和防伪造,加密负责不让别人直接看懂固件内容,防回滚则要靠版本号和升级记录区。不同项目安全要求不一样,不一定都要上最高规格,但思路要分清。

第十篇讲上位机联调:

《STM32 BootLoader 实战(十):上位机升级工具联调流程与问题定位》

很多人写 BootLoader 时只盯着单片机代码,最后现场升级不好用,其实问题出在上位机。一个能交付的升级工具,不应该只显示一个进度条。

它至少要显示当前阶段、当前包号、传输进度、设备返回的错误码、升级前版本、升级后版本和日志。尤其是现场维护时,日志比界面好不好看更重要。

第十一篇讲工程移植:

《STM32 BootLoader 实战(十一):工程移植模板、链接脚本与多芯片适配》

BootLoader 在一个芯片上跑通,不代表换个芯片还能顺利跑。地址、Flash 擦写方式、分区大小、链接脚本、VTOR、打包工具参数,都可能跟着变。

这篇主要是把工程结构整理出来:分区表集中定义,Flash 驱动按芯片适配,通信通道统一接口,BootLoader 和 APP 的地址配置保持一致。做完这些,后面从 F103 移到 F407、G473,会少踩很多坑。

第十二篇是排查和交付清单:

《STM32 BootLoader 实战(十二):常见问题排查、量产测试与现场维护清单》

这一篇不是讲新功能,而是讲怎么把问题查清楚。比如 APP 跳转失败怎么查,YMODEM 第 0 包失败怎么查,Flash 写入失败怎么查,CRC 失败怎么查,断电恢复异常怎么查。

BootLoader 最后能不能交付,靠的不是某一段代码写得多漂亮,而是出了问题能不能快速定位。

按需求怎么跳读

如果你只是想做一个最小 BootLoader,先看第一篇和第二篇。把 APP 跳转和中断向量表处理好就行,不要急着加复杂功能。

如果你想做串口升级,看第一篇到第四篇,再补第七篇和第十篇。串口升级跑通以后,一定要把错误码和上位机日志加上。

如果你想做 W5500 网口升级,先把第三篇串口 YMODEM 看懂,再看第五篇。网口部分重点不是 W5500 初始化本身,而是 TCP 字节流怎么适配 YMODEM。

如果你关心升级可靠性,重点看第六篇、第七篇、第八篇和第十二篇。这里面讲的是固件头、升级记录、断电恢复、A/B 回滚和排查清单。

如果你准备做产品级升级,再看第九篇、第十篇、第十一篇。签名校验、上位机工具和工程模板,都是项目后期绕不开的内容。

这个系列里最容易踩的几个坑

第一个坑,是只改 BootLoader,不改 APP 链接地址。APP 如果还按 0x08000000 链接,BootLoader 跳过去以后很容易跑飞。

第二个坑,是忘了设置 APP 的中断向量表。主循环能跑,不代表中断也能跑。很多“跳转成功但串口中断不进”的问题,都在这里。

第三个坑,是固件头直接写到 APP 起始地址。APP 起始地址放的是初始栈顶和 Reset_Handler,不能随便覆盖。

第四个坑,是不同 STM32 的 Flash 擦写方式混用。F103、F407、G473 的 Flash 组织方式不一样,分区保护一定要按芯片单独适配。

第五个坑,是上位机显示 100% 就认为升级成功。传输完成只是第一步,BootLoader 校验通过、写记录成功、设备复位后 APP 上报新版本,这才算真正闭环。

第六个坑,是没有做断电测试。尤其是擦 APP 时断电、写 APP 时断电、写有效标志时断电、A/B 分区 PENDING 阶段断电,都要单独测。

最后说两句

BootLoader 看起来只是启动和升级,但真正做完整以后,它其实是一套小型系统工程。

我的建议是按阶段推进:先跳转,再升级;先串口,再网口;先 CRC,再版本管理;先单分区跑稳,再考虑 A/B;先能定位问题,再谈量产交付。

这个系列也是按这个思路写的。前面几篇解决“能不能跑”,中间几篇解决“稳不稳定”,后面几篇解决“能不能用于产品和现场维护”。

如果你正在做 STM32 在线升级,不建议一开始就追求大而全。先把最小闭环跑通,每一步都能验证,再往上加功能,BootLoader 会好维护得多。

文章标签

STM32、BootLoader、IAP、YMODEM、W5500、Flash 分区、固件升级、嵌入式、单片机

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐