stefanrueger / urboot

Small AVR bootloader using urprotocol
GNU General Public License v3.0
55 stars 8 forks source link
avr bootloader

Urboot

Feature-rich small AVR bootloader using urprotocol

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

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?

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

The naming convention for the .hex files is given in the larger comparison table covering a range of MCUs.