I am writing a bootloader for the ATmega168 and trying to understand the role of the reset vector. As I understand it, when the bootloader is ready to start the application, it moves the program counter to the reset vector address (0x0000).
From the datasheet in Table 27-6, it appears that the application flash also starts at 0x0000. If I put the application code in flash starting at 0x0000, wont I overwrite all the interrupt vector table and disallow interrupts for the actual program?
In short, what address should the bootloader write the application code to? How can I make sure that when I call the reset vector that it then jumps to the application code?
This has a lot of explanation : http://jaxcoder.com/Projects.aspx?id=912541054
You can also have a look at the optiboot.c file of the OptiBoot project : http://code.google.com/p/optiboot/
Why do you want to know that ?
The Arduino IDE can burn the bootloader and upload a sketch. You don't have to know all the addresses and vectors.
The Interrupt Service Routine is code in flash. That means its address is fixed. So the vector table has fixed values and is also in flash. I don't see the problem.
Once the bootloader has passed on executation to the uploaded sketch, the bootloader is not used in any way anymore. And every time you press the reset button (hardware reset) the bootloader starts first. That's just how it is.
You can upload a sketch with a programmer (it is in the menu of the Arduino IDE) the bootloader is omitted and the sketch starts running immediately.
Note that on AVR, the vectors are actually full “JUMP” instructions, rather than just addresses to jump to (like they would be on an ARM.) So the “vector” at location 0 is actually something like a “jmp start” instruction, and the code that invokes vectors actually sets the PC to the vector address and executes whatever instruction is there. (this allows applications that don’t contain a vector table, for example. The reset hardware starts the cpu at pc=0, and that either is a jump instruction “vector”, or just actual code.)
Thank you all for the responses. It sounds like if I want to keep all of my interrupt vector table, I need to place the application code after it. Table 12-4 (from datasheet) indicates the first available address is 0x0034 after the vector table. We can only write to flash a page at a time and a page is 128 bytes (Table 27-9) so I should place application code at 0x0080. Then I should put 0x0080 in the reset vector. The code would look something like this
#define APP_START_ADDR (0x0080)
//do bootloader/place code with pages starting at APP_START_ADDR
//now tell the microcontroller where to go on reset
//i think in assembly I could just write asm(".org 0x0000\n" "jmp 0x0080\n");
uint16_t *ptr_to_reset = 0x0000;
*ptr_to_reset = APP_START_ADDR;
//now actually call reset so the application can run
Is this correct? Thanks.
Can you tell why you want to do that ?
The Arduino IDE sets is correctly for you, and so does the avr-gcc compiler.
No problem. I want to program my microcontroller wirelessly. A similar project is located here.
Bluetooth or Wifi or with an RF module ?
So the bootloader must have the code for the wifi. I think the bootloader can only have certain sizes, I hope it fits.
The Optiboot has certain timings, that might not be compatible for wifi. But at least the optiboot shows how to write the code into the flash. Does avrdude have a programmer option that is useable for wifi ?
I think there is already a bootloader that loads the hex file via ethernet. I forgot what the name is for that project.
It sounds like if I want to keep all of my interrupt vector table, I need to place the application code after it.
I think you're missing something. The vector table is normally included as part of the application, so the application INCLUDING THE VECTOR table is usually programmed starting at location 0 in flash.
if you want to use interrupts within the bootloader, you can relocate the vector table to the start of boot section instead of at 0, using the IVSEL bit in MCUSR.
Where this falls apart is if you're using a chip that doesn't have support for a separate bootloader section. In this case Optiboot tries to implement a "virtual boot section." What happens there is that the bootloader tries to "intercept" the vector table in the downloaded application, and replace it with the bootloader's start address (while also saving the application start address somewhere else, so that it can actually be started.)
Good point. I think I was missing something as well but it makes sense now. For now I am not planning on using interrupts for the bootloader. It looks like the code will go something like this:
get hex data for program
copy hex data into flash starting at 0x0000
asm(".org 0x0000\n" "jmp 0x0000\n");