Feature-rich small AVR bootloader using urprotocol
- Tight code: most bootloaders fit into
- 256 bytes albeit without EEPROM read/write support
- 384 bytes with EEPROM read/write support
- 512 bytes with dual-boot, EEPROM read/write support and Chip Erase capability
- High default baud rate 115200 for fast programming
- Highly modular feature set:
- EEPROM read/write support
- Vector bootloader for devices without a boot section or to save space on devices with one
- Software UART: no hardware UART required, but also useful when the chip's CPU frequency and the bootloader's desired baudrate are incompatible (eg, 8 MHz and 115200 baud)
- Subroutine
pgm_write_page(sram, progmem)
for applications so they can change themselves: on many MCUs the SPM write flash only works when called from the bootloader section (default on) - Dual programming from external SPI flash memory for over-the-air programming
- Template bootloader with nops that can be replaced at bootloader-burning time on the fly with code to operate the right LED/TX/RX/CS pins (see accompanying urloader sketch once published)
- Saves the reset flags in R2 for inspection by the application via the .init0 section (default on)
- Bootloader protects itself from overwriting (default on)
- Avrdude supports urboot bootloaders with
-c urclock
from v7.2
Documentation. In the first instance, the first 600 or so lines of urboot.c
give a good
insight.
Compiling an urboot bootloader. The small sizes of urboot
bootloaders depend on many a trick
of the trade, most of which only work with the avr-gcc toolchain used for compilation. It turns out
that two older avr-toolchains, version 4.8.1 or 5.4.0, produce pretty tight code. Linux binaries of
these are located in the avr-toolchain
directory. This project uses helper programs in perl: an
avr-gcc wrapper urboot-gcc
and hexls
that shows stats of the produced .hex
files. So, all
things considered, compiling your own, is easiest on Linux with perl installed and some required
perl libraries, too (install them with cpan
). All going well make all
should produce .hex
,
.elf
and .lst
files of a number of bootloaders. The created .hex files should coincide with the
corresponding ones in the all
directory.. Once all these
hurdles are taken, it is pretty easy to create own bootloaders with commands such as
$ make MCU=atmega328p F_CPU=16000000L BAUD_RATE=115200 EEPROM=1 URPROTOCOL=1 \
LED=AtmelPB1 SFMCS=AtmelPB0 DUAL=1 FRILLS=7 MOVETO=moteino-dual
Pre-compiled bootloaders. If compiling bootloaders is not feasible, feel free to try out one of
the roughly 110,000 different pre-compiled bootloaders in the directory tree
bootloaders
. The tree
contains are actually some 350,000 hex files, but they are somewhat redundant because a bootloader
on 115200 baud for 16 MHz is exactly the same as a bootloader on 57600 baud for 8 MHz.
Usage. As with all bootloaders, one needs to first program them onto the board/chip using a (physical) programmer and an uploader program, eg, through
$ avrdude -c usbasp -p m328p -U flash:w:bootloader.hex:i
Particular attention is needed as to whether
- The bootloader assumes hardware support (
h
, see below) and sits in a dedicated HW boot section, in which case the fuses need to be set to ensure that on reset the MCU jumps to the correct bootloader start and that the lock bits do not preclude writing to the boot sections (otherwise this space cannot be used), or whether - The bootloader is a vector bootloader (
j
,v
orV
, see below), in which case the fuses need to be programmed so that on reset the MCU jumps to the reset vector 0. Strictly speaking vector bootloaders also need ajmp
orrjmp
from the reset vector at address 0 to the bootloader. However, if the chip was erased before putting the bootloader on, then this is not necessary: Erased words read0xffff
, and although this is not an official opcode, it behaves assbrs r31,7
(skip one instruction if bit 7 in R31 is set). A reset to address 0 on an otherwise erased flash will therefore eventually run into the start of the bootloader. Uploading the first sketch withavrdude -c urboot
will then set the reset vector correctly to jump to the bootloader.
Once the board has its bootloader it can be directly connected to and programmed from the host/laptop/PC (without a physical programmer), eg, through
$ avrdude -c urclock -p m328p -b 115200 -P /dev/ttyUSB0 -U flash:w:mysketch.hex:i
$ avrdude -c urclock -p m328p -b 115200 -P /dev/ttyUSB0 -U eeprom:r:backup.eep:I
$ avrdude -c urclock -p m328p -b 115200 -P /dev/ttyUSB0 -t
Voila!
Fun fact. avrdude -c urclock
can keep bootloaders in terminal mode -t
without the
bootloader resetting itself through the watchdocg timer.
Comparison. The table below lists a sample of urboot
bootloaders and their features alongside
vanilla optiboot. They are all for a 16 MHz MCU and 115200 baud serial communication speed, except
where noted differently. Note that the USART on an 8 MHz ATmega328P cannot produce 115200 baud
within a 2.5% tolerance. The examples shown use software I/O that allows for a finer baud
granularity.
- Size: Bootloader code size including small table at top end
- Usage: How many bytes of MCU flash are needed, ie, HW boot section or a multiple of the page size
- Version: For example, u7.6 is an urboot version, o5.2 is an optiboot version
- Features:
w
urboot providespgm_write_page(sram, flash)
for the application atFLASHEND-4+1
e
EEPROM read/write supportu
uses urprotocol and requiresavrdude -c urclock
for programmings
uses skeleton of STK500v1 protocol;-c urclock
or-c arduino
both workd
dual boot (over-the-air programming from external SPI flash)h
hardware boot section: make sure fuses are set for reset to jump to boot sectionj
vector bootloader: uploaded applications need to be changed externally, eg, usingavrdude -c urclock
p
bootloader protects itself from being overwrittenr
preserves reset flags for the application in the register R2
- Hex file naming convention: MCU, oscillator frequency and baud rate followed by
rxd0 txd1
software I/O using, in this example, lines RXD0
and TXD1
ee
bootloader supports EEPROM read/writeled-b1
toggles an active-low LED on pinB1
,+
designates an active-high LEDlednop
template bootloader containsmov rx,rx
nops that can be replaced to toggle LEDscsb0
for dual boot uses, in this example, pin B0 as chip select of external SPI flash memorycsnop
likelednop
generates nops that can be replaced to toggle the correct CS pinfr
bootloader provides non-essential code for smoother error handingce
bootloader provides a chip erase commandur
uses urprotocol and requiresavrdude -c urclock
for programmingvbl
vector bootloader: set fuses to jump to reset, not the HW boot section