Minimal bare-metal RISC-V UART bootloader
Assembly entry • CRC32 validation • Portable HAL • QEMU reference for fast real-hardware ports (ESP32-C3 ready)
- Fast, minimal, open-source RISC-V bootloaders — production-ready in days, fully auditable, no proprietary lock-in.
- This QEMU-validated reference is your clean, portable starting point for custom ESP32-C3 or similar MCUs.
Prerequisites:
- RISC-V toolchain (
riscv-none-elf-gccor equivalent) - GNU Make
- QEMU (system emulation)
Build and run:
make all # Compile bootloader
make qemu # Run in QEMURun automated tests:
python3 test_validator.py # Protocol validation testRun live visual validation (Windows PowerShell):
.\scripts\run-test-with-uart-tail.ps1Demo capture mode (for terminal recording/GIF preparation):
.\scripts\run-test-with-uart-tail.ps1 -DemoModeExpected output: Bootloader waits for UART input, displays BOOT?
📖 Detailed setup instructions: See SETUP.md
- Fast adaptation: Portable HAL + clear separation enable ports in hours or days — ideal for IoT prototypes.
- No vendor lock-in: 100% open-source under the MIT License; no proprietary SDKs or vendor binaries.
- Audit & debug friendly: Explicit C and assembly with minimal abstractions — excellent for security reviews and compliance.
- Proven in QEMU virt: Validated in QEMU virt and designed bottom-up to migrate to real hardware without surprises.
- Full ownership: Complete source delivered so you can adapt, audit, and ship with confidence.
Perfect for:
- Hardware startups prototyping IoT devices
- Small OEMs with custom boards needing controlled boot behavior
- Makers & labs moving from Arduino to production-grade firmware
- Consultancies building complete firmware stacks
Perfect base for your next ESP32-C3 product — from prototype to small production runs.
- Ready for production: minimal, auditable, and portable code you can trust.
- Accelerates time-to-market: small, focused codebase reduces integration overhead.
- Low-risk migration: QEMU-validated path from prototype to hardware.
- Reliable bare-metal startup (assembly
_startwith stack/BSS init) - Human-readable UART update protocol (115200 8N1)
- CRC32 + magic number + size firmware validation
- Compact footprint (default ~64 KB for bootloader)
- Clean handoff to application
- Portable HAL for easy porting
- UART/USB update for your specific board
- GPIO/timeout recovery trigger
- LED signaling (e.g., Waveshare ESP32-C3 Zero RGB)
- Fast delivery: 1–3 days with full source and total ownership
Let's build simple, dependable boot infrastructure — fast and 100% yours!
riscv-bootloader/
├── src/ # Core logic (OS-agnostic)
├── include/ # Definitions & HAL interfaces
├── linker/ # Linker scripts (memory.ld)
├── boards/ # Board-specific HAL
│ └── qemu_virt/ # Default: QEMU RISC-V Virt
├── Makefile # Build system
└── README.md
| Region | Address | Size | Description |
|---|---|---|---|
| FLASH | 0x00000000 | 64 KB | Bootloader code |
| APP | 0x00010000 | 448 KB | Application binary partition |
| RAM | 0x80000000 | 128 KB | Runtime (stack, data, BSS) |
See linker/memory.ld and include/boot.h for details.
- Bootloader sends:
BOOT? - Host sends any char (e.g.
u) → enter update mode - Bootloader:
OK - Host:
SEND <size>\n(decimal size) - Bootloader:
READY(after flash erase) - Host sends raw binary data
- Bootloader:
CRC?→OK→REBOOT
- Create
boards/<your_board>/ - Implement
platform.cwith HAL functions frominclude/boot.h(uart_init(),uart_putc(), etc.) - Optional: GPIO/LED init for signaling
- Adjust
linker/memory.ldfor real flash/RAM map - Update
Makefilefor new target - Build & flash with
esptool.py/ OpenOCD
- ✅ QEMU virt reference fully working
- ✅ Windows native support (tested)
- ✅ Linux / WSL / macOS support
📖 For detailed setup instructions and troubleshooting, see SETUP.md