4. 设备端存储分区设计
OTA升级能否安全落地,很大程度上取决于设备端存储分区是否设计合理。分区设计不只是“把Flash切成几块”,而是要同时回答四个问题:升级镜像写到哪里、失败后从哪里恢复、旧版本保留多久、剩余空间是否够用。对于资源受限的嵌入式设备,分区表一旦量产就很难更改,因此必须在产品定义阶段就把A/B分区、恢复分区、备份分区和空间规划一起考虑。
一、核心原理:分区是升级可靠性的物理基础
设备端OTA通常涉及三类镜像:引导程序(Bootloader)、系统镜像(Kernel + RootFS 或完整固件包)、应用/配置数据。分区设计的核心目标,是让“写入新镜像”和“运行当前系统”互不干扰。常见方案有单分区、A/B双分区和恢复分区三种。
单分区方案只有一个系统分区,升级时直接覆盖当前镜像。优点是省空间,缺点是升级中断电或写入失败后设备可能无法启动。A/B分区方案则保留两个可启动系统槽位,当前运行A,新镜像写入B,写入完成并校验通过后切换启动标志。若新系统启动失败,Bootloader可回退到A。恢复分区是一个独立的最小系统,用于在A/B都不可用时执行恢复、回滚或重新烧录。
二、A/B分区、恢复分区与备份分区的职责划分
A/B分区解决“可回滚的升级”,恢复分区解决“系统无法启动时的救援”,备份分区解决“关键参数和旧版本镜像的保留”。三者不是互相替代,而是分层防护。
- A/B分区:两个系统槽位,交替升级。需要维护启动标志、槽位状态、镜像校验值。适合对可用性要求高的设备。
- 恢复分区:存放最小恢复系统,通常包含串口/USB升级、网络恢复、出厂烧录功能。它不参与日常OTA,但必须独立且不可被普通升级覆盖。
- 备份分区:保存出厂参数、校准数据、设备证书、旧版本镜像或差分升级基线。备份分区应尽量只读或带写保护。
在具体实现中,Bootloader需要读取分区表中的槽位状态。例如,使用U-Boot时可通过环境变量记录当前槽位和升级状态:
# 典型A/B启动标志示例
bootslot=a
slot_a_ok=1
slot_b_ok=0
upgrade_status=idle
# 升级完成后切换
setenv bootslot b
setenv upgrade_status pending
saveenv
设备首次启动新槽位时,若系统健康检查通过,则将upgrade_status置为confirmed;若连续启动失败,Bootloader根据重试计数回退到旧槽位。
三、空间规划要点:先算账,再切分
空间规划不能只看镜像大小,还要考虑文件系统开销、坏块管理、日志、配置增长和未来版本膨胀。建议按以下顺序估算:
- 统计当前固件包解压后大小,并预留20%~30%增长空间。
- 确认Flash类型:NOR、NAND还是eMMC。NAND需要额外坏块管理和ECC开销,eMMC则要考虑分区对齐和预留OP空间。
- 为每个分区确定文件系统类型:只读分区可用squashfs,可写分区可用ubifs、ext4或f2fs。
- 为Bootloader、环境变量、分区表、恢复系统、备份数据分别留出独立区域。
- 最后检查剩余空间,确保至少有一个完整镜像的写入余量。
| 分区 | 典型大小 | 读写属性 | 作用 |
|---|---|---|---|
| Bootloader | 256KB~1MB | 只读,升级需谨慎 | 启动引导、槽位选择、回滚判断 |
| Env / 参数区 | 64KB~256KB | 可写,双备份 | 启动标志、升级状态、设备参数 |
| Slot A 系统 | 32MB~256MB | 只读 | 当前运行系统或备用系统 |
| Slot B 系统 | 与A相同 | 只读 | 升级目标槽位 |
| Recovery | 8MB~32MB | 只读 | 救援、恢复出厂、强制升级 |
| Backup / Data | 剩余空间 | 可写 | 配置、日志、证书、差分基线 |
四、案例与场景:一次失败升级的复盘
某工业网关采用单分区方案,固件包约48MB,Flash为128MB NAND。一次远程升级过程中,设备在写入RootFS时断电,重启后内核校验失败,设备无法进入系统,只能返厂。复盘发现三个问题:没有A/B槽位,没有恢复分区,Bootloader也没有镜像校验和回滚逻辑。
改造后,该设备采用A/B双系统槽位,每个槽位64MB,恢复分区16MB,参数区双备份。升级流程变为:下载新镜像到Data区,校验SHA256,写入B槽位,再次校验,设置启动标志为B并标记pending。重启后新系统自检通过,标记confirmed;若连续三次启动失败,Bootloader自动切回A槽位,并通过日志上报升级失败原因。
五、常见误区与检查清单
建议在分区设计评审时逐项检查:
- Bootloader是否支持双备份或至少带恢复模式?
- A/B槽位大小是否一致,是否预留了镜像增长空间?
- 启动标志是否双份存储并带CRC校验?
- 恢复分区是否独立编址,且不被普通OTA写入?
- 备份分区是否包含出厂参数、证书和差分基线?
- Data分区是否预留了下载新镜像的临时空间?
- 分区表是否在量产前冻结,并保留升级分区表的能力?
分区设计没有唯一答案,但有一条底线:任何一次OTA写入,都必须保证设备至少还能启动到一个可恢复的系统。A/B分区提供回滚能力,恢复分区提供救援能力,备份分区提供数据与基线保障,空间规划则决定这些能力能否真正落地。把四者放在同一张分区表里统筹,才能让OTA升级从“能升”走向“敢升”。