2. 固件升级基础
在双分区 A/B 升级系统中,很多工程问题并不是“升级代码写错了”,而是对基础术语理解不一致:有人把 Bootloader 当成固件,有人把镜像和分区混为一谈,也有人认为“版本号相同就一定不用升级”。本节先把这些概念一次讲清,为后续 A/B 分区切换、回滚策略和升级状态机打下共同语言。
一、核心概念:从 Flash 到可运行系统
嵌入式设备的非易失存储(通常是 Flash)被划分为若干分区,每个分区是一段有固定起始地址和长度的存储区域。分区表就是描述这些区域边界与用途的元数据,它决定了 Bootloader 去哪里找镜像、升级程序往哪里写数据。
- 固件(Firmware):运行在设备上的完整软件集合,通常包含 Bootloader、应用程序、文件系统、配置区等。口语中“刷固件”往往指更新应用镜像,但严格说固件是整体。
- Bootloader:上电后最先运行的引导程序,负责初始化时钟、内存、外设,校验镜像完整性,选择从 A 分区还是 B 分区启动,并在必要时执行回滚。
- 分区表:定义各分区名称、偏移、大小、类型和标志位。A/B 系统中至少包含 app_a、app_b,可能还有 bootloader、factory、data、misc 等。
- 镜像(Image):可被烧录或升级的二进制文件,如 app.bin、boot.bin、rootfs.img。镜像通常带头部信息,包含版本、长度、校验值和签名。
- 版本号:标识镜像新旧与兼容性的字符串或整数,常见形式为语义化版本 1.4.2 或构建号 20240612.1030。
- 回滚(Rollback):当新镜像启动失败、校验不通过或看门狗超时,系统自动切回上一可用分区的过程。
一句话理解:分区表是“地图”,镜像是“货物”,Bootloader 是“调度员”,版本号是“货物标签”,回滚是“送错货后的退货通道”。
二、A/B 双分区下的启动与升级数据流
下面这张图展示了一个典型 A/B 系统的核心结构:Bootloader 读取分区表和元数据,决定从哪个 slot 启动;升级时数据写入非活动分区,校验通过后切换启动标志。
三、版本号、镜像头与校验:升级判断的依据
版本号不只是给人看的字符串,它参与升级决策。设备上报当前版本,云端比较后决定是否下发新镜像。常见比较规则包括:主版本不同必须升级,次版本递增允许升级,构建号相同则跳过。镜像头通常包含以下字段:
struct image_header {
uint32_t magic; // 0x5A5A5A5A
uint32_t header_crc; // 头部校验
uint32_t image_len; // 镜像长度
uint32_t image_crc; // 镜像体校验
char version[16]; // "1.5.0"
uint8_t slot; // 目标分区 A/B
uint8_t signature[]; // 数字签名
};
Bootloader 在启动前会依次检查 magic、header_crc、image_crc 和签名。任何一项失败,都不会跳转到该 slot,而是根据元数据决定重试或回滚。
四、常见术语与误区对照
| 术语 | 正确理解 | 常见误区 |
|---|---|---|
| 固件 | 设备上完整软件集合 | 只把 app.bin 叫固件 |
| Bootloader | 引导、校验、选择 slot、回滚 | 认为它不参与升级逻辑 |
| 分区表 | 定义偏移、大小、用途 | 升级时随意改动分区边界 |
| 镜像 | 带头部和签名的可烧录文件 | 把裸 bin 直接写入分区 |
| 版本号 | 参与升级判断和兼容性检查 | 只看字符串,不比较构建号 |
| 回滚 | 失败后切回上一可用 slot | 认为回滚等于重新刷旧包 |
五、案例与复盘:一次“升级成功但无法启动”的排查
某设备 OTA 升级后重启,串口日志显示:
[BOOT] active_slot = B
[BOOT] verify image_b ... FAIL (crc mismatch)
[BOOT] retry_count = 1
[BOOT] switch to slot A
[BOOT] boot_ok = true
复盘发现:升级程序写入 B 分区后,没有回读校验就更新了启动标志。网络抖动导致最后 4KB 数据不完整,CRC 失败。Bootloader 按策略回滚到 A,设备恢复运行。这个案例说明:写入完成不等于升级成功,必须经过“写入 → 回读校验 → 更新标志 → 重启验证 → 确认”完整链路。
误区提醒:不要在活动分区上直接覆盖写入新镜像。A/B 的核心价值就是“后台写入、原子切换”,一旦破坏活动分区,回滚将失去落脚点。
工程建议:为每个 slot 维护独立的版本号、校验值和启动状态;misc 分区中的 active_slot、boot_ok、retry_count 三个字段是回滚策略的最小集合,务必保证写入原子性。
掌握这些基础概念后,后续学习 A/B 切换流程、升级状态机、差分升级和回滚策略时,就能准确判断每一步操作的对象、依据和风险边界。