Bootloader & MCUBoot serial recovery¶
The halves run MCUBoot (*** Booting MCUboot 9ddeffa8169c ***,
Zephyr OS v3.7.0-5411-g31fea97e05fd). App CDC ee/10ce
(NORMAL RESET) reboots into it; during recovery an extra USB node
appears (e.g. 1103 alongside 1101), window ~2.2 s, then the app
boots and the node disappears.
Boot banner (361 B, captured on the extra node):
*** Booting MCUboot 9ddeffa8169c ***
*** Using Zephyr OS build v3.7.0-5411-g31fea97e05fd ***
I: Starting bootloader / Primary image: magic=good, swap_type=0x3, copy_done=0x1, image_ok=0x1 / Scratch: magic=unset / Boot source: none / Image index: 0, Swap type: none / I: Enter the serial recovery mode
Console roles: ACM1 (1101-style) = serial-recovery COMMAND channel
(echo/reset answer here). ACM2 = boot LOG only (never answers).
Protocol (classic mcuboot-serial ASCII framing)¶
Request: 06 09 + base64(u16 totlen BE ‖ nmgr_hdr 8 B
(op,flags,lenBE,groupBE,seq,id) ‖ CBOR ‖ crc16) + \n.
Multi-line responses continue with 04 00 + base64 chunks (~124 B/line).
- CRC16 = XMODEM poly
0x1021, seed0x0000(proven: seed-0 echo answered instantly,0xFFFFecho ignored; response CRC verifies). - DEFAULT group (0) WORKS: echo id 0 (op 0, body
{"d":"naya"}→{"r":"naya"}); RESET id 5 (op 1 write, empty body) → bootloader reboots to app (port dies). - IMAGE group (1): states read (id 0) NEVER responds — even on a stable parked console while echo answers ⇒ IMAGE group compiled out (no serial upload/list/slot-info).
Parking, wedge, recovery (recipe proven 3×)¶
- Any VALID frame resets the serial inactivity timeout ⇒ the device PARKS in recovery indefinitely (extra node persists, app protocol dead, session wake hangs — classic symptom).
- Flooding frames into the window can additionally wedge the USB CDC driver (console mute on both nodes).
- Recovery recipe (no hands, all software):
- idle ports 20–50 s (no holders) → USB re-enumerates, console revives;
- canary: echo seed0 on the command node;
- RESET (group 0, id 5, op 1) → device boots app. Verify with
fa/1001.
Implications¶
- Serial image upload unavailable ⇒ stock base-FW updates flow through
the APP CDC protocol (download → secondary slot → reboot → MCUBoot
swap), matching NayaCore's
MCUBootWorker_*classes. - Custom FW is gated by RSA-2048 signature + encrypted bodies on every DFU path ⇒ SWD pads (labeled on PCB) remain the only custom-FW entry — see signing.
- Zephyr 3.7 base: a ZMK port is architecturally a board-def + driver exercise on the same nRF Connect SDK generation.
Reference tooling (RE repo toolkit/): smp-unwedge.py (canary +
RESET — keep handy), smp-probe*.py (probe evolution), boot-trap.py
(node-trap for cold-boot log capture).