Electronic – Arduino Bootloader Details

arduinoavrbootloader

Can someone please explain how the Arduino bootloader works? I'm not looking for a high level answer here, I've read the code and I get the gist of it. I've also read through this other post (I had even been one of the responders to it).

There's a bunch of protocol interaction that happens between the Arduino IDE and the bootloader code, ultimately resulting in a number of inline assembly instructions that self-program the flash with the program being transmitted over the serial interface.

What I'm not clear on is on line 270:

void (*app_start)(void) = 0x0000; 

…which I recognize as the declaration, and initialization to NULL, of a function pointer. There are subsequent calls to app_start in places where the bootloader is intended to delegate to execution of the user-loaded code.

Surely, somehow app_start needs to get a non-NULL value at some point for this to all come together. I'm not seeing that in the bootloader code… is it magically linked by the program that gets loaded by the bootloader? I presume that main of the bootloader is the entry point into software after a reset of the chip.

Wrapped up in the 70 or so lines of assembly must be the secret decoder ring that tells the main program where app_start really is? Or perhaps it's some implicit knowlege being taken advantage of by the Arduino IDE? All I know is that if someone doesn't change app_start to point somewhere other than 0, the bootloader code would just spin on itself forever… so what's the trick?

On a separate note, would it be possible for the bootloader code to rely on interrupts or is that a no-no?

Edit

I'm interested in trying to port the bootloader to an Tiny AVR (specifically the ATTiny44A) that doesn't have separate memory space for boot loader code. As it becomes apparent to me that the bootloader code relies on certain fuse settings and chip support, I guess what I'm really interested in knowing is what does it take to port the bootloader to a chip that doesn't have those fuses and hardware support (but still has self-programming capability)?

I was thinking I could use the implementation of AVR307 to use the USI as a half-duplex UART (uses Timer0 interrupt, and pin-change interrupt). Can anyone offer guidance on how to go about writing/porting the bootloader code for a chip that doesn't have hardware support for bootloaders?

I presume I would put my bootloader code at the normal location for address main (e.g. 0x029e or wherever the compiler puts main). I would then make it so that 'address' in the bootloader code added an offset that put me just past the end of main, and have 'app_start' set to that address. Am I thinking about this correctly or am I totally missing something? Thanks!

EDIT 2

FWIW, I found a documented process for how to load Arduino sketches onto a ATTiny85, which is where I was originally going with this question… pretty neat I think

Best Answer

void (*app_start)(void) = 0x0000; 

This isn't a NULL pointer. This really is the address of the start of application code, which the bootloader jumps to. The linker arranges for your application code to start at address 0. See table 26-6 in the ATMEGA168 datasheet.

The bootloader code starts higher up in flash. Exactly where depends on the bootloader fuses.