ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

BootLoader 通用设计:固件怎么分区、怎么跳转、怎么防变砖

BootLoader 通用设计:固件怎么分区、怎么跳转、怎么防变砖 第一次做在线升级BootLoader 写好了APP 烧进去一跳转板子直接飞了进 HardFault。查半天才知道APP 的中断向量表还在默认地址MCU 发生中断时去 0 地址取向量取到的是 BootLoader 的向量跳转早把栈搬走了取到的栈顶是错的当场崩。BootLoader 的套路其实和芯片关系不大核心就四件事把 Flash 分区、上电决定跳不跳、跳的时候把向量表和栈摆正、升级过程断电能恢复。这篇把这套通用设计讲清楚。Flash 怎么分最基础的划分最前面一小块给 BootLoader 自己后面大块给 APP再留一小块参数区存升级标志、版本号、当前激活分区。想要升级不掉线最好搞双 APP 分区A、B 各一份。当前跑 A新固件写到 B写完整校验过再切到 B 激活万一 B 跑不起来还能回 A。这就是 A/B 双分区抗变砖的关键。上电先问一句跳还是不跳BootLoader 启动后先看参数区的「升级请求」标志。这个标志可能来自通信口收到升级指令、特定按键按住、或者某个引脚电平。有请求就进升级流程收数据、写 Flash、校验、切分区没有就直接跳 APP。voidboot_main(void){if(param_upgrade_requested())// 通信/按键/引脚置位{do_firmware_update();// 收包、写另一分区、校验}if(slot_is_valid(active_slot))// 当前激活分区完整{jump_to_app(app_addr(active_slot));}// 都不行停在 BootLoader等重新升级wait_for_update();}跳转向量表和栈必须摆正这是最容易翻车的地方。APP 不在 0 地址所以它的向量表也不在默认位置。跳转前要两件事把中断向量表偏移指到 APP 的起始地址Cortex-M 上写SCB-VTOR。否则所有中断还去 0 地址取向量取到 BootLoader 的栈早搬了必崩。把主栈指针 MSP 设成 APP 向量表第一项栈顶再跳到 APP 复位向量向量表第二项。typedefvoid(*app_entry_t)(void);voidjump_to_app(uint32_tapp_addr){uint32_tsp*(volatileuint32_t*)app_addr;// 栈顶uint32_tpc*(volatileuint32_t*)(app_addr4);// 复位向量// 关所有中断避免跳转过程被中断打断__disable_irq();// 向量表偏移到 APP 起始SCB-VTORapp_addr;// 设主栈指针__set_MSP(sp);// 跳过去((app_entry_t)pc)();}注意顺序先关中断再改 VTOR、设 MSP、跳。APP 起来后会重新初始化自己的中断和栈。BootLoader 里开过的定时器、DMA 等外设最好在跳转前关掉或复位别把状态留给 APP。升级过程断电能恢复才叫可靠双分区升级的标准流程收到新固件写到非当前的分区比如正跑 A写到 B。整包收完算校验CRC 或哈希不对就丢弃重来。校验通过更新参数区把「激活分区」指向 B并记录版本号。复位BootLoader 跳到 B。B 启动后自检确认能跑再清掉「升级中」标志。关键在第 3 步校验通过才切换激活标志。如果写到一半断电参数区还是指向旧的 A重启继续跑 A设备不砖。新固件哪怕残缺也没被激活。防刷非法固件验签如果设备会通过网络升级光校验不够得验签。思路发布时用私钥对固件哈希做签名BootLoader 里存公钥升级时验签名对得上才允许激活。这样别人没法刷篡改过的固件。非对称验签如 ECDSA在资源紧的 MCU 上要算一会儿但只在升级时跑一次能接受。回滚启动失败要能退加一个「启动失败计数」。APP 起来后在规定时间内比如喂一个「我还活着」的标志清计数如果连续几次启动都失败BootLoader 判定当前分区坏了回退到上一版本分区。这和用户层看门狗配合防止一个坏固件把设备锁死在重启循环里。10 个容易踩的坑跳转前没改 VTORAPP 中断全进 BootLoader 向量栈错直接 HardFault。跳转没先关中断跳转途中被中断打断上下文乱套。MSP 没设成 APP 的栈顶函数调用用到错栈立刻崩。APP 编译时 ROM 起始地址没改烧到 0 地址和 BootLoader 重叠。升级写完没校验就切激活残缺固件被激活变砖。写到一半断电参数区已切到新分区新固件不全起不来又没回退。跳转前没关外设定时器/DMAAPP 没预期这些在跑状态冲突。看门狗在升级擦写期间没喂长擦除触发复位升级中断变砖。验签只做哈希不做签名固件被篡改也照刷不误。忘了防回滚版本号旧固件能刷回去修好的漏洞又被打开。配套骨架一个抗变砖的 BootLoader1. Flash 分区BootLoader APP A APP B 参数区 2. 上电有升级请求 - 写非当前分区 - 整包校验 - 改激活标志 - 复位 3. 无请求校验当前分区有效 - 关中断 - 改 VTOR - 设 MSP - 跳 APP 4. 升级中掉电激活标志仍指向旧分区重启继续跑旧的 5. 验签防非法固件版本号防回滚 6. 启动失败计数 看门狗连续失败回退上一分区BootLoader 的价值不是「能升级」是「升级坏了还能回来」。分区隔开、校验门后再激活、断电能回到旧的这三道关少一道OTA 就是给现场埋雷。下一篇回到语言层C 的字节序、对齐和结构体 padding。你以为sizeof(struct)等于各成员之和编译器笑而不语。
返回列表