In microcontroller (AVR), the interrupt vector take address $0000 to $003A so the program is start after that address

microcontroller

I'm studying microcontroller using Atmel 8-bit microcontroller datasheet, According to the datasheet, there's 3 types of internal memory in microcontroller

  • Flash memory = program memory
  • SRAM: 32 general purpose register as well as I/O register is located here
  • EEPROM

So, when program counter (PC) fetchs instruction, it will fetch from flash memory where the program (instructions) is stored, starting from $0000 but then when I read interrupt chapter (ATmega 2560) , it says that interrupt vectors is stored at $0000 to $003A in program memory then does it mean when the microcontroller starts, PC will go through the interrupt vector list first and then instructions later?

Moreover, the interrupt is enabled by instruction which come after $003A so when the PC start from $0000 to $003A, microcontroller do nothing because at that time, intteruption haven't enabled yet?

I'm currently use two datasheet, Atmel ATmega 2560 and ATmega 16A

Best Answer

The first vector in the interrupt vector table (located at 0x0000) is the "Reset Vector". This is the first program memory address which is read by the CPU on power up1. The location in memory is usually filled with a JMP or RJMP instruction where the jump address is the start of your program.

If the reset vector is not correctly programmed (e.g. with an RJMP instruction or whatever), the CPU will simply keep counting along executing instructions as they appear - e.g. executing other interrupt vectors if there. If there are any other interrupt routines programmed into the vector table, these would all be executed in turn regardless of whether it's interrupt source was enabled or disabled.

When using something like avr-gcc, it is aware of the interrupt vector table and its structure, and will make sure that the reset vector points to the start of your program. In this case, the start of the program is actually not your main() function, but a load of stuff the compiler adds to initialise variables and whatnot. But after all of the initialisation stuff, your main() function would be called.


As an example, this is the disassembled vector table for one of my programs:

   0:   0c 94 72 00     jmp 0xe4    ; 0xe4 <__ctors_end>
   4:   0c 94 8f 00     jmp 0x11e   ; 0x11e <__bad_interrupt>
   8:   0c 94 8f 00     jmp 0x11e   ; 0x11e <__bad_interrupt>
   c:   0c 94 8f 00     jmp 0x11e   ; 0x11e <__bad_interrupt>
  10:   0c 94 4f 03     jmp 0x69e   ; 0x69e <__vector_4>
  14:   0c 94 8f 00     jmp 0x11e   ; 0x11e <__bad_interrupt>
  18:   0c 94 ef 03     jmp 0x7de   ; 0x7de <__vector_6>
  1c:   0c 94 8f 00     jmp 0x11e   ; 0x11e <__bad_interrupt>
  ...
  6c:   0c 94 8f 00     jmp 0x11e   ; 0x11e <__bad_interrupt>

Notice how avr-gcc adds a jump at address 0x0000 to what it calls __ctors_end which is basically a memory address after the end of the vector table where it's initialisation stuff starts. All unused vectors jump to something called __bad_interrupt - located at the destination of that jump is basically another jump instruction back to 0x0000 such that any occurrence of an unhandled interrupt resets the processor.


1. Some AVRs have a bootloader space and can be programmed to have the interrupt vector table at a different address than 0x0000, but the same still applies.