Skip to content

Commit

Permalink
Merge pull request #34 from stefanrueger/u8.0
Browse files Browse the repository at this point in the history
Urboot 8.0
  • Loading branch information
stefanrueger authored Jun 11, 2024
2 parents ee9c826 + 9de68d6 commit d9e35e5
Show file tree
Hide file tree
Showing 2,214 changed files with 20,949 additions and 6,039 deletions.
29 changes: 14 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
+ Bootloader protects itself from overwriting (default on)
+ Automatic host baud rate detection
+ Chip erase in bootloader (faster than -c urclock emulation)
+ Update flash feature that tries to wear out flash less (and is faster)
- Avrdude (from v7.1 onwards) supports urboot bootloaders with `-c urclock`

Urboot bootloaders can be hundreds of bytes shorter than
Expand All @@ -47,14 +48,14 @@ with the corresponding ones in the directory
[`src/all`](https://github.com/stefanrueger/urboot/tree/main/src/all). Once all these hurdles are
taken, it is easy to create own bootloaders with commands such as
```
$ make MCU=atmega328p F_CPU=16000000L BAUD_RATE=115200 EEPROM=1 URPROTOCOL=1 \
$ make MCU=atmega328p F_CPU=16000000L BAUD_RATE=115200 EEPROM=1 \
LED=AtmelPB1 SFMCS=AtmelPB0 DUAL=1 FRILLS=7 NAME=moteino-dual
```

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 F_CPU=16000000L BAUD_RATE=115200 EEPROM=1 URPROTOCOL=1 \
MCU=atmega328p F_CPU=16000000L BAUD_RATE=115200 EEPROM=1 \
LED=AtmelPB1 SFMCS=AtmelPB0 DUAL=1 FRILLS=7 NAME=moteino-dual
```
More detailed information here: [`make` options](https://github.com/stefanrueger/urboot/blob/main/docs/makeoptions.md)
Expand Down Expand Up @@ -193,24 +194,24 @@ for all `F_CPU` and a range of associated baudrates.

|Size|Usage|Version|Features|Hex file|
|:-:|:-:|:-:|:-:|:--|
|222|224|u7.7|`w-u-jpr--`|[urboot_t2313_1s_x16m0_115k2_uart0_rxd0_txd1_lednop.hex](https://raw.githubusercontent.com/stefanrueger/urboot.hex/main/mcus/attiny2313/watchdog_1_s/external_oscillator_x/16m000000_hz/+115k2_baud/uart0_rxd0_txd1/lednop/urboot_t2313_1s_x16m0_115k2_uart0_rxd0_txd1_lednop.hex)|
|256|256|u7.7|`w-u-jPra-`|[urboot_t2313_1s_autobaud_uart0_rxd0_txd1_lednop.hex](https://raw.githubusercontent.com/stefanrueger/urboot.hex/main/mcus/attiny2313/watchdog_1_s/autobaud/uart0_rxd0_txd1/lednop/urboot_t2313_1s_autobaud_uart0_rxd0_txd1_lednop.hex)|
|252|256|u7.7|`w-u-jPr--`|[urboot_m328p_1s_x16m0_115k2_uart0_rxd0_txd1_led+b5.hex](https://raw.githubusercontent.com/stefanrueger/urboot.hex/main/mcus/atmega328p/watchdog_1_s/external_oscillator_x/16m000000_hz/+115k2_baud/uart0_rxd0_txd1/led+b5/urboot_m328p_1s_x16m0_115k2_uart0_rxd0_txd1_led+b5.hex)|
|368|384|u7.7|`weu-jPrac`|[urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+b5_pr_ee_ce.hex](https://raw.githubusercontent.com/stefanrueger/urboot.hex/main/mcus/atmega328p/watchdog_1_s/autobaud/uart0_rxd0_txd1/led+b5/urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+b5_pr_ee_ce.hex)|
|438|512|u7.7|`wes-hpr-c`|[urboot_m328p_1s_x16m0_115k2_uart0_rxd0_txd1_led+b5_ee_ce_hw_stk500.hex](https://raw.githubusercontent.com/stefanrueger/urboot.hex/main/mcus/atmega328p/watchdog_1_s/external_oscillator_x/16m000000_hz/+115k2_baud/uart0_rxd0_txd1/led+b5/urboot_m328p_1s_x16m0_115k2_uart0_rxd0_txd1_led+b5_ee_ce_hw_stk500.hex)|
|454|512|u7.7|`wes-hprac`|[urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+b5_ee_ce_hw_stk500.hex](https://raw.githubusercontent.com/stefanrueger/urboot.hex/main/mcus/atmega328p/watchdog_1_s/autobaud/uart0_rxd0_txd1/led+b5/urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+b5_ee_ce_hw_stk500.hex)|
|474|512|o8.3|`--s-h-r--`|[optiboot_atmega328.hex](https://raw.githubusercontent.com/stefanrueger/urboot/main/src/all/optiboot_atmega328.hex)|
|496|512|u7.7|`weudhprac`|[urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+d5_csb0_dual_ee_ce_hw.hex](https://raw.githubusercontent.com/stefanrueger/urboot.hex/main/boards/urclockusb/atmega328p/watchdog_1_s/autobaud/uart0_rxd0_txd1/led+d5_csb0_dual/urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+d5_csb0_dual_ee_ce_hw.hex)|
|710|1024|o8.3|`-es-h-r--`|[bigboot_328.hex](https://raw.githubusercontent.com/stefanrueger/urboot/main/src/all/bigboot_328.hex)|
|190|192|u8.0|`----jpr--`|[attiny2313_min.hex](https://raw.githubusercontent.com/stefanrueger/urboot/main/src/all/attiny2313_min.hex)|
|248|256|u8.0|`w---jPr--`|[urboot_m328p_1s_x16m0_115k2_uart0_rxd0_txd1_led+b5_pr.hex](https://raw.githubusercontent.com/stefanrueger/urboot.hex/main/mcus/atmega328p/watchdog_1_s/external_oscillator_x/16m000000_hz/+115k2_baud/uart0_rxd0_txd1/led+b5/urboot_m328p_1s_x16m0_115k2_uart0_rxd0_txd1_led+b5_pr.hex)|
|256|256|u8.0|`we--jpr--`|[attiny2313_emin.hex](https://raw.githubusercontent.com/stefanrueger/urboot/main/src/all/attiny2313_emin.hex)|
|384|384|u8.0|`weU-jPrac`|[urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+b5_pr_ee_ce.hex](https://raw.githubusercontent.com/stefanrueger/urboot.hex/main/mcus/atmega328p/watchdog_1_s/autobaud/uart0_rxd0_txd1/led+b5/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](https://raw.githubusercontent.com/stefanrueger/urboot.hex/main/u7.7/mcus/atmega328p/watchdog_1_s/autobaud/uart0_rxd0_txd1/led+b5/urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+b5_ee_ce_hw_stk500.hex)|
|474|512|o8.3|`--s-h-r--`|[optiboot_atmega328.hex](https://raw.githubusercontent.com/stefanrueger/urboot/main/src/all/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](https://raw.githubusercontent.com/stefanrueger/urboot.hex/main/boards/urclockusb/atmega328p/watchdog_1_s/autobaud/uart0_rxd0_txd1/led+d5_csb0_dual/urboot_m328p_1s_autobaud_uart0_rxd0_txd1_led+d5_csb0_dual_ee_ce_hw.hex)|
|512|512|u8.0|`weUdhprac`|[atmega328p_ad.hex](https://raw.githubusercontent.com/stefanrueger/urboot/main/src/all/atmega328p_ad.hex)|
|710|1024|o8.3|`-es-h-r--`|[bigboot_328.hex](https://raw.githubusercontent.com/stefanrueger/urboot/main/src/all/bigboot_328.hex) from the optiboot project|

- **Size:** Bootloader code size including small table at top end
- **Usage:** How many bytes of 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` bootloader provides `pgm_write_page(sram, flash)` for the application at `FLASHEND-4+1`
+ `e` EEPROM read/write support
+ `u` uses urprotocol requiring `avrdude -c urclock` for programming
+ `s` uses skeleton of STK500v1 protocol (deprecated); `-c urclock` and `-c arduino` both work
+ `U` checks whether flash pages need writing before doing so
+ `s` uses skeleton of STK500v1 protocol (only u7.7); `-c urclock` and `-c arduino` both OK
+ `d` 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 section
+ `j` vector bootloader: applications *need to be patched externally*, eg, using `avrdude -c urclock`
Expand All @@ -222,5 +223,3 @@ for all `F_CPU` and a range of associated baudrates.
+ `-` corresponding feature not present

The naming convention for the `.hex` files is given in the [larger comparison table covering a range of MCUs](https://github.com/stefanrueger/urboot/blob/main/docs/comparison.md).

**Bugs.** The code still defaults to `URPROTOCOL=0`. The urprotocol should be chosen by default! :)
37 changes: 17 additions & 20 deletions docs/background.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ hardware or protocol error occurred during burning/verification or when the boot
task successfully. Watchdog timeout resets the MCU just like an external reset. When the bootloader
is entered under this condition, though, it then normally jumps directly to the application.
However, when the bootloader was compiled with dual-boot support, it first checks external SPI
flash memory to see it contains a new sketch, in which case a copy of it is burned from external
flash memory to see if it contains a new sketch, in which case a copy of it is burned from external
memory onto internal flash. The idea is that the application sketch could have been written to
receive a new version via a radio and have placed it onto the external SPI flash memory before
issuing a WDT reset. Hence, this dual-boot property is also called over the air programming,
Expand Down Expand Up @@ -67,30 +67,27 @@ actual app is started. Here some choices for the first decision:
- The bootloader sets the TX line of the UART or the designated TX pin of the software serial
communication to output after every reset. If the bootloader is compiled to blink an LED, to
output a square wave for debugging or to communicate via SPI with external memory for dual
programming, there will be other lines that are set to output shortly after each reset. Not
all projects can deal gracefully with these short flares of output activity on some of the
pins. If you use a bootloader for production settings it is best to carefully consider the
programming, there will be other lines that are set to output shortly after each reset. Not all
projects can deal gracefully with these short flares of output activity on some of the pins. If
you use a bootloader for production settings it is best practice to carefully consider the
hardware implications on the circuit.

- As with all bootloaders they work best when the host has a way to reset the board, which is
typically done via DTR/RTS lines of the host's serial port. Avrdude -c [arduino|urclock]
does this automatically. The board needs to have hardware to facilitate the DTR/RTS
connection for reset. Most boards do. If not, sometimes running a small dedicated reset
program on the host just before running avrdude helps. This reset program somehow needs to
pull the board's reset line low for a short time; on a Raspberry Pi external GPIO pins can
be used for that. If that is not possible either, then setting the watchdog timeout to a
long time (see the WDTO option below) may be helpful, so one can manually reset the board
before calling avrdude. The default for the timeout is 500 ms, but only with the urclock
programmer can small timeouts down to 256 ms be reliably utilised.
typically done via DTR/RTS lines of the host's serial port. Avrdude -c [arduino|urclock] does
this automatically. The board needs to have hardware to facilitate the DTR/RTS connection for
reset. Most boards do. If not, sometimes running a small dedicated reset program on the host
just before running avrdude helps. This reset program somehow needs to pull the board's reset
line low for a short time; on a Raspberry Pi external GPIO pins can be used for that. If that
is not possible either, then setting the watchdog timeout to a long time (see the WDTO option
below) may be helpful, so one can manually reset the board before calling avrdude. The default
for the timeout is 1 s when using `make`, but the urclock programmer can utilise timeouts down
to 256 ms. When compiling directly using the `urboot-gcc` wrapper the default timeout is 512 ms.


## Assumptions, limitations, caveats, tips and tricks for *this* bootloader

- The uploading program is assumed to be avrdude with either the arduino or urclock
programmer: call avrdude -c [arduino|urclock] for this. I have not tested other uploaders.
The tightest bootloader code (see URPROTOCOL=1 option below) requires avrdude's urclock
programmer as this forgoes some get/put parameter calls that arduino issues unnecessarily
and uses its own leaner protocol.
- The uploading program is assumed to be AVRDUDE with the urclock programmer: use `avrdude -c
urclock`

- A bootloader with dual-boot support needs to know which port pin is assigned to the chip
select of the SPI flash memory, which pin drives a blinking LED (if wanted), where the tx/rx
Expand Down Expand Up @@ -122,7 +119,7 @@ actual app is started. Here some choices for the first decision:
+ Vector table of the MCU, and therefore the reset vector, resides at address zero
+ Compiler puts either a jmp or an rjmp at address zero
+ Compiler does not zap/shorten the vector table if no or few interrupts are used
+ Compiler does not utilise unused interrupt vectors to place code there
+ Compiler does not utilise unused interrupt vectors to place code/data there

This should be the case with all regular sketches produced by avr-gcc. Vector bootloaders are
also useful for devices with boot section support to allow them to use less space than the
Expand All @@ -131,7 +128,7 @@ actual app is started. Here some choices for the first decision:
protection bits in the lock byte actually allow code be written into the bootloader section
with SPM instructions. Otherwise the extra space in the boot section that is freed by smaller
vector bootloaders cannot be used. The urloader sketch sets fuses and lock bits appropriately
when burning a vector bootloader onto your board. More on VBLs below.
when burning a vector bootloader onto your board.

- The code makes several assumptions that reduce the code size (eg, no interrupts can occur, the `USART`
character size register defaults to 8N1). They are true after a hardware reset, but will not
Expand Down
Loading

0 comments on commit d9e35e5

Please sign in to comment.