0
\$\begingroup\$

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

\$\endgroup\$
1
  • \$\begingroup\$ Interrupt vectors are normal code, just like the rest of it. \$\endgroup\$ Dec 12, 2015 at 19:42

3 Answers 3

8
\$\begingroup\$

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.

\$\endgroup\$
6
  • \$\begingroup\$ Hi, just look into the table again and see there is nothing in $0001 so at first, the reset routine is run and return to $0001 so if I program other interrupt service routine too, I must avoid PC reading it by setting another jump at $0001 address to where my program begin? \$\endgroup\$
    – aukxn
    Dec 12, 2015 at 19:45
  • \$\begingroup\$ @aukxn after the jump instruction is executed, the code won't return to the vector table until the next interrupt (or reset), unless you specifically add a jump back again. In an AVR all interrupt vectors are 4 bytes, so 0x0000 through to 0x0003 are all part of the reset vector. Addresses 0x0004 through 0x0007 will be the vector for ISR source 1. Notice how at 0x0010 there is a jump to <__vector_4>, this is to the ISR routine for interrupt source 4. \$\endgroup\$ Dec 12, 2015 at 19:48
  • \$\begingroup\$ It's a jump, not a call. You can only return from calls as a call instruction will push the return address on the stack. Jumps are usually one-way since the return address is not recorded. \$\endgroup\$ Dec 12, 2015 at 19:50
  • \$\begingroup\$ yes, sorry for my mistake, then what instruction can be used to tell that it's the end of interrupt routine then go to the main function after that? \$\endgroup\$
    – aukxn
    Dec 12, 2015 at 19:53
  • \$\begingroup\$ @aukxn the reti instruction is placed at the end of an ISR to tell the CPU to return from the ISR to the memory location the CPU was at when the interrupt occurred (before it jumped to the vector table). \$\endgroup\$ Dec 12, 2015 at 19:54
0
\$\begingroup\$

When an interrupt is triggered during a program execution(after you must have set and programmed it for interrupt of course) there are unique addresses in which your program counter will point to which is specific for each specific interrupts of your AVR microcontroller. These addresses just happens to be designated at the beginning of your flash memory, like you said from 0x0000(reset interrupt) to 0x003A. Now when you program your AVR uC and then start your program with

.ORG 0 what you have done is tell your assembler to start placing your program from address 0x0000, downwards..meanwhile you have actually written your programs on top of those interrupt addresses downwards.

Now what do you think will happen, if paraventure during the course of execution of your program you have set an interrupt?. By design, your Program Counter(PC) is to point to the unique address of that particular interrupt that just triggered which is usually among those specified addresses at the beginning of your flash memory. Then on pointing to that address it see an instruction and then starts to execute, that is the logic. so therefore, what programmers do is avoid those address and then just place a function call on those interrupt address if there is need for any interrupt in your program that you have written. I hope this helps

\$\endgroup\$
0
\$\begingroup\$

You can place your start point anywhere after the reset vector address.

If you use interrupts, you will want to at least steer clear of the interrupt vectors you use. Unplanned interrupts, if they occur, will jump into your code and would likely be bad. (!)

Best practice is to start your code after the whole block of interrupt vectors. I typically start a project with all int vectors populated with a JMP or RJMP (depending on processor) to a trap for bad interrupts, where I set a breakpoint during development. As I populate the ISRs, they get vectors to the appropriate locations. When done, all unused ints are trapped, and then trigger a fault in my sanity check routine.

You could place the entry point anywhere past the int vector block. You might want to place tables between the int vector block and the code, but unless I have a specific reason to do otherwise, I typically allocate tables starting past the end of the code.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.