Part 1 of this little series includes a ready-to-use bootloader. But, for the curious, here is how to compile a bootloader, from scratch.
The first thing is to download the source code – which includes, well, everything. Instructions are here. And, by the way, they are right about “it’ll take a while” to download – especially if you’re on DSL.
Now, one first built to make sure it all works fine, and then it’s time to do some editing!
Since we’re working on the “atmega” bootloader, the file to edit is
A section needs to be added which is derived from the “decimilia” section (so, placing it right after is a good idea):
slowpoke_1mhz_int: TARGET = slowpoke_1mhz_int slowpoke_1mhz_int: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DBAUD_RATE=4800' slowpoke_1mhz_int: AVR_FREQ = 1000000L slowpoke_1mhz_int: $(PROGRAM)_slowpoke_1mhz_int.hex slowpoke_1mhz_int_isp: slowpoke_1mhz_int slowpoke_1mhz_int_isp: TARGET = slowpoke_1mhz_int slowpoke_1mhz_int_isp: HFUSE = DE slowpoke_1mhz_int_isp: LFUSE = 62 slowpoke_1mhz_int_isp: EFUSE = 00 slowpoke_1mhz_int_isp: isp
- -DBAUD_RATE=4800: since the internal oscillator is really not that precise, one could foresee some problems with serial communications if the baud rate is left at the default value of 19200. Lowering it to 4800 allows somewhat more sloppy timing, which is what we need. I mean it’s not like we have to transfer that much data.
- The “AVR_FREQ = 1000000L” is pretty self-explanatory – it declares the clock frequency to 1MHz. This does not actually set the clock frequency – that is done with fuses. But it declares a value that is used in the bootloader code to calculate things involving time (such as serial transmissions, delays, etc).
- LFUSE=62. Fuse low byte.
0×62 = 01100010 (binary). So this means:
- CKDIV8: programmed (clock will be divided by 8 )
- CKOUT: unprogrammed (do not output system clock on PORTB0)
- SUT1,0 =(1,0) (Startup time = 14CK + 65ms)
- CKSEL3,2,1,0 = (0,0,1,0) (use internal RC Oscillator @ 8MHz)
This basically means that the AVR is programmed to use the internal 8MHz oscillator, which gets divided by 8 to 1MHz, and to take its time to start up.
- HFUSE=DE. Fuse high byte.
0xDE = 11011110 (binary). So this means:
- RSTDISBL is unprogrammed (the external reset disabled is unprogrammed, in other words, external reset is enabled!)
- DWEN is unprogrammed (debugWIRE disabled)
- SPIEN is programmed (SPI programming enabled)
- WDTON is unprogrammed (watchog timer NOT always on)
- EESAVE is unprogrammed (EEPROM not reserved)
- BODLEVEL2/1/0 set to ’110′, which sets the brown-out reset level to 1.8V
- EFUSE=00. Extended Fuse byte.
0×00 = 00000000 (binary). So this means:
- BOOTSZ1/0 is set to ’00′, which means that the boot size is set for 1024 words (2048 bytes)
- BOOTRST is programmed, which moves the Reset vector to the start of the Boot Flash section.
After this, cd to Arduino/hardware/arduino/bootloaders/atmega (basically the same directory where the Makefile lives) and do a
make slowpoke_1mhz_int You should see stuff like: avr-gcc -g -Wall -O2 -mmcu=atmega168 -DF_CPU=1000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DBAUD_RATE=4800' -c -o ATmegaBOOT_168.o ATmegaBOOT_168.c avr-gcc -g -Wall -O2 -mmcu=atmega168 -DF_CPU=1000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DBAUD_RATE=4800' -Wl,--section-start=.text=0x3800 -o ATmegaBOOT_168_slowpoke_1mhz_int.elf ATmegaBOOT_168.o avr-objcopy -j .text -j .data -O ihex ATmegaBOOT_168_slowpoke_1mhz_int.elf ATmegaBOOT_168_slowpoke_1mhz_int.hex rm ATmegaBOOT_168_slowpoke_1mhz_int.elf ATmegaBOOT_168.o
Success. The file ATmegaBOOT_168_slowpoke_1mhz_int.hex is the new, ready-to-upload bootloader.
At this point all that is needed is to follow the deploy instructions in Part 1.