Feature-rich small AVR bootloader using urprotocol
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)-c urclock
Urboot bootloaders can be hundreds of bytes shorter than optiboot with the same functionality, see below.
Background. More information on how bootloaders work with tips, tricks and limitations here.
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 and 5.4.0, produce pretty tight code. Linux binaries of
these are located in the src/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 this project 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 directory
src/all
. Once all these hurdles are
taken, it is easy to create own bootloaders with commands such as
$ make MCU=atmega328p AUTOBAUD=1 VBL=1 AUTOFRILLS=5..10 NAME=atmega328p_a
Alternatively, the Dockerfile may be built and used to build binaries on other systems:
$ docker run --platform linux/amd64 -v "$(pwd)/src":/src --rm -it $(docker build -q .) \
MCU=atmega328p AUTOBAUD=1 VBL=1 AUTOFRILLS=5..10 NAME=atmega328p_a
More detailed information here: make
options
Pre-compiled bootloaders. If compiling bootloaders is not feasible, feel free to try out one of
the 1,283,806 different pre-compiled bootloaders in the directory tree for MCU parts
. You can find bootloaders for
popular boards in a corresponding directory for
boards, for example, autobaud
bootloaders for the venerable ATmega328P based
Uno
with a LED on PB5, the Arduino Pro
Mini
(same bootloaders), the
Jeenode
with a low-active LED on PB1, the ATmega1284P based Moteino
Mega
and the ATmega2560 Mega R3
board;
or, eg, some 16 MHz and 115,200 baud bootloaders for the ATtiny167 based Digispark
Pro,
the ATtiny85 based
Disgispark
and the ATtiny84 based
Luminet.
Finally, there are pre-compiled urboot bootloaders for popular Arduino cores in the
cores directory of the
urboot.hex repository.
How to select a bootloader. Tips, tricks and some background here.
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
If the part does not have hardware support for bootloaders (eg,
ATtiny167
), then this is all that is needed. However, if your part has
hardware support for bootloaders (eg, ATmega328p
), then particular
attention is needed as to whether the bootloader
j
), in which case the fuses need to be programmed so that on reset
the MCU jumps to the reset vector at address 0. Ensure the lock bits do not preclude writing to
any of the boot sections (otherwise the space freed up by vector bootloaders cannot be used).h
) 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;
the boot section size fuse bits need to match the actual bootloader size (consult the data sheet
of the part); the lock bits should protect the boot section from being written to.Bootloader | FUSE_BOOTRST |
FUSE_BOOTSZ |
Lock bits for boot section |
---|---|---|---|
j |
Reset to memory start | Don't care | Read/write to everywhere |
h |
Reset to boot section | Match with usage in words | Protect boot section |
Strictly speaking vector bootloaders also need a jmp
or rjmp
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 read 0xffff
, and although not an official opcode, behave as sbrs 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
application with avrdude -c urclock
will set the reset vector correctly to jump to the
bootloader.
Some parts also need the SELFPRGEN
fuse set allowing the vital spm
opcode (store to program
memory) to be executed without which bootloaders cannot write to flash.
Once the board has its bootloader the board 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 facts. avrdude -c urclock
can keep bootloaders in terminal mode -t
without the
bootloader resetting itself through the watchdog timer. avrdude -c urclock
keeps metadata of the
uploaded program, which are displayed with avrdude -c urclock -xshowall
. Urboot bootloaders tell
avrdude exactly which part they were compiled for; hence, -c urclock
is the only programmer
for which the part does not need specifying via -p
.
Trouble shooting. So, you have selected the right bootloader for your board and followed above but programming does not work as expected?
hexls
will be in
bytes but the data sheets often specify BOOTSZ
in words (note the factor of 2).RX
pin that the bootloader was compiled with
(typically, the RX
pin of the processor's USART) needs to be connected to the TX
pin
(not the RX
pin) of the USB/serial converter chip and vice versa. If the board has a
USB/serial converter, check to which processor pins it is connected and verify these are the
RX/TX pins that the bootloader was compiled with.TX
side of the board. Some boards run at a different voltage than 5V USB; they may need their
own power supply (in which case connect GND, but do not connect the different Vcc); they may
need voltage level shifters.WDTO
time (typically
one second).CKDIV8
fuse been programmed? Then the MCU runs slower by a
factor of 8.avrdude
baud rate match the bootloader's? Try an eighth of the nominal bootloader
baud rate in case CKDIV8
is programmed. Autobaud bootloaders only recognise 256 different
baud rates: F_CPU/8n where n is 1..256; is the used baud rate close to an auto-detectable one?blink.hex
sketch (uploaded with a physical programmer)Comparison. The table below lists a sample of urboot
bootloaders and their features alongside
vanilla optiboot and its larger bigboot variant for EEPROM access. They are all for a 16 MHz MCU
and 115,200 baud serial communication speed, except for the autobaud ones, which should work
for all F_CPU
and a range of associated baudrates.
Size | Usage | Version | Features | Hex file |
---|---|---|---|---|
190 | 192 | u8.0 | ----jpr-- |
attiny2313_min.hex |
248 | 256 | u8.0 | w---jPr-- |
urboot_m328p_1s_x16m0_115k2_uart0_rxd0_txd1_led+b5_pr.hex |
256 | 256 | u8.0 | we--jpr-- |
attiny2313_emin.hex |
384 | 384 | u8.0 | weU-jPrac |
urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+b5_pr_ee_ce.hex |
454 | 512 | u7.7 | wes-hprac |
urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+b5_ee_ce_hw_stk500.hex |
474 | 512 | o8.3 | --s-h-r-- |
optiboot_atmega328.hex from the optiboot project |
504 | 512 | u8.0 | weUdhprac |
urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+d5_csb0_dual_ee_ce_hw.hex |
512 | 512 | u8.0 | weUdhprac |
atmega328p_ad.hex |
710 | 1024 | o8.3 | -es-h-r-- |
bigboot_328.hex from the optiboot project |
w
bootloader provides pgm_write_page(sram, flash)
for the application at FLASHEND-4+1
e
EEPROM read/write supportU
checks whether flash pages need writing before doing sos
uses skeleton of STK500v1 protocol (only u7.7); -c urclock
and -c arduino
both OKd
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: applications need to be patched externally, eg, using avrdude -c urclock
p
bootloader protects itself from being overwrittenP
vector bootloader only: protects itself and reset vector from being overwrittenr
preserves reset flags for the application in the register R2a
autobaud detection (f_cpu/8n using discrete divisors, n = 1, 2, ..., 256)c
bootloader provides chip erase functionality (only recommended for large MCUs)-
corresponding feature not presentThe naming convention for the .hex
files is given in the larger comparison table covering a range of MCUs.