Skip to content

OpenServoCore/tinyboot

tinyboot

CI Docs MIT Apache 2.0

A Rust bootloader for resource-constrained microcontrollers. Fits in the CH32V003's 1920-byte system flash with full trial boot, CRC16 app validation, and version reporting — leaving every byte of user flash free for your application.

tinyboot demo

Note

A note on AI assistance. Parts of this project — code, tests, and the handbook — were written with AI assistance. We disclose that upfront so you can factor it into your evaluation. Humans still own the architecture, code quality, and correctness calls: every change is reviewed by a person, validated on real hardware where it touches flash / peripherals / boot, and has to keep fitting in the system-flash size budget. AI helps with throughput, not judgment. Full policy in the contributing guide.

Supported chips

Family Status
CH32V003 ✅ Supported
CH32V00x (V002 / V004 / V005 / V006 / V007) ✅ Supported
CH32V103 ✅ Supported (needs a small BOOT0 circuit — see boot-ctl)
CH32X03x 📋 Planned

Porting to a new MCU family is a few hundred lines of glue.

Quick start (CH32V003)

Five minutes from a blank chip to an app that updates itself over UART.

1. Install the tools.

rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
cargo install wlink          # flash system flash via WCH-LinkE
cargo install tinyboot       # host CLI for UART flashing

2. Clone the repo and flash the bootloader.

git clone https://github.com/OpenServoCore/tinyboot
cd tinyboot/examples/ch32/v003/boot
cargo build --release
wlink flash --address 0x1FFFF000 target/riscv32ec-unknown-none-elf/release/boot
wlink set-power disable3v3 && wlink set-power enable3v3   # power-cycle

3. Build and flash the demo app over UART.

Connect a USB-UART adapter (TX ↔ PD6, RX ↔ PD5, GND shared), then:

cd ../app
cargo build --release
tinyboot flash target/riscv32ec-unknown-none-elf/release/app --reset

4. Confirm it's running.

tinyboot info
# capacity: 16320
# erase_size: 64
# boot_version: 0.4.0
# app_version: 1.2.3
# mode: 1            ← 1 means the app is running

LED should be blinking. To kick the device back into bootloader mode at any time:

tinyboot reset --bootloader

On CH32V00x or CH32V103, the flow is the same — swap the example directory. See Getting Started for chip-specific notes.

Where to go next

The full documentation lives at openservocore.github.io/tinyboot. Highlights:

Why tinyboot?

The CH32 factory bootloader is fixed to 115200 baud on PD5/PD6 with a sum-mod-256 checksum and no error reporting. embassy-boot is a well-designed bootloader but needs ~8 KB of flash — half the V003's total. tinyboot fits a real protocol (CRC16, trial boot, configurable transport) into 1920 bytes so every byte of user flash is yours.

For the full story and how it fits in 1920 bytes, see the design notes.

Project structure

lib/core/         tinyboot-core — boot state machine, protocol dispatcher
lib/protocol/     tinyboot-protocol — wire protocol, frame format, CRC16
ch32/             tinyboot-ch32 — HAL + platform
ch32/rt/          tinyboot-ch32-rt — minimal bootloader runtime
cli/              tinyboot — host CLI flasher
examples/ch32/    per-chip boot + app examples (also CI test targets)
docs/             user guide

Contributing

Contributions are very welcome — especially new chip ports and transports. See the contributing guide and please open an issue before starting anything big.

License

Licensed under either of Apache License, Version 2.0 or MIT License at your option.

About

Rust based embedded bootloader for resource constrained MCUs such as CH32

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors