Minimal ESP-IDF bootloader for the Waveshare ESP32-C3 Zero board, built to prove readable bring-up, bounded recovery, and explicit boot-path control on real hardware.
When a custom ESP32-C3 board will not boot reliably, blocked bring-up and recovery gaps can delay delivery and raise field risk. This repository is the public hardware proof for a deterministic, debuggable, and recoverable boot path.
Boot flow aligned with BRS-B principles (RISC-V ecosystem, ratified 2025): minimal, standardized handoff, no heavy UEFI/ACPI stack. Scope note: this repository demonstrates baseline alignment, not full production hardening or full standards conformance.
This repository proves that a small ESP32-C3 team can get a custom board booting with a readable, auditable path on real hardware without relying on opaque vendor boot behavior. It shows deterministic bring-up behavior, recovery and update baseline paths, validation evidence, and explicit scope limits.
- Teams moving from ESP32-C3 devkits to custom boards
- Consultancies that need a clean boot baseline they can hand off
- OEMs that need owned code, explicit limits, and evidence-backed behavior
This repository is the main public reference for ESP32-C3 bring-up, recovery, and boot-path adaptation work.
Best starting point:
First-Board Bring-Upwhen the board is blocked or boot behavior is still unstableFactory and Field Recoverywhen bad images, failed first boots, or update fallout need a bounded fallback pathVerified Boot Gatewhen update, audit, or compliance pressure is already explicit
Use it to start one bounded scope:
- First-Board Bring-Up: explicit boot flow, diagnostics, and board adaptation
- Factory and Field Recovery: recovery and update baseline paths with deterministic behavior
- Verified Boot Gate: small verification gate, expected-versus-observed package, and compliance-ready baseline evidence
ESP32-C3 leads because it has the strongest public proof today. Other ESP32 RISC-V chips, including ESP32-C6, can be handled separately when board assumptions and validation targets are explicit.
Handled separately:
- advanced production hardening internals
- full key management architecture
- client-specific anti-tamper implementation details
What this repository demonstrates:
- Deterministic ESP32-C3 second-stage boot behavior on real hardware
- Explicit boot decision states with stable serial tokens and LED mapping
- Recovery and update baseline behavior that is easy to review against the published token sequence and evidence logs
- A public reference implementation for ESP32-C3 bring-up and boot-path adaptation
Not included:
- Advanced production hardening internals
- Full key management architecture
- Client-specific anti-tamper implementation details
| Need | Typical timeline | Includes | Evidence artifact |
|---|---|---|---|
| First-Board Bring-Up | 1-3 days | Board bring-up, boot flow adjustment, deterministic logs | docs/evidence/<release>/expected-vs-observed.md |
| Factory and Field Recovery | 3-5 days | GPIO trigger or UART path, CRC gate, behavior summary | docs/evidence/<release>/logs/recovery_update.log |
| Verified Boot Gate | 1-2 days | Selective verification gate, expected-versus-observed package, known limits, handoff summary, compliance-ready baseline note | docs/evidence/<release>/expected-vs-observed.md |
ExerionBit works through fixed-scope, evidence-backed deliverables.
Most projects start from a current boot blocker or a recovery/update risk, then add verification work only when the extra gate is already justified.
Send four inputs. Get a short, scoped reply with the best-fit path for your board.
To request a scoping pass, email exerionbit.diego@gmail.com with:
- target SoC or board
- current boot blocker
- desired outcome:
First-Board Bring-Up,Factory and Field Recovery,Verified Boot Gate, orArchitecture de-risking review - expected timeline
Main public proof: this repository for ESP32-C3.
RISC-V reference for architecture review: the portable RISC-V repository.
Web entry point: https://www.exerionbit.com
- Build and flash using ESP-IDF.
- Capture logs with
scripts/watch_serial.py. - Validate token sequence with the validation profile (
VALIDATION_PROFILE.md). - Optional: hold
GPIO9at boot to enter selector and verify mode tokens (MODE_SELECT_ARMED,MODE_SELECTED,MODE_EXECUTE). - Optional: test CRC validation via
SETUP.md(CRC OK path and CRC failure path with recovery).
- Live validation requires physical ESP32-C3 hardware access
- Native USB re-enumeration can hide very early boot lines without watcher tooling
- The published boot sequence includes deliberate visual/reconnect delays to make LED states and late boot tokens easy to observe; production-oriented builds would usually shorten or remove them
- Repository documentation covers a minimal recovery/update baseline, not full production hardening
- Commercial scope can extend to other ESP32 RISC-V chips, but this repository only proves ESP32-C3 today
-
Canonical evidence pack: docs/evidence/v0.2/expected-vs-observed.md
-
Normal boot demo:
Direct video file: docs/media/v0.2/waveshare-esp32-c3-zero-custom-bootloader-normal-boot.mp4
-
Recovery/update serial evidence: recovery_commands.log and recovery_update.log
-
Build instructions target ESP-IDF 6.0.
-
The current v0.2 evidence set was captured on 2026-03-11.
- BRS-B principles alignment: minimal boot flow, explicit handoff contract, no heavy UEFI/ACPI dependency.
- Scope note: this repository is not a full BRS/BRS-B conformance claim.
- Reference: RISC-V BRS ratification (2025), last checked 2026-03-18.
- Board: Waveshare ESP32-C3 Zero
- SoC: ESP32-C3FH4 (RISC-V, 160MHz)
- Flash: 4MB onboard
- USB: USB-CDC (no external USB-UART chip)
- BOOT: GPIO9 (manual sequence required)
To flash the board:
- Press and hold BOOT button (GPIO9)
- Press and release RESET button
- Release BOOT button
- Run flash command
- Install ESP‑IDF v6.0 (or use VS Code ESP‑IDF extension).
- See SETUP.md for one-time PowerShell profile setup that configures all paths, tools, and convenience wrappers.
- After setup, use any of:
- VS Code: ESP‑IDF extension → Build → Flash → Monitor
- PowerShell:
idf build/idf flash/idf monitor - Optional port override:
idf -p <PORT> flash/idf -p <PORT> monitor
In PowerShell:
$env:IDF_PATH = 'C:\esp\v6.0\esp-idf'
$env:IDF_TOOLS_PATH = 'C:\Espressif\tools'
. "$env:IDF_PATH\export.ps1"
idf.py buildSee SETUP.md for full environment details, toolchain paths, and troubleshooting.
Look for these in the serial monitor:
Normal path (ordered):
BL_EVT:INITBL_EVT:HW_READYBL_EVT:PARTITION_TABLE_OKBL_EVT:DECISION_NORMALBL_EVT:APP_CRC_CHECKBL_EVT:APP_CRC_OKBL_EVT:LOAD_APPBL_EVT:HANDOFFBL_EVT:HANDOFF_APPAPP_EVT:STARTAPP_EVT:BOOTLOADER_HANDOFF_OK
Selector/update path (GPIO9):
BL_EVT:MODE_SELECT_ARMEDBL_EVT:MODE_SELECTED:UPDATE(and mode cycling on short press)BL_EVT:MODE_EXECUTE:UPDATE(long press)BL_EVT:DECISION_UPDATEis emitted when update mode is executed.- Update protocol is implemented in this repository:
- host sends
START_UPDATE - device emits
READY_FOR_CHUNK - host sends
[LEN:OFFSET:CRC16]+ payload - device emits
CHUNK_OK:<offset>orCHUNK_FAIL:<offset> - host sends
END_UPDATE - device runs app CRC gate and either hands off (
APP_CRC_OK) or stays in recovery (APP_CRC_FAIL).
- host sends
Recovery command path:
BL_EVT:DECISION_RECOVERY- no
BL_EVT:HANDOFF_APPwhile recovery is active - UART command parser is implemented (
status,reboot,update,erase,boot,?,h,help) - command responses are deterministic single-line
BL_RSP:* - idle liveness is visual-only (gentle violet LED blink)
ESP32-C3 native USB CDC disconnects during reset. Early ROM and bootloader output is invisible to idf monitor until the app reinitializes USB.
For early complete boot capture, use idf monitor (default tool). For long-running logging with timestamps and file output, use python scripts/watch_serial.py (note: starts logging after initial bootloader events already pass).
Example:
python scripts/watch_serial.py --inactivity 10See SETUP.md for full setup, watcher flags, and troubleshooting.
This repository provides a minimal bootloader demo and instructions for building and flashing on the Waveshare ESP32-C3 Zero.
Boot sequence specification: See BOOT_SEQUENCE.md for complete LED mapping, timing budget, and serial token definitions.
Validation defaults:
- Serial port auto-detection enabled by default
- Total validation timeout:
10s - Manual port override remains available
- Protocol PASS/FAIL is based on deterministic boot/app token checks.
The diagram below summarizes the normal, update, and recovery branches with the key decision points and observable serial-token milestones.
For canonical timing, LED mapping, and token definitions, see BOOT_SEQUENCE.md.
- Custom bootloader:
bootloader_components/main/main.ccontains ourcall_start_cpu0() - Component override: Our
maincomponent replaces ESP-IDF's default bootloader main - USB handling: Scripts handle ESP32-C3 USB reenumeration during reset
- Build verification: Bootloader size snapshot tracked in docs/evidence/v0.2/size_report.txt
- Secure Boot: not included (development build)
- Flash Encryption: not included (development build)
- Bootloader Log Level: ERROR (reduce noise)
- Partition Table Offset: 0x8000 (default)
- Compiler Optimization: Size (-Os)
- Full app payload CRC verification (beyond descriptor-level baseline)
- OTA update support (add ota_0, ota_1, otadata partitions)
- Image signature verification
- JTAG debugging (add ESP-PROG probe)
- USB DFU mode
- Request a scoped project with: target board, current boot blocker, desired outcome, and timeline
- Email:
exerionbit.diego@gmail.com - Web:
https://www.exerionbit.com - Use this repository as the main public reference for
First-Board Bring-UpandFactory and Field Recoveryon ESP32-C3 today; addVerified Boot Gatewhen verification pressure is already explicit, and ask separately about ESP32-C6 or other ESP32 RISC-V adaptation work - See
BOOT_SEQUENCE.mdandVALIDATION_PROFILE.mdfor the canonical contract

