跳到主要内容

图 8 - OTA 升级流程

设备怎么远程升级固件而不会变砖?这张图把整个 A/B 双分区 + 防回滚的逻辑说清楚。

如果上方图无法显示,点这里看 PNG 版本

整体思路

ESP32 把 Flash 切成两个对称的 OTA 分区 ota_0ota_1(各 4MB)。

  • 任何时刻只有一个分区在运行;
  • 升级时把新固件写到另一个分区
  • 写完用 esp_ota_set_boot_partition 把启动指针切过去;
  • 重启加载新固件;
  • 新固件如果跑不起来(看门狗触发),Bootloader 自动回滚到旧分区 —— 这就是防砖机制的核心。

6 个关键步骤

Step 1: CheckVersion — 设备自报家门

设备 POST 自己的信息(mac / 当前版本 / 芯片型号 / 屏幕信息 / 分区表 / 已运行固件 SHA-256)到 OTA_URL

服务器响应里含:

  • 激活信息(首次开机要走激活流程)
  • MQTT/WebSocket 配置(自动下发)
  • 服务器时间(用来 settimeofday,国内 NTP 经常被墙时这是兜底方案)
  • 新固件 URL + 版本号 + 是否强制

Step 2: 激活流程(仅首次或更换设备)

服务器质询 → 设备用 eFuse 内的 32 字节序列号 HMAC-SHA256 签名 → 应答。

为啥用 eFuse? eFuse 是芯片内不可改写的存储,签名密钥永远不出芯片,复制设备的人没法绕过激活。

Step 3: 版本比较 + 决定升级时机

  • 版本相同 → 跳过
  • 有新版本 + force=false → 等设备进 Idle 时再升级(不打断用户)
  • force=true → 立刻进 Upgrading 状态

Step 4: 流式下载 + 写 Flash

HTTP GET 固件 → 边收边 esp_ota_write → 进度回调

不是先下载到 RAM 再写——而是边收边写,因为 4MB 固件根本放不进 RAM。OTA_WITH_SEQUENTIAL_WRITES 选项让 ESP-IDF 自动处理擦写边界。

Step 5: 校验

  • SHA-256 校验完整性(防下载错乱)
  • image header 校验芯片型号匹配(防把 ESP32 固件刷到 ESP32-S3)

Step 6: 切分区 + 重启 + 防回滚

  • esp_ota_set_boot_partition() 把新分区设为启动
  • esp_restart() 重启
  • 新固件启动第一件事:开 1 秒看门狗,如果在指定时间内没 MarkCurrentVersionValid(),bootloader 下次启动会自动回滚

MarkCurrentVersionValid 在哪调?小智项目在 Application 跑到 Idle 状态后调——说明完整的初始化+联网+协议建链都过了,这版固件确实可用。

一句话讲清

"双分区轮流升级,新固件下载到备用分区;校验签名通过才切启动指针;首次跑不通自动回滚到老分区。整个过程对用户透明,最多看到一次重启。"

关联章节

  • /07-system-services §7.3(OTA)
  • /10-build-and-tools §10.4(分区表)