图 8 - OTA 升级流程
设备怎么远程升级固件而不会变砖?这张图把整个 A/B 双分区 + 防回滚的逻辑说清楚。
如果上方图无法显示,点这里看 PNG 版本

整体思路
ESP32 把 Flash 切成两个对称的 OTA 分区 ota_0 和 ota_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(分区表)