views:

80

answers:

1
+2  Q: 

Arduino Bootloader

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.

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?

Edit

I'm interested in trying to port the bootloader to an Tiny AVR 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)?

+5  A: 

When the AVR resets with the Boot Reset Fuse set, program exeuction will begin from the bootloader memory block at the upper end of the memory (where that is specifically depends on further values, see a datasheet (PDF, 7 MB) for specifics). That code scans for special events that can signal the MCU to enter bootloading mode. If found, then the MCU will pull down data from the programmer then flash the rest of the memory.

If not, then the bootloader gives control back to the program that already resides in the MCU. The vector table for AVRs lives at the beginning of their program memory, beginning at address 0 with the RESET vector. I'm not sure exactly what the compiler does with the C, but all it really needs to generate is an RJMP 0 (or RJMP app_start) to hand off control.

An ATtiny bootloader:

On ATtinys, as you mentioned, there is no luxury of the bootloader fuses or memory, so your code will always start at address 0. You might be able to put your bootloader into some higher pages of memory and point your RESET vector at it, then whenever you receive a new hex file to flash with, take the command that's at address 0:1, replace it with the bootloader address, then store the replaced address somewhere else to call for normal execution. (If it's an RJMP ("relative jump") the value will obviously need to be recalculated)

On NULL:

Address 0 does not a null pointer make. The concept of a "null pointer" only has meaning if a function that takes or gives (void *)0 (or similar) grants it special meaning by implementing unique behavior.

Nick T
+1 for correct and helpful answer to both original and updated question.
Yann Vernier