Repository navigation
Description
Background
Commit 809fca0 (fix(deploy): force DIO bootloader, add verify-flash skip, harden daemon port recovery) changed how every ESP32-family chip resolves its bootloader flash mode and how BoardConfig reports flash_mode. The fix unblocked ESP32-S3 (which was watchdog-resetting in a loop with Saved PC pointing into ROM 0x400454d5 whenever the bootloader was built as QIO), but the change is global:
crates/fbuild-build/src/esp32/orchestrator.rs— second-stage bootloader is now forced todiofor every ESP32 chip whose appflash_mode != \"opi\".crates/fbuild-config/src/board.rs— for any MCU starting withesp32, the JSON-shippedflash_modeis intentionally dropped; only an explicit env override (board_build.flash_mode = qio) survives. Downstream code falls back tomcu_config.default_flash_mode()(currently\"dio\"for the entire family).crates/fbuild-deploy/src/esp32.rs— newtry_verify_deployment()/build_verify_flash_args()skip re-flash when the candidate image already matches.
The only hardware-gated test (try_verify_deployment_real_esp32s3, --ignored) targets a single ESP32-S3 on COM13. We have zero physical confirmation that the other eight ESP32 MCUs still boot, flash, and verify correctly under the new pipeline.
Goal
Confirm that a clean build + deploy + verify cycle succeeds end-to-end on each ESP32-family MCU we ship a config for, and that verify-flash correctly returns Match immediately after a fresh deploy.
MCUs to cover
One representative dev board per MCU. Suggestions in parentheses are common boards from crates/fbuild-config/data/boards/ — substitute whatever hardware is on hand.
-
esp32(e.g.esp32dev, ESP32-DevKitC) -
esp32s2(e.g.esp32-s2-saola-1) -
esp32s3✅ already covered bytry_verify_deployment_real_esp32s3on COM13 — re-run as a regression baseline -
esp32c2(e.g.esp32-c2-devkitm-1) -
esp32c3(e.g.esp32-c3-devkitm-1) -
esp32c5(if hardware available — newer part, may be skipped) -
esp32c6(e.g.esp32-c6-devkitc-1, also covers the NightDriverStripdemo_c6env) -
esp32h2(e.g.esp32-h2-devkitm-1) -
esp32p4(e.g.esp32-p4-function-ev) — only OPI-flash family member, exercises theapp_flash_mode == \"opi\"branch inorchestrator.rs
Per-board checklist
For each MCU above:
- Clean build — wipe
.fbuildcache for the target, runuv run cargo run -p fbuild-cli -- build <board>against the FastLED reference sketch. - Inspect the bootloader BIN header — byte
0x02ofbootloader.binencodes the flash mode (0x00=qio,0x01=qout,0x02=dio,0x03=dout,0x04=opi). Confirm it is0x02for every chip exceptesp32p4, which should be0x04. - Deploy —
fbuild deploy <board> --port <COMx>. Watch for the watchdog-reset symptom (Saved PCin ROM,rst:0x10/rst:0x7, repeating boot banner). A healthy boot ends in the application's first serial output. - Run
try_verify_deploymentagainst the just-flashed image — must returnVerifyOutcome::Matchin <15s. Add a#[test] #[ignore]mirror oftry_verify_deployment_real_esp32s3per chip if hardware is dedicated CI hardware. - Tampered-image negative test — flip a byte in the middle of
firmware.bin, re-run verify, must returnVerifyOutcome::Mismatch(notErr). - QIO opt-in regression — set
board_build.flash_mode = qioin the env section, rebuild, confirm the application firmware.bin header byte0x02is0x00(qio) butbootloader.binheader byte0x02is still0x02(dio). This is the contract the fix establishes: app mode is user-controllable, bootloader mode is not (except for OPI). - Daemon port recovery — pull and reinsert USB during a deploy; the daemon should recover and complete on retry (this exercises the
port_recovery.rstest path on real hardware).
Acceptance criteria
- Every checked MCU above either passes the seven steps or has a tracking sub-issue explaining why it's blocked (no hardware, broken board JSON, missing toolchain, etc.).
- A new
tests/esp32_family_verify.rs(or per-chip#[ignore]tests incrates/fbuild-deploy/src/esp32.rs) documents the COM port + reference firmware path for each chip we have on hand, so the regression suite can be re-run on demand. - If any MCU regresses, file a focused fix issue and reference it back here.
Why this matters
The commit message for 809fca0 calls out the symptom ("watchdog reset loop with Saved PC pointing into ROM 0x400454d5 on ESP32-S3") but the root cause — ROM bootloader can only fetch the second-stage bootloader in DIO/OPI — applies to every ESP32 chip. There is a real risk that:
- An MCU we don't physically test was working only because its board JSON happened to ship
flash_mode: dioand is now silently picking up the new code path, OR - An MCU was working with QIO because its specific flash chip honoured the QIE bit and we've now downgraded it to DIO without performance justification.
We need physical confirmation, not unit tests, to close this out.
References
- 809fca0 — the fix being verified
crates/fbuild-build/src/esp32/orchestrator.rs—BuildOrchestrator for Esp32Orchestratorblock, bootloader ELF selection (bootloader_<mode>_<freq>.elf)crates/fbuild-config/src/board.rs—is_esp32_familyflash_mode override logic in bothfrom_board_idand the boards.txt parser pathcrates/fbuild-deploy/src/esp32.rs::try_verify_deployment— verify-flash command builder + outcome enumcrates/fbuild-daemon/tests/port_recovery.rs— daemon-side recovery test that needs hardware coverage
Activity
test(deploy): add hardware-gated verify tests for all ESP32 family MCUs
Merge pull request #31 from FastLED/test/esp32-family-verify-scaffold