std/bootloader — Serial firmware bootloader¶
import std/bootloader
A ready-made serial bootloader that lives in the Boot Loader Section and rewrites the application section of Flash with an image streamed over USART0 by the IDE. It builds on std/boot — Flash self-programming (SPM) (SPM), std/uart — Serial USART, and std/crc — Checksums.
Everything that depends only on the chip — the Flash page size and the start of
the boot section — is selected automatically from the declared target, the
same way std/uart — Serial USART and std/gpio — Digital I/O pins pick their registers. Each per-target block
also carries its own boot directive, so importing the module automatically
locates the program in the Boot Loader Section: you do not write a boot
<addr> line yourself. The only thing you supply is the UART divisor for your
crystal and baud rate.
target atmega32
import std/bootloader
@main { @bootloader_run(51) } # 51 = 8 MHz / (16 * 9600) - 1
See std/uart — Serial USART for how to compute the UBRR divisor from your clock and baud.
Supported targets¶
The module supports the 32 KB and 64 KB ATmega parts that have a hardware UART, self-programming (SPM), and a real boot section — the ATmega32/324/325/3250/328/329/3290 and ATmega64/640/644/645/6450/649/6490 families — plus AT90CAN32 and AT90CAN64.
API¶
- @bootloader_run($ubrr: u16)¶
The entry point. Initialises USART0 at divisor
$ubrr, then waits a short startup window for the IDE to send the sync magic. If nothing syncs in time it jumps to0x0000and runs whatever application is already in Flash, so a normally-flashed board boots without the IDE attached. If sync is seen it services the upload protocol below in a loop, programming pages as they arrive and finally jumping to the new application on theRUNcommand.$ubrrisF_CPU / (16 * baud) - 1for the board’s crystal and baud.
The remaining @bl_* functions (@bl_read_into, @bl_resync,
@bl_wait_sync, @bl_write_page, @bl_dispatch) are internal helpers
used by @bootloader_run.
Safety¶
The bootloader can never erase or overwrite itself:
Every frame is CRC-16 checked; a bad CRC is NAKed and ignored.
A
WRITEis rejected unless the page address is page-aligned and the whole page lies strictly below the boot section, so writes are confined to the application area.Interrupts are disabled around every SPM sequence.
Wire protocol¶
Host (IDE) talks to the target; multi-byte integers are big-endian. Every frame
is prefixed with the 3-byte sync magic 0x1B 'i' 'k', which also lets the
bootloader resynchronise after a garbled frame.
Frame host -> target: 0x1B 'i' 'k' CMD LEN_HI LEN_LO payload[LEN] CRC_HI CRC_LO
CRC-16/ARC (poly 0xA001, init 0) over CMD, LEN_HI, LEN_LO, payload.
Reply target -> host: 0x06 (ACK) or 0x15 (NAK), then command-specific bytes.
Command |
Code |
Payload |
Reply |
|---|---|---|---|
|
0x01 |
(none) |
ACK, VER, PAGE_HI, PAGE_LO, ORIGIN_HI, ORIGIN_LO |
|
0x02 |
ADDR_HI ADDR_LO + one page of data |
ACK on success, NAK if rejected |
|
0x04 |
(none) |
ACK, then jump to the application at |
HELLO lets the host discover the device’s page size and boot-section origin
before streaming pages, so a single host tool drives any supported target.