Atmega8A BOOTSZ fuses smaller than urboot size ? (using minicore)

Hello

I burnt a bootloader (and fuses) via Minicore on Atmega8A, using an "Arduino as ISP" UNO.

As shown below, it was successful, …. but on second look, something looks weird :open_mouth:

"C:\Users\xxxxx\AppData\Local\Arduino15\packages\MiniCore\tools\avrdude\8.0-arduino.1/bin/avrdude" "-CC:\Users\xxxxx\AppData\Local\Arduino15\packages\MiniCore\tools\avrdude\8.0-arduino.1/etc/avrdude.conf" -v -patmega8 -cstk500v1 -PCOM5 -b19200 -e -Ulock:w:0xff:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:0b11010111:m -Ulfuse:w:0b00100100:m
Avrdude version 8.0-arduino.1
Copyright see https://github.com/avrdudes/avrdude/blob/main/AUTHORS

System wide configuration file is C:\Users\xxxxx\AppData\Local\Arduino15\packages\MiniCore\tools\avrdude\8.0-arduino.1\etc\avrdude.conf

Using port            : COM5
Using programmer      : stk500v1
Setting baud rate     : 19200
AVR part              : ATmega8
Programming modes     : SPM, ISP, HVPP
Programmer type       : STK500
Description           : Atmel STK500 v1
HW Version            : 2
FW Version            : 1.18
Topcard               : Unknown
Vtarget               : 0.0 V
Varef                 : 0.0 V
Oscillator            : Off
SCK period            : 0.0 us
XTAL frequency        : 7.372800 MHz

AVR device initialized and ready to accept instructions
Device signature = 1E 93 07 (ATmega8, ATmega8A)
Erased chip

Processing -U lock:w:0xff:m
Reading 1 byte for lock from input file 0xff
in 1 section [0, 0]
Writing 1 byte (0xFF) to lock, 1 byte written, 1 verified

Processing -U efuse:w:{bootloader.extended_fuses}:m
Warning: skipping -U efuse:... as memory not defined for part ATmega8

Processing -U hfuse:w:0b11010111:m
Reading 1 byte for hfuse from input file 0b11010111
in 1 section [0, 0]
Writing 1 byte (0xD7) to hfuse"C:\Users\xxxxx\AppData\Local\Arduino15\packages\MiniCore\tools\avrdude\8.0-arduino.1/bin/avrdude" "-CC:\Users\xxxxx\AppData\Local\Arduino15\packages\MiniCore\tools\avrdude\8.0-arduino.1/etc/avrdude.conf" -v -patmega8 -cstk500v1 -PCOM5 -b19200 "-Uflash:w:C:\Users\xxxxx\AppData\Local\Arduino15\packages\MiniCore\hardware\avr\3.1.1/bootloaders/urboot/atmega8/watchdog_1_s/autobaud/uart0_rxd0_txd1/led+b5/urboot_atmega8_pr_ee_ce.hex:i" -Ulock:w:0xff:m
, 1 byte written, 1 verified

Processing -U lfuse:w:0b00100100:m
Reading 1 byte for lfuse from input file 0b00100100
in 1 section [0, 0]
Writing 1 byte (0x24) to lfuse, 1 byte written, 1 verified

Avrdude done.  Thank you.
Avrdude version 8.0-arduino.1
Copyright see https://github.com/avrdudes/avrdude/blob/main/AUTHORS

System wide configuration file is C:\Users\xxxxx\AppData\Local\Arduino15\packages\MiniCore\tools\avrdude\8.0-arduino.1\etc\avrdude.conf

Using port            : COM5
Using programmer      : stk500v1
Setting baud rate     : 19200
AVR part              : ATmega8
Programming modes     : SPM, ISP, HVPP
Programmer type       : STK500
Description           : Atmel STK500 v1
HW Version            : 2
FW Version            : 1.18
Topcard               : Unknown
Vtarget               : 0.0 V
Varef                 : 0.0 V
Oscillator            : Off
SCK period            : 0.0 us
XTAL frequency        : 7.372800 MHz

AVR device initialized and ready to accept instructions
Device signature = 1E 93 07 (ATmega8, ATmega8A)
Auto-erasing chip as flash memory needs programming (-U flash:w:...)
specify the -D option to disable this feature
Erased chip

Processing -U flash:w:C:\Users\xxxxx\AppData\Local\Arduino15\packages\MiniCore\hardware\avr\3.1.1/bootloaders/urboot/atmega8/watchdog_1_s/autobaud/uart0_rxd0_txd1/led+b5/urboot_atmega8_pr_ee_ce.hex:i
Reading 372 bytes for flash from input file urboot_atmega8_pr_ee_ce.hex
in 2 sections of [0x1e80, 0x1fff]: 6 pages and 12 pad bytes
Writing 372 bytes to flash
Writing | ################################################## | 100% 0.58s
Reading | ################################################## | 100% 0.27s
372 bytes of flash verified

Processing -U lock:w:0xff:m
Reading 1 byte for lock from input file 0xff
in 1 section [0, 0]
Writing 1 byte (0xFF) to lock, 1 byte written, 1 verified

Avrdude done.  Thank you.

The flashed bootloader size is 372 bytes, and avrdude verified it successfully.

But the high fuse is D7 which decodes to

  • BOOTSZ1 unprogrammed (1)
  • BOOTSZ0 unprogrammed (1)
  • BOOTRST unprogrammed (1)

According to Atmega8A datasheet section 24.8.13 and table 24-6,

BOOTSZ works like this :

  • 11 = 128 words = 4 pages
  • 10 = 256 words = 8 pages
  • 01 = 512 words = 16 pages
  • 00 = 1024 words = 32 pages

So, if BOOTSZ[1..0] = 0b11 then the bootloader flash section

  • is 128 words (256 bytes)
  • and starts at 0xF80
  • goes until the end of the flash memory

That is where i am not understanding something :face_with_raised_eyebrow:

Question 1 : how can avrdude actually burn a 372 bytes in an actual 256 bytes boot size ?

Question 2 : shouldn't the fuses be BOOTSZ = 0b10 to get at least 256 words = 512 bytes ?

Question 3 : if not, wouldn't the bootloader be truncated ? ... then how can it still "work" ?

Thanks in advance for your insight on this, because i'm not getting it.

I don’t know why it writes 372 bytes, but the bootloader itself is only 250 bytes

The question how those bytes are counted. Perhaps it is a size of the hex file - that always bigger than binary code.

urboot provides several bootloader .hex files. It looks like the "default" one has eeprom and chip-erase support, and is 300+ bytes, even though there are versions slightly less than 256 bytes...

You are right. Minicore selects the bigger bootloader, which is 372 bytes according Avrdude.

Maybe OP ask Stefan Rueger, who wrote urboot.

@hmeijdam thanks for pointing me to avrdudess, another tool under the belt !

@b707 i checked the HEX file itself, it definitely holds 372 bytes of real information (outside of adresses, record type and checksomes) … so whatever that information is, it’s there.

@hmeijdam I found the related readme along the minicore urboot hex files (i didn't see it at first) at MiniCore/avr/bootloaders/urboot/atmega8/watchdog_1_s/autobaud/uart0_rxd0_txd1/led+b5 at master · MCUdude/MiniCore · GitHub .

And according to this statement "Size: Bootloader code size including small table at top end" ... so the extra bytes ought to be something like the Interrupt Vector table at table 12-1 and later in the datasheet.

So burning a bootloader might burn a table of the vectors too !

If so, that would make sense, size-wise :

  • the bootloader (and only itself) is burnt in the BOOTSZ-size boot area
    • and if sized as shown by avrdudess capture, it would fits in 256 byte (BOOTSZ=0b11)
  • the vector table (in the hex file) would be at 0x000 (outside BOOTSZ) (see Table 12-2)
    • its content and size is still to be determined … but that is of lesser importance :slight_smile:

So… i think that rounds it up. Even if it worked perfectly, i could not guess what explained the difference, and now i have a hint. I’ll still browse/ask urboot author page, good advice !

Thanks again, and have a nice day

TLDR; the discrepancy between BOOTSZ=3 and the bootloader size does not matter.

The example given is an urboot vector bootloader. Its size can be any multiple of the page size, which is 64 for the ATmega8A, so can be, eg, 256, 320, 384, ...

In contrast, ATmega8A's hardware-supported bootloaders only come in sizes of 256, 512, 1024 and 2048 bytes (BOOTSZ=3...0). These bootloaders need the fuse setting BOOTRST=0, where reset makes the MCU jump to the correct address of the bootloader at the top of flash, ie, to address 8192-256, 8192-512, 8192-1024 or 8192-2048 depending on BOOTSZ.

Vector bootloaders require BOOTRST=1 where reset makes the MCU jump to the reset vector at address 0. If the bootloader .hex file does not already do so, avrdude -c urclock writes to address 0 the correct rjmp to the bootloader start. Hence, BOOTSZ is irrelevant for the MCU to jump to the bootloader on reset.

The magic of bootloaders is that they are allowed to execute the spm opcode, which amongst other things can write a flash page. For MCUs that support hardware bootloading (such as the ATmega8A) the spm opcode is disabled outside the bootloader section. Urboot bootloaders only ever use one spm opcode, which is located near the end of the bootloader code. The smallest bootloader section (BOOTSZ=3) for the ATmega8A are the top 256 bytes of flash, which covers the location of the single spm urboot opcode. It doesn’t matter that some of the urboot code is below the top 256 bytes bootloader section as it’s regular code (no spm there).

2 Likes

I was planning to post a summary here but Stefan beat me to it

And with a synthetic, spot-on summary of the awesome discussion on his repo.

Great stuff, very detailed and instructive :+1:

Thanks a lot everyone.