SuperAPI AI Directory

esp32-ota

Deployment & operations

View repository

Updated 10-15 21:48

About this skill

ESP32 OTA (Over-the-Air Firmware Update)

OTA reliability comes frompartition mechanism + state machine + rollback confirmationthree things meshing together. This Skill provides baseline (high-confidence) facts and order; device facts such as partitions and offsets must always "read target first"; fabrication is forbidden.

Determine Task Type

  1. Add OTA capability to a product: partition layout rework + upgrade code + upgrade server → Workflow A (main path).
  2. After upgrade the device runs the old version: suspected rollback → Workflow B (troubleshooting, first check for unconfirmed PENDING_VERIFY).
  3. Upgrade channel robustness/decision: when to allow upgrades, what to do on failure → upgrade decision checklist + rollback-checklist。
  4. Upgrade without network / offline flashing: out of scope → refusal route esp32-idf(see Hand-off).

Prerequisites / Preflight

idf.py --version            # IDF 版本(基线见下)
idf.py partition-table      # 读 target 实际分区表——任何分区回答的起点
idf.py confserver 2>/dev/null | head -5 || true   # 存在性自检可忽略
  1. Read target first:idf.py partition-table output is the only valid source of partition facts; before there is target board output,refuse to fabricate partition offsets/sizes。
  2. Confirm the actual flash capacity (determines how large the OTA slot can be).
  3. Upgrade server: HTTPS reachable, CA certificate in hand (see Contracts item 4).

Offline Baseline

  • ESP-IDF baseline = v6.1(as of walkthrough 2026-09-02, not auto-updated); partition mechanism, OTA state machine,CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE, and esp_https_ota are all cited from baseline §4/§5 (official partition-tables and ota docs, high confidence).
  • Behavior changes after this version are subject to the official OTA docs; do not assert from memory.

Contracts (Device Contracts)

  1. Partition prerequisites (high confidence): OTA requires at least two OTA app slots ota_0/ota_1 + otadata partition; the bootloader selects the slot according to otadata's ota_seq; if otadata is empty, it boots factory.
  2. Image validity status is stored in otadata (not inside the image): VALID/UNDEFINED can boot; INVALID/ABORTED do not boot.
  3. Only OTA slots can roll back, factory cannot—placing production firmware in a combination of factory + OTA slots is a common practice and supported by the mechanism, but rollback only occurs between OTA slots.
  4. HTTPS certificate: esp_https_ota uses HTTPS, and the firmware must hold the server CA certificate (the embedding method and verification options are subject to the official esp_https_ota docs, verified at runtime).Security stance: server certificate verification must not be disabled—disabling verification is equivalent to opening the upgrade channel to man-in-the-middle poisoning.
  5. Flashing/erasing partitions is a destructive operation: before changing the partition table, restate the current layout (Preflight output) and obtain confirmation.

Partition prerequisites and minimal CSV template

Mechanism hand-off esp32-idf(CSV fields, full Type/SubType set), this Skill only provides the OTA minimal complete template. Leave all Offset columns empty = let the build arrange them automatically (high confidence: empty Offset = automatic arrangement; app 64KB alignment and data partition 4KB alignment are guaranteed by the build)—do not hand-fill offset values from memory:

# Name,     Type, SubType,  Offset,  Size,     Flags
# 说明:Offset 留空自动排布;各 Size 按实际 flash 容量与 app 体积调整,
#       最终布局以 idf.py partition-table 输出为准(读 target 先行)。
nvs,        data, nvs,      ,        0x4000,
otadata,    data, ota,      ,        0x2000,
phy_init,   data, phy,      ,        0x1000,
factory,    app,  factory,  ,        1M,
ota_0,      app,  ota_0,    ,        1M,
ota_1,      app,  ota_1,    ,        1M,

menuconfig preset can be a starting point:"Factory app, two OTA definitions"(corresponds to the table above); "Single factory app, no OTA" means no OTA. The build will verify that the image must fit into some app partition—if it does not fit, it will error out directly; do not try to squeeze it in by shrinking nvs.

OTA state machine (core anti-pitfall)

写入非活动槽(esp_ota_begin/write/end)
    -> esp_ota_set_boot_partition,镜像记为 NEW
    -> 重启,bootloader 置 PENDING_VERIFY 后启动新镜像
    ├── 应用自检通过 -> esp_ota_mark_app_valid_cancel_rollback() -> VALID(转正)
    ├── 应用自检失败 -> esp_ota_mark_app_invalid_rollback_and_reboot() -> ABORTED 回滚旧版
    └── 新镜像崩溃/看门狗反复重启,从未调用确认 -> 重启即回滚旧版(INVALID)

Trap #1 for this skill: after enabling CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE ,the new image must explicitly call esp_ota_mark_app_valid_cancel_rollback()on the application side—the consequence of not calling it is not "success by default", but ratherrolling back to the old version on the first reboot. The number one cause of "after a successful upgrade the device runs the old version again" is an omitted self-check confirmation (for troubleshooting see Workflow B).

API order (high confidence):esp_ota_begin(if the size is unknown, pass OTA_SIZE_UNKNOWN)→ esp_ota_write(block loop) → esp_ota_end(image verification) → esp_ota_set_boot_partition; for slot selection use esp_ota_get_next_update_partition() rotation. For high-level encapsulation use esp_https_ota(esp_https_ota_config_t, with buffer_size/bulk_flash_erase and other tuning options). Anti-rollback (optional)CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK: secure_version burns eFuse and can only increase—enabling it involves an irreversible eFuse operation, route esp32-secureboot。

Capability Boundaries + Hand-off

User Intent Skill
Project skeleton/partition table mechanism fundamentals/USB serial flashing esp32-idf
Offline device upgrade (no network) refusal: OTA inherently requires a network; for offline use USB serial flashing → esp32-idf
Signing/anti-rollback eFuse/encrypted image esp32-secureboot
Real-device upgrade + power-loss rollback acceptance fw-hil-testing
Upgrade package naming/checksum/release process fw-release-gate
Locating a crash in the new image after upgrade esp32-debug(coredump)
Pre-upgrade network (credentials invalid, cannot connect) esp32-wifi-provision

Workflow A — Add OTA dual-partition rollback support (main path)

  1. Read target:idf.py partition-table to record the current layout; confirm that ota_0/ota_1/otadata exist; if not, modify according to the CSV template above (leave Offset blank),refuse to fabricate offsets。
  2. menuconfig: In Partition Table preselect "Factory app, two OTA definitions"; enable CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE。
  3. Implement the upgrade flow:esp_ota_get_next_update_partition() select slot → esp_ota_begin/write/end → esp_ota_set_boot_partition → reboot; for download use esp_https_ota (for certificates follow Article 4 of Contracts).
  4. Implement self-check confirmation: after the new image starts, complete a business-level self-check (peripherals present, network present, critical tasks running), and immediately after passing esp_ota_mark_app_valid_cancel_rollback(); if the self-check fails, call esp_ota_mark_app_invalid_rollback_and_reboot()。do not leave "we'll do it next time" for confirmation。
  5. Real-device acceptance: see Validation Gates; among them, power-loss rollback acceptance → fw-hil-testing。
  6. When there is no real device, mark all conclusions as Build Verification Only。

Workflow B — After upgrade, the device reboots into the old version (troubleshooting)

  1. First check for state machine gaps: whether in the new image there exists andis necessarily executedthe esp_ota_mark_app_valid_cancel_rollback()? (A hung self-check/blocked task will cause confirmation to never execute.)
  2. Confirm menuconfig:CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE whether it is enabled (once enabled, the semantics are "rollback if unconfirmed", which is mechanism behavior, not a fault).
  3. Read the evidence: serial boot log + esp32-debug(coredump/reset reason) to locate whether the new image crashes before confirmation.
  4. Refer to rollback-checklist acceptance checklist and replay the upgrade process once.

Upgrade decision checklist (conditions allowing the upgrade to start)

  1. Version comparison: the target version is newer than the current version; anti-rollback requirement (eFuse secure_version) → esp32-secureboot。
  2. Window and battery: for battery devices, battery level is above the threshold; business idle window; no power loss during upgrade (notify the user).
  3. Image budget: new image ≤ OTA slot size (known only after reading target).
  4. Rollback plan: The confirmation logic has been implemented and rehearsed; on failure it can return to the old version (only between OTA slots).
  5. Channel security: HTTPS + certificate verification enabled, images are not pulled over plaintext HTTP.
  6. On-device acceptance items → fw-hil-testing; release artifact verification → fw-release-gate。

Validation Gates

  1. Normal upgrade: the new version number is reported, otadata points to the new slot, and the application is in VALID.
  2. Rollback acceptance: Flash a test image that is guaranteed to fail its self-check → the device automatically returns to the old version and can be upgraded again (execute on a real device; no real device = Pending HIL).
  3. Unconfirmed semantics acceptance: with the confirmation call commented out, after a reboot it returns to the old version—used to prove the anti-trap has been understood.
  4. Power-loss interrupted upgrade: after the upgrade is interrupted, the device can still boot (the old slot was not damaged).
  5. Channel security: packet capture confirms HTTPS; testing against a server with an expired/wrong certificate is rejected.

Pitfalls

  1. Do notenable ROLLBACK and then forget to write the confirmation call—the culprit behind "upgrade succeeds but it returns to the old version".
  2. Do notfabricate partition offsets/sizes—leave Offset blank for automatic layout, and the placement is based on idf.py partition-table .
  3. Do notdisable esp_https_ota's server certificate verification—I do not provide that path.
  4. Do notpresent a layout of "factory only, no OTA slots" as supporting rollback—rollback only occurs between OTA slots.
  5. Do notpromise that "offline devices can also do OTA"—OTA inherently requires a network; for offline, use USB serial flashing (route esp32-idf)。
  6. Do notretry downloads infinitely in the upgrade loop—failures must have backoff and a limit, to avoid the device getting stuck in an "upgrade storm".

Official Sources

Privacy

Upgrade metadata (device version, serial number, upgrade server URL) and diagnostic logs may contain device identifiers: do not collect, do not send externally; upgrade server credentials/certificate private keys are governed according to fw-release-gate , and must not enter the repository or logs.