2. OTA基础概念

做OTA升级,说白了就是让设备能自己给自己“换脑子”。

但这个过程没那么简单。你得先搞清楚几个核心概念。我刚开始接触OTA时,也踩过不少坑。今天咱们就把这些概念掰开揉碎了讲清楚。

2.1 固件(Firmware)——设备的灵魂

固件是什么?就是跑在MCU里的程序。它决定了设备能做什么、怎么做。

在OTA场景下,固件通常指的就是那个待升级的二进制文件。比如一个.bin文件,或者.hex文件。

关键点:固件不是一成不变的。它会被编译、打包、签名,然后通过OTA通道下发到设备上。

我个人习惯把固件分成两类:

  • 基础固件:出厂时烧录的版本,包含最核心的功能。
  • 升级固件:后续通过OTA推送的新版本,修复bug或增加功能。

嗯,这里要注意:固件的大小直接影响升级速度和成功率。我在项目中遇到过,一个固件包太大,导致下载超时,设备变砖。后来我们强制要求固件压缩,并且做了断点续传。

2.2 Bootloader——升级的总指挥

Bootloader,直译就是“引导加载程序”。它是一段特殊的代码,在MCU上电后最先运行。

它的任务很简单:决定接下来跑哪个固件。

你可以把它想象成一个“看门大爷”。设备一启动,Bootloader先检查:

  1. 有没有新固件要升级?
  2. 现有固件是否完整?
  3. 该跳转到哪个分区执行?

我的经验:Bootloader必须足够小、足够稳定。它不能依赖任何应用层的功能。我曾经见过有人把Wi-Fi驱动写在Bootloader里,结果升级时Wi-Fi模块挂了,Bootloader也跟着卡死。这是大忌。

Bootloader的典型工作流程:

  1. 上电,初始化时钟和基本外设。
  2. 检查升级标志(比如某个GPIO电平,或者Flash里的标记位)。
  3. 如果有升级请求,进入升级模式,接收新固件并写入Flash。
  4. 如果没有升级请求,验证当前固件的完整性(CRC校验)。
  5. 跳转到应用程序分区执行。

2.3 应用程序分区——固件的“家”

MCU的Flash空间是有限的。我们需要把它划分成不同的区域,每个区域叫一个“分区”。

应用程序分区,就是存放固件代码的地方。

常见的分区布局:

分区名称 起始地址 大小 用途
Bootloader 0x08000000 32KB 引导和升级管理
App_A(主分区) 0x08008000 256KB 当前运行的固件
App_B(备份分区) 0x08048000 256KB 新固件下载或备份
参数区 0x08088000 16KB 存储配置、升级标志等

你想想看,如果没有分区,新固件直接覆盖旧固件,万一写到一半断电了,设备就彻底废了。这就是为什么我们需要分区。

2.4 双区备份——OTA的“安全气囊”

双区备份,也叫A/B分区升级。这是目前最可靠的OTA方案之一。

它的核心思想:永远保留一个可正常运行的固件副本。

具体做法:

  • App_A:当前正在运行的分区。
  • App_B:备用分区,用于下载新固件。

升级流程:

  1. 设备在App_A中正常运行。
  2. 收到升级通知,开始下载新固件到App_B。
  3. 下载完成后,校验App_B的完整性。
  4. 设置升级标志,重启。
  5. Bootloader检测到升级标志,跳转到App_B执行。
  6. 如果App_B运行正常,标记为“已确认”,下次启动继续用App_B。
  7. 如果App_B启动失败,Bootloader自动回退到App_A。

注意:双区备份需要Flash空间翻倍。对于资源受限的MCU,这可能是个挑战。我曾经在一个只有512KB Flash的芯片上做双区备份,最后不得不把固件压缩到200KB以内,才勉强塞下两个分区。

下面这张图展示了双区备份的核心逻辑:

双区备份OTA升级流程图 双区备份OTA升级流程 App_A 正常运行 下载新固件到 App_B 校验完整性 设置标志,重启 Bootloader 检测升级标志 App_B 启动成功 App_B 启动失败 标记为已确认 回退到 App_A 说明 App_B 启动失败时 自动回退到 App_A 保证设备不“变砖”

2.5 回滚机制——最后的救命稻草

回滚机制,就是当新固件出问题时,能自动退回到上一个稳定版本。

这是双区备份的天然优势。但回滚不是简单的“切回去”,它需要一套完整的策略。

我总结了几种常见的回滚触发条件:

  • 启动超时:新固件在规定时间内没有完成初始化。
  • 看门狗复位:新固件导致系统反复重启。
  • 用户主动触发:比如长按某个按键,强制回滚。
  • 通信失败:新固件上线后无法连接服务器。

避坑指南:我曾经做过一个项目,回滚逻辑写得太“激进”。新固件刚启动3秒,还没来得及连网,就被判定为“通信失败”,触发了回滚。后来我们加了一个“延迟确认”机制:新固件必须正常运行至少5分钟,并且成功上报一次数据,才算“确认通过”。

回滚的执行过程:

  1. Bootloader检测到新固件异常(比如CRC校验失败,或者启动标志未清除)。
  2. 将启动标志指向旧分区(App_A)。
  3. 跳转到App_A执行。
  4. App_A启动后,可以尝试重新下载新固件,或者保持当前版本。

2.6 总结一下这些概念的关系

你想想看,这些概念其实是一个完整的链条:

  • 固件是目标。
  • Bootloader是执行者。
  • 分区是场地。
  • 双区备份是策略。
  • 回滚是兜底。

缺了任何一个,OTA升级都可能出大问题。我记得有一次,一个同事只做了单分区升级,结果升级过程中断电,设备直接变砖。后来我们花了整整两天才用JTAG把固件救回来。从那以后,双区备份就成了我们团队的硬性要求。

最后提醒:不要为了省Flash空间而放弃双区备份。除非你的设备允许现场拆机烧录,否则,省下的那点空间,迟早会变成你加班的时间。