4. 双备份方案(A/B分区):状态管理、切换逻辑、回滚触发条件
双备份方案,圈里人常叫它 A/B 分区升级。说白了,就是给固件准备两个“窝”。一个跑着,另一个等着。我做了这么多年固件,这方案救过我不少次。你想想看,要是升级到一半断电了,或者新固件有 bug 起不来,至少还有个老固件能顶上。
这一章,咱们把 A/B 分区的核心掰开揉碎。状态怎么管?切换怎么跳?什么情况下必须滚回去?
4.1 状态管理:谁在跑,谁在等
A/B 方案里,系统得时刻知道两件事:当前哪个分区在运行,以及另一个分区里装的是什么版本。这些信息不能丢,得存到持久化存储里。
我个人习惯用 Bootloader 共享数据区,或者叫 Metadata 分区。它很小,但至关重要。
| 状态字段 | 说明 | 典型值 |
|---|---|---|
active_slot |
当前启动的分区 | A / B |
trial_slot |
试运行中的新分区 | A / B / NULL |
boot_attempt |
试运行启动次数 | 0 ~ N |
slot_status[A/B] |
每个分区的健康状态 | OK / FAILED / UNKNOWN |
这里有个坑。我曾经遇到过,设备在写入 Metadata 时突然掉电,结果两个分区都变成了 UNKNOWN。嗯,后来我加了个 双备份校验——Metadata 写两份,启动时交叉验证。如果有一份坏了,用另一份恢复。
核心原则:状态数据必须原子写入。要么全写成功,要么全不写。千万别写到一半断电,留下个“四不像”。
4.2 切换逻辑:从下载到生效的完整链路
切换不是简单地把启动标志位翻一下。它是一套严谨的流程。我把它拆成四个阶段:
- 下载阶段:新固件写入非活跃分区。比如当前跑的是 A,那就往 B 里写。写完后校验完整性,标记 B 为
PENDING_VERIFY。 - 切换阶段:设置
active_slot为 B,trial_slot也为 B,boot_attempt清零。然后复位。 - 试运行阶段:Bootloader 看到
trial_slot不为空,启动 B。应用层上报“我起来了”。每上报一次,boot_attempt加 1。 - 确认阶段:如果
boot_attempt达到预设值(比如 3 次),且应用层持续上报健康,就把trial_slot清空,B 正式转正。
为什么要有试运行?我见过太多“启动一次就确认”的悲剧。设备刚起来时一切正常,跑了两小时突然死机。所以,多跑几次,跑久一点,才能暴露问题。
我的经验:试运行次数别设太少。消费类产品 3 次够了,工业设备我建议 5 次以上。有些 bug 是偶发的,次数多了才能抓到。
4.3 回滚触发条件:什么时候必须滚回去
回滚不是你想滚就能滚的。得有一套明确的规则。我把它分成三类:
4.3.1 主动回滚
用户或运维发现新固件有问题,手动触发回滚。这种最简单,直接设置 active_slot 为旧分区,复位即可。
4.3.2 被动回滚(自动触发)
系统自己判断,不需要人参与。常见场景:
- 启动失败:Bootloader 尝试启动新分区,但卡在某个阶段,Watchdog 超时复位。连续 N 次失败后,自动切回旧分区。
- 应用层崩溃:新固件跑起来了,但关键服务(比如网络、传感器)频繁崩溃。应用层主动向 Bootloader 发回滚请求。
- 试运行超时:新分区在试运行阶段,一直没收到“确认健康”的信号。比如设备离线了,或者上报机制坏了。
4.3.3 强制回滚
这是最后的保险。当 Metadata 损坏,或者两个分区都标记为 FAILED 时,Bootloader 进入恢复模式,从外部存储(比如 SD 卡、U 盘)加载固件。
注意:强制回滚是“死马当活马医”。它依赖外部介质,如果外部介质也坏了,设备就真变砖了。所以,永远不要依赖强制回滚作为主要方案。
4.4 核心流程图:A/B 分区状态机
下面这张图,是我自己画的状态机。它把整个流程串起来了。你仔细看,每个箭头都对应一个触发条件。
4.5 避坑指南:我踩过的几个雷
最后,分享几个实战中容易翻车的地方。这些都是我用真金白银换来的教训。
- Metadata 写坏:我曾经遇到过,设备在写 Metadata 时断电,结果两个分区都变成了 UNKNOWN。后来我加了双备份校验,才解决。
- 试运行次数设太少:有个项目,试运行次数设了 2 次。结果设备每次启动都正常,但跑 10 分钟后必死。后来改成 5 次,问题才暴露。
- 回滚后不清理:回滚后,新分区还标记着 PENDING_VERIFY。下次升级时,系统以为它还在试运行,直接跳过。嗯,回滚后一定要把新分区状态重置为 UNKNOWN。
- 忽略 Watchdog:Bootloader 阶段也要开 Watchdog。我见过 Bootloader 卡在某个循环里,设备彻底死机。加了 Watchdog 后,至少能自动复位。
总结一下:A/B 分区方案的核心,就是状态机。状态管好了,切换逻辑清晰了,回滚条件明确了,这方案就稳了。别想着偷懒,每一步都要做扎实。