4、Bootloader在A/B切换中的角色
Bootloader,说白了就是车机启动时的第一个程序。它小,但权力大。整个A/B分区能不能切成功,Bootloader说了算。
我经常跟团队里的小朋友讲:Bootloader是OTA升级的守门员。它要是出了问题,车机可能就变砖了。今天咱们就聊聊,这个守门员到底怎么干活。
Bootloader的启动流程
车机上电后,Bootloader的启动流程大致分四步。每一步我都踩过坑,咱们一个一个说。
- 硬件初始化:时钟、DDR、存储控制器,这些得先跑起来。没有DDR,代码都没地方放。
- 加载Bootloader自身:从Flash里把Bootloader代码读到DDR里。嗯,这里要注意,Flash驱动必须稳定。我遇到过Flash初始化时序不对,导致读出来的数据全是0xFF,车机直接死在那。
- 读取分区状态:去metadata区域查一下,当前哪个分区是活跃的,哪个是待升级的。
- 跳转到活跃分区:把控制权交给活跃分区的启动代码。
你看,第三步是关键。Bootloader得知道往哪跳。
如何判断当前活跃分区
判断活跃分区,靠的是metadata。metadata是一小块存储区域,通常放在Flash的固定位置。里面记录着:
- 当前活跃分区编号(slot A 或 slot B)
- 每个分区的尝试启动次数(retry count)
- 分区状态(成功、失败、待升级)
我个人习惯用这样的数据结构:
typedef struct {
uint8_t active_slot; // 0: Slot A, 1: Slot B
uint8_t retry_count[2]; // 每个分区的尝试次数
uint8_t slot_status[2]; // 0: 正常, 1: 待回滚, 2: 损坏
uint32_t crc32; // 校验
} BootMetadata;
Bootloader启动时,先读metadata。如果active_slot指向Slot A,那就从Slot A启动。就这么简单。
但这里有个坑:metadata必须防写坏。OTA升级过程中如果突然断电,metadata可能只写了一半。我建议用双备份,或者带CRC校验。我曾经在项目里没做CRC,结果metadata被写坏,Bootloader读到一个非法值,直接不知道该启动哪个分区,车机就卡在启动界面了。
Bootloader的故障恢复机制
Bootloader不能只负责启动,它还得会处理故障。说白了,就是启动失败了怎么办。
常见的故障恢复机制有三种:
| 机制 | 原理 | 我遇到的坑 |
|---|---|---|
| 尝试计数回滚 | 每次启动尝试,retry_count减1。减到0就切到另一个分区 | retry_count初始值设太大,导致反复尝试失败分区,用户等很久 |
| 看门狗复位 | 如果启动超时,看门狗复位,Bootloader重新选择分区 | 看门狗时间设太短,正常启动也被复位了 |
| 用户强制回滚 | 用户长按某个按键,Bootloader检测到后强制切回旧分区 | 按键检测逻辑写在了DDR初始化之后,结果DDR坏了,按键检测根本跑不到 |
我个人最推荐的是尝试计数回滚 + 看门狗的组合。为什么?
你想想看,OTA升级后新分区可能有问题。比如驱动不兼容,系统启动到一半就挂了。这时候看门狗会复位,Bootloader重新启动。如果retry_count还没到0,Bootloader会再次尝试新分区。如果连续失败,retry_count归零,Bootloader就自动切回旧分区。
这个流程,我称之为「三次机会」策略:
- 第一次启动新分区,失败 → retry_count减1
- 第二次启动新分区,又失败 → retry_count再减1
- 第三次启动新分区,还是失败 → retry_count归零,切回旧分区
我曾经在一个项目里,retry_count设成了5。结果新分区有bug,车机反复重启了5次才切回去。用户投诉说「车机重启了5分钟才好」。后来我改成了3次,既给了足够的机会,又不会让用户等太久。
避坑指南
做Bootloader的A/B切换,有几个坑我踩过,分享给你:
- Flash驱动必须在Bootloader里独立实现。别依赖其他分区的代码,否则分区坏了,Bootloader也读不了。
- metadata的写入要防中断。我建议先写备份区,再写主区。如果写主区时断电,备份区还能用。
- Bootloader本身也要有回滚能力。Bootloader升级失败怎么办?我一般用双Bootloader方案,一个主Bootloader,一个恢复Bootloader。
- 启动日志要保留。每次启动失败,把原因写到日志区。这样售后分析问题时,能知道是哪个环节出的问题。
嗯,Bootloader这部分内容其实挺多的。今天咱们聊了启动流程、分区判断和故障恢复。下一章我会详细讲metadata的设计和防写坏策略,那才是真正考验功底的地方。
记住一句话:Bootloader稳了,OTA就稳了一半。