Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Porting to a new MCU family

Adding a new chip series within an existing family (e.g. V00x alongside V003 in the CH32 family) is covered in Adding a new chip series.

Porting to an entirely new MCU family (e.g. STM32) requires a parallel crate. The core crates (tinyboot-core, tinyboot-protocol, tinyboot) are platform-agnostic — you implement four traits and provide a minimal HAL. Here’s what that looks like.

1. Create a tinyboot-{chip} crate

Mirror the layout of tinyboot-ch32:

  • src/hal/ — low-level register access: flash (unlock/erase/write/lock), GPIO (configure, set level), USART (init, blocking read/write/flush), RCC (enable peripherals), reset (system reset + optional jump).
  • src/platform/ — implementations of the four tinyboot_core::traits on top of the HAL.
  • src/boot.rs and src/app.rs — thin bootloader and app entry points exposing the platform to user binaries.

The four traits

TraitWhat to implement
TransportAny embedded_io::Read + Write stream — UART, RS-485, USB, SPI, even WiFi or Bluetooth. The protocol doesn’t care what carries the bytes
Storageembedded_storage::NorFlash (erase, write, read), plus as_slice() for zero-copy flash reads
BootMetaStoreRead/write boot state, trial counter, app checksum, and app size from a reserved flash page (address from linker symbol)
BootCtlrun_mode()/set_run_mode() for Service/HandOff intent across reset, reset() for software reset, hand_off() to boot the app

2. (Optional) Create a tinyboot-{chip}-rt crate

If your chip needs a custom _start + linker script to fit a small bootloader — tinyboot-ch32-rt exists for this reason on CH32 — ship one alongside. Otherwise the regular chip runtime is fine for the app.

3. Create an example workspace

Add examples/{family}/{series}/ with boot + app binaries. Each provides a memory.x defining the five standard regions (CODE, BOOT, APP, META, RAM). The core linker scripts (tb-boot.x, tb-app.x, tb-run-mode.x) handle the rest.

Linker region contract

All memory.x files define five standard regions. The crate linker scripts (tb-boot.x, tb-app.x) derive all __tb_* symbols from these regions — no magic addresses in memory.x.

RegionDescription
CODEExecution mirror (VMA) of the binary’s flash region
BOOTBootloader physical flash
APPApplication physical flash
METABoot metadata (last flash page)
RAMSRAM

What you get for free

The entire protocol (frame format, CRC, sync, commands), the boot state machine (Idle / Updating / Validating transitions, trial boot logic, app validation), the CLI, and the host-side flashing workflow all work unchanged. You only write the chip-specific glue.

Before starting a port

Please open an issue so we can discuss the approach. Some families have surprises (boot-pin muxing, flash write granularity, clock domain quirks) that we’ve already run into on CH32 and can share context on.