Bootloader that fits in 256 words

Hi everybody,

I'm new to the arduino, so I'm not sure if I simply didn't search good enough in this forum or if my "invention" is really new...

I managed to shrink the bootloader to fit in 512 bytes by porting it to plain assembler. This is only for the ATMega8 now - but that's where the additional 512 bytes available for the user program are of special value!

I also did not find a way to attach anything to this message, so I will wait for now if anyone is interested - and if so, maybe someone shows me how to post a file here, or I will provide a link to my webspace.


I also did not find a way to attach anything to this message ...

Try again, you can't do that on your [u]first[/u] post but you should be able to now.


Thanks Don, so OK, here we go again.

Hmm, I still do not see any possibility to post a file… :frowning:

I will try a third post before giving up.

Still no attachments...

Giving up now, here is an external link:

Some notes on the bootloader

  • Bootloader is entered, if the MOSI pin is grounded (jumper on the ICSP connector pins 4&6)
  • Bootloader is also entered if there is no code in the user area (0x0000 = 0xFF)
  • Bootload does NOT exit to execute the user program automatically after a timeout, you need to switch off/on!
  • The LED on pin PB5 (digital 13) lights up when the bootloader is entered and stays on
  • The standard baudrate 115200 works
  • The preassembled HEX in the archive is for an ATMega8 running at 16MHz with 115200 baud


No, that info seems wrong on the attachments . I think it may have been closed due to server overloading problems. If you link to a picture I think it can be made to display here and you can add code etc but no files it seems.

Your bootloader could be useful for me . I thought I would buy one of these cheap boards and a chip and try throwing it together . When it arrived it was a blank Mega8 . I put a bootloader on it via the IDE and another arduino . I didnt have a resonator so I threw in a 14.890Mhz one I had on an old throwaway board.

Then I found out I had to recompile the bootloader for it to be programable directly rather than in the other arduino so thats where I stopped . $3 spent and much learnt.

So could you recompile one for me with this frequency ? I ask because you seem to know what you are doing and can do it quickly whereas this is a one off for me. I wont be doing it again I should think. If you can't ,can you tell me how to do that? I already tried "avr-gcc arduinoBOOT.s "with your assembler file but got lots of error messages as below .

[tytower@localhost Download]$ avr-gcc -mmcu=atmega8 -c ArduinoBOOT.s
ArduinoBOOT.s: Assembler messages:
ArduinoBOOT.s:94: Error: constant value required
ArduinoBOOT.s:94: Error: register number above 15 required
ArduinoBOOT.s:95: Error: constant value required
ArduinoBOOT.s:95: Error: constant value required
ArduinoBOOT.s:96: Error: constant value required
ArduinoBOOT.s:96: Error: register number above 15 required
ArduinoBOOT.s:99: Error: constant value required
ArduinoBOOT.s:99: Error: constant value required
ArduinoBOOT.s:101: Error: constant value required
ArduinoBOOT.s:102: Error: constant value required
ArduinoBOOT.s:102: Error: register number above 15 required
ArduinoBOOT.s:105: Error: constant value required
ArduinoBOOT.s:105: Error: constant value required
ArduinoBOOT.s:108: Error: constant value required
ArduinoBOOT.s:108: Error: register number above 15 required
and lots more........


I have attached an even more shrunk version that I made over the weekend.

Here are the news:

  • Makefile and configuration within makefile added - see there
  • Bootloader timeout (how long it will wait for ISP commands before rebooting into user code) now implemented, specified in seconds.
  • Watchdog and brownout resets can jump directly into usercode again - bypassing the bootloader
  • More MCUs implemented (Atmega8,16,32,88,168,328p,128,1280) - only tested with ATMega8, 16 and 32. Need feedback on other MCUs.

Btw, is there interest for the bootloader to be adapted for the ATMega48?

@tytower: As I can see, you have avr-gcc installed, so you can assemble it yourself with your parameters - just edit the configuration section in the makefile and then call make...



Probably most of us on here do mot have your programming level of expertise. I got stuck on the make approach and have no idea how to fix it

$  make
make: *** No rule to make target `makefile', needed by `ArduinoBOOT.o'.  Stop.

EDIT- running "make -f Makefile " gave no joy either until I found the reference to Makefile(in the Makefile) which was a small "m" ,makefile instead of a capital "M" Makefile. Then it compiled . Bugger me ! That's not the area to be careless.

OK, I see the problem… I am working under Windows, you have Linux. Linux is case sensitive, windows is not… :-/

You can:
a) rename the “Makefile” to “makefile”
b) edit Makefile line 85, at the end of the line to read “Makefile” instead of “makefile” - which is what is present in future versions
c) download the zip below which has everything set up…

Probably most of us on here do mot have your programming level of expertise. I got stuck on the make approach and have no idea how to fix it

Hmm, then the only way would be to assemble every possible configuration (CPU clock, baudrate etc) and put them somewhere…

Btw., the bootloader has still bugs when tried to be used with anything other than ATMega8, ATMega16 or ATMega32 !
This means presently NO ATMega88, 168, 328, 128 or 1280 support. Problem is, the UART registers are in the extended io space that cannot be accessed with IN/OUT but only with LDS/STS instructions (which I didn’t notice until now). Each instruction takes 4 bytes instead of 2 - and as there are quite a few registers to be set, the loader possibly does not fit into 256 words anymore, depending on the boot options (BL_CHECK, WDT_CHECK, )…

It still fits if:

  1. assembled with BL_CHECK, CODE_CHECK and USE_LED on, WDT_CHECK and BL_TIMEOUT off - this means you have to short two pins if you want to get into bootloader, and if you are in it you must remove the short and cycle power to get into user code.
  2. assembled with USE_LED and BL_TIMEOUT on, all other options (CODE_CHECK, BL_CHECK, WDT_CHECK) off.


  • Use LDS/STS instead of IN/OUT for ATmegaxx8 and 128x


Good stuff Jim Thank you for that. I stumbled on it and got it uploaded but could not get it to load a sketch so I changed the baud rate back to 19200 for me and when redone it loaded beautifully.

Its only frustrating until it works then everything is hunkey dorey - have you noticed.

I can confirm it works fine at 19200 baudrate for my ATmega8 chip running at 14.890000 Mhz and for the pretty slow like me to save time just follow this

Jims bootloader-Linux Fedora11 Change Makefile line 15 16000000 to 14890000 23 BAUDRATE 115200 to 19200 84 Capital "M" for Makefile use a terminal to enter directory and type "make"

Copy the created ArduinoBOOT.hex into the Arduino-0017/hardware/bootloaders/atmega8/ file and rename the old ATmegaBOOT.hex to OldATmega.hex. Now rename ArduinoBOOT.hex to ATmegaBOOT.hex

Now put the bootloader on the chip through the normal Arduino IDE

HHey Jim , Ive just noticed the bootloader burns on to the chip OK (Im using ATtinyISP) and then you can upload a sketch with an ftdi cable( eg the heartbeat sketch) but when I try to upload another sketch after that it will not upload.

It appears that once a sketch is uploaded to your bootloader it will not accept another ,I have tried probably 30 times and reburnt the bootloader 5 times just to test this.

Can you suggest a reason for this . My arrangements are as per the previous post

Which software options did you use? If you take the default settings that are present in the v0.03 archive, the boot sequence is as follows:

  • 1st) Look if CODE location 0000h, the reset vector of a loaded sketch, is FFh (unprogrammed). If yes -> jump to bootloader.
  • 2nd) See if bootloader pin (by default: PB3) is low. If yes -> jump to bootloader.
  • 3rd) Check if reset was caused by the watchdog or by a brown-out. If not -> jump to bootloader.
  • 4th) If we reach here, start the sketch.

So, even if PB3 is not grounded, you should land in the bootloader after a poweron. Then you have (by default, set in the makefile) no more than 4 seconds to start the upload process. If you wait any longer, the bootloader will restart your sketch. You can prolong this time in the makefile if you want - but 4 seconds seemed to be a good compromise between annoyance after a reset and stress to be quick enough to invoke the upload.

OOPS, I just noticed, that I reversed the pin definitions for the LED and the bootloader pin in the makefile!!!!! The LED is defined to be at PB3 and the bootloader pin at PB5, but this must be the other way round - or at least, the LED must be set to PB5...! I didn't see this, as I am using a STK500 board for testing, where the LED lights up when a LOW on PB5 is output. PB5 is in high impedance after reset (with a pullup on the board, which makes the pin HIGH), the bootloader then outputs an active HIGH when entered. So the pin is always HIGH, and my LED never lights up...

But, if you do not use the bootloader pin, this does not change anything in the behaviour of the boot process detailed above - except if the LED on the (incorrect) bootloader pin PB5 would lower the voltage in a way, that it would be detected as a LOW after reset.

Corrected version:

Well Jim I tried the new one which compiled and loaded OK. Once the bootloader loaded I have an LED on PB5 and this came on and stayed on . Trying to upload a sketch did not happen and the LED came straight back on each time I reset the chip(immediately, no 4 sec delay). So I'll keep working on it but I think there is another error there somewhere

Well Jim I tried the new one which compiled and loaded OK. Once the bootloader loaded I have an LED on PB5 and this came on and stayed on

That's how it should be.

Trying to upload a sketch did not happen

In your last post you said, that the first upload worked - while your current post suggests, that this is not the case anymore!?

and the LED came straight back on each time I reset the chip (immediately, no 4 sec delay).

That's OK too, the delay starts at the moment the bootloader is entered, and this is when the LED lights up.

And then, after a delay of 4s and when there is no activity on the serial lines, the sketch is started. If there is no sketch loaded (erased chip), the bootloader regains control after a while. So, when you reset the chip, from the moment the LED starts glowing, you have 4 seconds to start your upload.

So I'll keep working on it but I think there is another error there somewhere

We will get it working! Please keep me informed, thanks. My arduino boards should arrive today (as said, currently I'm working with the ATMEL STK500), then I will check it on the "real thing".

First upload worked on the previous bootloader . I now have Version 4 and nothing uploads at all . Tried a few times now . Ill wait and see I suppose

I have another idea: did you check the fuses when programming the bootloader? If the lockbits would prevent the SPM instruction from functioning, the result would look like your phenomenon. Try both fuses BLB01 and BLB02 unprogrammed (1) - is it by all means possible with the arduino IDE to set these fuses when uploading the bootloader? I can't check this, because the IDE does not work on my PC and I'm burning the bootloader with the STK500...

The IDE simply uploads the hex file and a file "boards.txt" gives it its instructions as far as I can see here are the lines of that file pertinent to the ATMega8 The fuses you speak of are mentioned but only their addresses I think , lock/unlock bits?

The atmega8.upload.speed=19200 and in your Makefile it is 115200 , would that affect it ? I'll keep trying NG or older w/ ATmega8

atmega8.upload.protocol=stk500 atmega8.upload.maximum_size=7168 atmega8.upload.speed=19200

atmega8.bootloader.low_fuses=0xdf atmega8.bootloader.high_fuses=0xca atmega8.bootloader.path=atmega8 atmega8.bootloader.file=ATmegaBOOT.hex atmega8.bootloader.unlock_bits=0x3F atmega8.bootloader.lock_bits=0x0F

I changed the above to my crystal speed and tried the above baud rate and 19200 but the error was the same

In case it is of assistance I also put in the compile commands and error message I get- They may differ as I was playing around trying variations later

For the ATmega8 bootloader, these are:

From library * bootloader.atmega8.programmer (default value: stk500) is the protocal used by the bootloader.

  • bootloader.atmega8.unlock_bits (default value: 0xFF) is the value to write to the ATmega8 lock byte to unlock the bootloader section.

  • bootloader.atmega8.high_fuses (default value: 0xca) is the value to write to the high byte of the ATmega8 fuses.

  • bootloader.atmega8.low_fuses (default value: 0xdf) is the value to write to the low byte of the ATmega8 fuses.

  • bootloader.atmega8.path (default value: bootloader) is the path (relative to the Arduino application directory) containing the precompiled bootloader.

  • bootloader.atmega8.file (default value: ATmegaBOOT.hex) is the name of the file containing the precompiled bootloader code (in bootloader.path).

  • bootloader.atmega8.lock_bits (default value: 0x0F) is the value to write to the ATmega8 lock byte to lock the bootloader section (so it doesn't get accidently overwritten when you upload a sketch).

Error message

avrdude: initialization failed, rc=-1 Double check connections and try again, or use -F to override this check.

Compile code sent

avr-gcc -c -mmcu=atmega8 -DMCU=atmega8 -DF_CPU=14890000 -DBAUD_RATE=115200 -DBOOTUART=1 -DUSE_LED=1 -DLED_DDR=DDRB -DLED_PORT=PORTB -DLED_PIN=PINB -DLED_NO=PINB5 -DBL_TIMEOUT=2 -DCODE_CHECK=1 -DWDT_CHECK=1 -DBL_CHECK=1 -DBL_DDR=DDRB -DBL_PORT=PORTB -DBL_PIN=PINB -DBL_NO=PINB3 -x assembler-with-cpp -Wa,-gdwarf2 ArduinoBOOT.asm avr-gcc -mmcu=atmega8 -DMCU=atmega8 -DF_CPU=14890000 -DBAUD_RATE=115200 -DBOOTUART=1 -DUSE_LED=1 -DLED_DDR=DDRB -DLED_PORT=PORTB -DLED_PIN=PINB -DLED_NO=PINB5 -DBL_TIMEOUT=2 -DCODE_CHECK=1 -DWDT_CHECK=1 -DBL_CHECK=1 -DBL_DDR=DDRB -DBL_PORT=PORTB -DBL_PIN=PINB -DBL_NO=PINB3 -nostdlib -Wl,,--section-start=.text=0x1e00 ArduinoBOOT.o -o ArduinoBOOT.elf avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature ArduinoBOOT.elf ArduinoBOOT.hex avr-objdump -h -S ArduinoBOOT.elf > ArduinoBOOT.lss

When im running the atmega8 on 16mhz it works, but when I use the internal crystal on 8MHz it doesn't work any more.

I have changed the make file from 16mhz to 8mhz, I also lower the baud rate, nothing works. Led13 blinks very fast.

And for the fuses, how many words do i have to set de boot flash section? 256 words?

Oke, ive got it working at 8mhz now, i had a wrong fuse.

It works like a charm! very nice.

For the arduino users, set in the make file the next on 0: CODE_CHECK BL_CHECK WDT_CHECK

If one of these are set 1, you cant re-upload a new sketch.

Its still not working for me . I have the bootloader going on OK, with ,and without, the above switches set as above . Then the LED comes on hard immediately and stays on . Taking the reset line low it goes out but immediately comes on hard again . No delay That's where my problem is I think . Its not resetting into the upload routine.

With the three fuses set at 1 , I get that rapidly flashing LED all the time

What baud rate are you using? Can you post your makefile ,asm and cpp files please

I finally got my Arduino boards (old serial V2 boards).

Checks made concerning multiple upload of sketches:
Prolific PL-2303 USB <-> serial cable

Fuses used for ATmega168: EXTENDED:0xFC, HIGH:0xD7, LOW:0xFF

ATmega8-16, 16MHz → works
ATmega8-16, 14.25045MHz (nearest value to 14.89MHz I had available…) → works
ATmega8-16, 8MHz → works

ATmega168-20, 14.24045MHz → works
ATmega168-20, 20MHz → repeatedly FLASH verify errors (seems, my chip does not support 20MHz though it’s a -20 …) ->FAILED
ATmega168-20, 16MHz → works

Pressing RESET instantly illuminates the LED, then I started the upload within 4s.

So, at present I have no idea any more…


Addendum: Retried 168 with 20MHz clock and BAUDRATE lowered to 38400 - this works. Seems, obtainable baudrate error at 115200 is too high.