This is a file of random notes gathered while working on a custom
bootloader for the AardRemote project. The files in here are from
version 4.4 of optiboot and have been unmercifully hacked
to build a custom optiboot_atmega328.hex for use on an
Arduino Uno R3 which will occupy the inside of my AardRemote
box.

https://github.com/arduino/Arduino/tree/master/hardware/arduino/bootloaders

http://arduino.cc/forum/index.php/topic,100834.0/topicseen.html

Hack optiboot to check eeprom byte zero for the low bit being set to
mean fall through to bootloader, do not call appStart().

If it falls through, clear the bit in the eeprom so the next time it resets
(which it will do when finished loading) it will call appStart() for real.

Unfortunately, the eeprom_read_byte and eeprom_write_byte routines are now
external routines and I need to link them in, but with the -nostdlib option,
I can't do that, so find the .o files in the libc.a archive:

/usr/avr/lib/avr5/libc.a

eerd_byte_atmega328p.o:
00000000 T __eerd_byte_m328p
eewr_byte_atmega328p.o:
00000000 T __eewr_byte_m328p
00000002 T __eewr_r18_m328p

Then hack the makefile horribly to extract the .o files and explicitly make
them dependencies of the optiboot .elf file.

In the forum thread above, more good info comes to light as well.

This version of optiboot will now be bigger than 512 bytes, so I need
to change the "fuses" that say how much flash is occupied by the boot loader
(so the chip will know where to start executing on reset) and I need to change
the start address in the linker command line options so the makefile
will build a boot loader that expected to start at the given location.

Now I have to translate the BOOTSZ1 and BOOTSZ0 bits table 27-13 (page 294)
of the datasheet into the mystical fuse names in the boards.txt file...

The 512 byte existing optiboot uses BOOTSZ1==1, BOOTSZ0==1, and I
want (for a 1024 byte bootloader) BOOTSZ1==1, BOOTSZ0==0.

Finally found it! Table 28-8 page 300 says BOOTSZ1 is bit 2 and
BOOTSZ0 is bit 1 in the fuse high byte (be careful to note that
it is different in other models, this is for the ATmega328P).

So instead of high_fuses=0xde I want high_fuses=0xdc. Let's see
if this all makes sense:

RSTDISBL -> 1

DWEN     -> 1

SPIEN    -> 0

WDTON    -> 1

EESAVE   -> 1

BOOTSZ1  -> 1

BOOTSZ0  -> 0

BOOTRST  -> 0

I guess it all makes sense, but there are so many double negatives
on that page of the manual, I'm not sure :-).

Also want to set upload.maximum_size=31744 (32K - 1K).

Then it turns out there is a bug where burning bootloader with arduino as
ISP doesn't work when run at the default 19200 baud, so you need to run at
9600 baud instead. This necessitated finding out how to tweak the
IDE's idea of the baud rate it should use.

Note that you also need to modify the ArduinoISP sketch to set the baud rate
to 9600 as well.

Found the programmers.txt file and changed baud rate to 9600 there, so now I can
actually upload bootloader from IDE.

And I was actually able to load my modified bootloader and use it to download
new microcode! I can tell it is my new one because I changed the version
number from 4.4 to 4.7 and avrdude now reports 4.7 as the version.

There was a brief interruption in my progress somewhere in here as my SSD
system disk died (on Friday the 13th, no less :-), but I'm back up and
running now, and when re-pairing my bluetooth shield, I also took the
trouble to discover where the heck the setting are stashed - some file in
/var/lib/bluetooth holds the pairing info (a whole bunch of the files in
there have a newer timestamp than before I did the pairing). In fact a
grep for the ID of the shield shows that virtually every file in there
has some reference to it, so I guess the whole collection is needed.

Meanwhile, I've tested the new reset capability and the results are
mysterious to me. I seem to have to run avrdude twice to get the microcode
to load. The first time apparently erases it so the bootloader is
active 100% of the time, then the second actually loads it. I'm
now starting on a journey through the datasheet to read about watchdog
and reset :-).

Section 11.2 Reset Sources (Page 48), it says:

   Watchdog System Reset. The MCU is reset when the Watchdog Timer period
   expires and the Watchdog System Reset mode is enabled.

Section 11.6 Watchdog System Reset (Page 51):

   There is a diagram showing the watchdog triggers a timeout counter.
   (So perhaps it takes more time to get reset than just the watchdog
   interval?).

Section 11.8 is all about the watchdog timer (Page 52):

   It says there are 3 operating modes: Interrupt, System Reset,
   and Interrupt+System Reset.

   It says the WDTON fuse bit is for watchdog always on.

   It says turning on the WDTON fuse bit means the watchdog
   will never operate in Interrupt mode, but only in System
   Reset mode.

   It also says the programming of the watchdog has to be done
   in a particular manner with particular time constraints
   (which hopefully the wdt_* routines follow).

Nothing strikes a bell so far...

Perhaps I should just experiment with the timeout value (but that is kind of
a pain because every time I screw up the sketch, I need to reload it before
I can try again).
