Over-the-Air Firmware Updates
Scope
Set up signed Over-the-Air (OTA) firmware updates for fielded SoMs. Two flows are supported by the Alp SDKTM:
- Yocto / Linux targets (Cortex-A55 on V2N family) use Mender for full-image updates with A/B partition rollback. This is the shipping in-field path.
- Zephyr targets (Cortex-M on AEN, and the M33 on V2N) use MCUboot for swap-using-scratch A/B images with ECDSA-P256 signing. As of v0.4 MCUboot provides signed boot plus automatic rollback, but there is no in-field OTA client for Zephyr yet (deferred to v1.1); deliver signed images by physical reflash or via a Linux companion until then.
Table: Scope summary
| Audience | Engineers and DevOps teams managing fielded SoM fleets. |
| Prerequisites | Functional Wi-Fi or Ethernet network (see AN-002), secure-boot keys generated (see AN-008), Mender server or local CDN reachable. |
| Outcome | End-to-end OTA: build artefact, sign, upload to update server, device pulls and installs, automatic rollback on failed health-check. |
| Time | 60 minutes (server setup is the long pole). |
| Source | docs/tutorials/12-mender-ota.md, docs/ota.md, docs/ota-device-contract.md in alp-sdk. |
Hardware Setup
No carrier-side wiring beyond the standard network connection. The on-module memory layout (eMMC + LPDDR4X on V2N; MRAM + optional OSPI on AEN) provides the A/B partition layout the OTA flows expect.
For the V2N family, the bootloader (U-Boot) owns A/B partition selection and automatic rollback. The GD32 bridge MCU is updated through its own independent firmware-update path (see docs/ota-device-contract.md) and is decoupled from the main-system OTA, so a failed bridge update cannot brick the application core, and vice versa.
Software Walkthrough
Yocto / Linux (V2N A55)
Enable Mender declaratively via the top-level ota: block in your project's board.yaml (the orchestrator emits the matching MENDER_* weak-assignments plus INHERIT += "mender-full" into the slice's local.conf), then build the Mender-aware image:
# Build the Mender-aware Alp image (produces the signed .mender artefact):
MACHINE=e1m-v2n101-a55 bitbake alp-image-edge
# Output: tmp/deploy/images/e1m-v2n101-a55/alp-image-edge-e1m-v2n101-a55.mender
# Upload the .mender artefact via the Mender UI's Releases tab,
# then create a Deployment targeting your device group.
Zephyr (AEN / V2N M-class)
Drive MCUboot from the boot: block in board.yaml (the orchestrator emits the SB_CONFIG_BOOTLOADER_MCUBOOT, SB_CONFIG_MCUBOOT_SIGNATURE_TYPE_ECDSA_P256, and SB_CONFIG_BOOT_SIGNATURE_KEY_FILE sysbuild options). The underlying build is a sysbuild MCUboot child image that signs the slot0 app at build time -- there is no separate west sign step:
# Build a signed image via sysbuild (MCUboot child image + signed slot0 app):
west build -p always --sysbuild \
-b alp_e1m_aen801_m55_he/ae822fa0e5597ls0/rtss_he \
examples/aen/aen-mcuboot-smoke -d build/mcuboot-smoke -- \
-DSB_CONFIG_BOOT_SIGNATURE_KEY_FILE="<abs>/keys/mcuboot_dev_ecdsa_p256.pem"
# Signed slot0 app: build/mcuboot-smoke/aen-mcuboot-smoke/zephyr/zephyr.signed.bin
There is no in-field OTA client header (<alp/ota.h>) for Zephyr yet. Until v1.1, deliver the signed image by physical reflash (J-Link / OpenOCD) or via a Linux companion coordinating through the bridge. The declarative boot: + ota: blocks are exercised by examples/connectivity/iot-fleet-ota (the v0.6 reference, native_sim-verified; HiL gates on a staged Mender server).
Expected Output
On the Yocto / Mender path, watch the device pick up a deployment:
$ journalctl -u mender-client -f
... Update available
... Downloading update
... Installing update to the inactive A/B rootfs slot
... Rebooting to apply update
... (after reboot) Running version: alp-image-edge-...
... Update committed
If the new image boots cleanly and the post-reboot health check passes, the swap is committed. If the device does not confirm within the inventory interval, the bootloader reverts to the previous partition automatically on the next reset. On the Zephyr / MCUboot path the equivalent confirm is the image calling MCUboot's boot_set_confirmed() within its health-check window; an image that never confirms is rolled back by MCUboot on the next reboot.
Troubleshooting
- Signature verification fails: the artefact was signed with a different key than the ECDSA-P256 verify key provisioned into the device. On Mender this anchor is the verify key written into the rootfs (
/etc/mender/); on MCUboot it is the public key compiled into the bootloader. Use the same key pair from your AN-008 secure-boot provisioning. - Health-check times out: the device never confirmed the new image. On Zephyr, the firmware must call MCUboot's
boot_set_confirmed()within its health-check window (typically ~30 s after boot). On Yocto, the device must check in withinMENDER_INVENTORY_INTERVAL(default 60 s) or the bootloader rolls back afterMENDER_RETRY_POLL(default 5 min). - Download stuck at 0 %: server URL unreachable, or TLS pinning mismatch. Test with
curlfrom the device or host first. - Rollback loop: the new image keeps failing health-check, so MCUboot keeps reverting. Pin the version on the server until the bug is fixed.
References
- Tutorial:
docs/tutorials/12-mender-ota.mdin alp-sdk. - OTA architecture:
docs/ota.md,docs/ota-device-contract.md. - Examples:
examples/connectivity/iot-fleet-ota/(declarativeboot:+ota:reference,native_sim-verified),examples/connectivity/firmware-update-log/(tamper-evident update audit log),examples/aen/aen-mcuboot-smoke/(SES → MCUboot → slot0 secure-boot bench test). - SDK API:
<alp/update_log.h>(firmware-update audit log),<alp/iot.h>(transport),<alp/security.h>(signature verification). There is no<alp/ota.h>Zephyr OTA client header yet.
Revision History
Table: Revision History
| Revision | Changes | Date |
|---|---|---|
| 0.1 | Initial draft. | May 2026 |
| 0.2 | Corrected to current SDK: removed non-existent <alp/ota.h>/alp_ota_confirm()/CONFIG_ALP_OTA_GRACE_SECONDS; clarified that Zephyr in-field OTA is deferred to v1.1 (MCUboot signed boot + boot_set_confirmed() rollback only); aligned Yocto build to bitbake alp-image-edge (MACHINE e1m-v2n101-a55) and Zephyr build to the sysbuild MCUboot flow; fixed example path to examples/connectivity/iot-fleet-ota and added firmware-update-log/aen-mcuboot-smoke; pointed API references at <alp/update_log.h>, <alp/iot.h>, <alp/security.h>. | June 2026 |