手机显示 100%,设备重启,随后一直没有重新连接。用户看到的是“刚升级就不能用了”,开发人员却可能还在争论:文件已经传完,问题算发生在哪一步?
超维方程的这篇嵌入式技术笔记,从这个场景讨论 BLE OTA 的状态设计。这里给出的是设计方法,实际恢复能力取决于芯片、分区布局和 SDK 配置。
进度条的终点应该写清楚
一次升级里至少有三件不同的事:固件包到达设备、设备切换到新镜像、新镜像运行并通过检查。只完成第一件事,界面就显示“升级成功”,后面的失败便很难解释。
可以把设备状态和手机提示对应起来:
| 设备已确认的事实 | 手机可以显示的提示 |
|---|---|
| 正在接收固件 | 正在传输,并显示设备确认的进度 |
| 固件接收完成,正在校验 | 正在校验固件 |
| 准备切换镜像 | 即将重启,连接会暂时断开 |
| 新版本启动,自检尚未结束 | 正在检查新版本 |
| 新版本通过检查并确认生效 | 升级完成,显示实际运行版本 |
重连超时只能说明手机没有按时收到结果。它不能单独证明设备已经损坏,也不能证明升级成功。此时应提示状态待确认,并给出重新连接或查看设备状态的入口。
断线以后,听设备的进度
假设手机记录自己已经发到第 80 个分片,设备只确认前 76 个已可靠写入。重新连接后从哪一片继续,不能由手机缓存单方面决定。
升级会话需要关联目标版本、固件包标识和设备确认的写入位置。重连时先查询这些信息,再判断是继续传输、重新开始还是拒绝当前包。重复收到分片时如何处理,也要事先确定,不能把重发当成一次新的升级。
如果底层没有可靠的断点续传能力,就明确告诉用户要重新传输。一个实际无法恢复的“继续升级”按钮,只会增加排查难度。
回滚开关和确认时机,都要检查
以 ESP-IDF 的应用 OTA 为例,官方提供多应用分区和应用回滚机制,但项目是否具备这条恢复路径,还要检查分区表和构建配置。[1]
启用CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE后,新应用首次运行需要按对应流程完成诊断并确认有效。若刚进入主函数就调用esp_ota_mark_app_valid_cancel_rollback(),而关键外设和业务组件尚未初始化,后面的故障便可能错过预期的回滚机会。
反过来,自检条件也不能随意扩大。比如核心离线功能正常,仅仅因为一个非必要的联网服务暂时不可达,就将固件判为不可用,可能让升级反复失败。哪些检查是版本生效的必要条件,要在实现之前列明。
这里讨论的是应用镜像。引导程序、分区表和数据分区的更新不能直接套用同样的断电恢复结论,官方文档对不同更新对象有单独说明。[1]
旧固件还能读懂新配置吗?
还有一种失败发生得更晚:新固件启动后先迁移配置,随后自检失败,系统恢复旧固件。镜像恢复了,配置格式却已经变了,旧固件读不出来。
所以“两个镜像都能启动”还不够。评审时要把持久化数据一起拿出来看:配置有没有版本号,迁移能否延后到确认阶段,旧版本是否还能读取,是否需要保留恢复副本。采用哪种方式取决于存储容量和业务要求。
包的完整性、来源和适用范围也要分别检查。校验和一致,只能说明文件符合对应校验结果;它不能替代可信来源验证,也不能保证这个包适用于当前硬件。
测试时,专门找状态交界处
先在测试样机上验证这些情况:传输途中断连;重复发送已确认的分片;发送不匹配的升级包;首次自检失败;新旧配置之间切换。受控断电测试也应按硬件风险单独安排,不能直接在用户设备上尝试。
每个用例记录故障发生阶段、设备报告的状态、手机提示和最终运行版本。这样遇到“100% 后失联”,才能判断是传输、启动、自检还是重连出了问题。
升级完成时,最有用的一条信息往往不是进度条,而是设备重新读回的实际版本,以及这个版本是否已经被确认生效。
参考资料
[1] Espressif OTA 官方文档:应用回滚、分区与更新流程。实现时请对应项目实际使用的 ESP-IDF 版本。
本文由超维方程整理,关注嵌入式固件、BLE/OTA 与智能硬件样机验证。公司信息见官网。