Contributing
Thanks for your interest in tinyboot. This page covers the dev setup, test procedures, and workflow conventions.
Before starting
- For anything bigger than a typo fix, please open an issue first so we can discuss the approach.
- New chip ports are especially welcome — see the porting guide for the trait surface you’d need to implement.
AI assistance
Parts of this project — including code, tests, and this handbook — were written with AI assistance. We’re open about that, and AI-assisted contributions from others are welcome under the same ground rules we hold ourselves to:
- AI-assisted code, tests, and documentation are accepted — but disclose it. If an AI assistant helped produce your contribution, say so in the PR description. A one-liner is enough. No need to itemize what came from where.
- You are the decision maker. Architecture, design, code quality, and correctness are your calls, not the AI’s. Don’t hand off judgment.
- You own the code, not the AI. Use your best judgment before submitting — if you wouldn’t be comfortable putting your name on it, don’t send it.
- Test on real hardware. No “it compiles” submissions for anything that touches flash, peripherals, or the boot path. Run the hardware validation checklist where it applies.
- Keep core features in system flash. The bootloader has to fit in the system-flash budget (see design notes). Non-core features can be
cfg-gated if they don’t fit for everyone. - Slop PRs will be rejected. AI-generated or not, PRs that show no sign of human review — unused code, wrong abstractions, duplicated logic, tests that don’t exercise the change, docs that hallucinate — will be closed. The policy is about thoughtfulness, not tooling.
Workspace layout
lib/ platform-agnostic core
core/ tinyboot-core
protocol/ tinyboot-protocol
ch32/ CH32 HAL + platform
rt/ tinyboot-ch32-rt (minimal bootloader runtime)
cli/ tinyboot host CLI
examples/ch32/v003/ V003 boot + app (CI testbed)
examples/ch32/v00x/ V00x boot + app
examples/ch32/v103/ V103 boot + app
docs/ user-facing documentation
Each directory is its own Cargo workspace with an independent Cargo.lock. A “clean compile” of the project therefore means wiping target/ under every workspace — see below.
Rust toolchain
- Library crates (
lib/,cli/) — stable Rust 1.85+, edition 2024. - CH32 example binaries — nightly, for
-Zbuild-stdonriscv32ec-unknown-none-elf(V003 / V00x) or the stableriscv32imc-unknown-none-elftarget (V103).
Each example workspace pins its toolchain via rust-toolchain.toml.
Running tests
# Unit tests for the platform-agnostic crates
cd lib && cargo test
# Build every example to make sure all feature combinations compile
cd examples/ch32/v003 && cargo build --release
cd examples/ch32/v00x && cargo build --release
cd examples/ch32/v103 && cargo build --release
# Host CLI
cd cli && cargo test
CI runs a matrix across chip variants and flash modes. Match that before opening a PR.
Clean compile
When hunting size regressions or build issues, a “clean compile” means removing target/ from every workspace. A leftover target/ in one workspace can mask issues in another:
find . -type d -name target -prune -exec rm -rf {} +
Then rebuild the affected workspaces.
Hardware validation
Some changes (particularly to flash, BootCtl, or the RS-485 transport) can’t be caught by unit tests and need on-hardware validation.
Integration test checklist (user-flash mode)
This is the acceptance test we run before merging flash-touching changes on CH32V003 / V103 in user-flash mode:
- Erase user flash via
wlink. - Build and flash the bootloader to the
BOOTregion. - Power-cycle the board.
- Confirm
tinyboot inforeportsmode = 0and the expectedboot_version. - Build the app.
- Flash the app via
tinyboot flash <app> --reset. - Confirm the app is running (LED blinks,
tinyboot inforeportsmode = 1). - Re-flash a different app version to exercise the update flow end-to-end.
- Trigger bootloader re-entry via
tinyboot reset --bootloader. - Re-flash the original app, confirm it still runs.
- Simulate an app that never confirms — boot should fall back to the bootloader after trials run out.
- Simulate a power loss mid-flash (disconnect power during a write); confirm recovery.
- Confirm
METAis in the expected location post-update.
Note
On CH32V103 in user-flash mode with the BOOT_CTL RC network installed, temporarily disconnect the PB1 → BOOT0 trace before running this procedure. A soft reset can otherwise latch BOOT0 HIGH and route you into system flash.
System-flash mode
System-flash validation follows the same shape but uses wlink to write to the system flash address (0x1FFFF000 on V003 / V103, 0x1FFF0000 on V00x). After writing system flash, always power-cycle before testing.
Commit and PR conventions
- Small, focused commits. Commit messages in imperative mood (e.g. “Add V00x feature flag”, “Fix FTPG partial page write”).
- A PR covering a behavior change should note how you validated it (unit test added, hardware procedure run, both).
- Keep docs changes in the same PR as the code change they describe, unless the docs are big enough to deserve their own review.
Releases
Releases are tagged vX.Y.Z across the whole repo — all crates share a version. tinyboot-ch32 stays git-only (not published to crates.io) while it depends on an unreleased ch32-metapac. The rest (tinyboot-core, tinyboot-protocol, tinyboot, tinyboot-ch32-rt) publish to crates.io.