Using AVR Studio 4 with gcc, write your assembly code like this:
.global INT0_vect ; tells the linker this is where INT0_vect lives
INT0_vect:
reti
The .global directive tells the linker "here's the interrupt service routine" and the appropriate jump instruction is filled into the vector table. When the interrupt fires, the program counter moves to that spot in the vector table, the jmp is issued and your ISR code is run, then returns from interrupt with the reti instruction.
You can find the correct interrupt service routine labels to use by looking inside your device-specific io file, e.g., io328p.h
...and edit the file, and look for the __vectors table, excerpt below. You can see below that I have vectors 1 and 2 defined and several undefined. These interrupts would result in jumps to __bad_interrupt, halting the MCU.
Disassembly of section .text:
You can find out by consulting your datasheet. For example, in the ATmega328P datasheet, reproduced here for educational purposes: Vector 1 is INT0, vector 2 is INT1, and so on.
/* Interrupt Vectors */
/* Interrupt Vector 0 is the reset vector. */
#define INT0_vect _VECTOR(1) /* External Interrupt Request 0 */
#define INT1_vect _VECTOR(2) /* External Interrupt Request 1 */
#define PCINT0_vect _VECTOR(3) /* Pin Change Interrupt Request 0 */
#define PCINT1_vect _VECTOR(4) /* Pin Change Interrupt Request 0 */
...
If you want to check to be sure your interrupt routines are getting populated within the interrupt vector table (starting at address 0x0000), then do:
avr-objdump -h -S -z AVRcam.elf > AVRcam.lss
...and edit the file, and look for the __vectors table, excerpt below. You can see below that I have vectors 1 and 2 defined and several undefined. These interrupts would result in jumps to __bad_interrupt, halting the MCU.
Disassembly of section .text:
00000000 <__vectors>:
0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>
4: 0c 94 95 01 jmp 0x32a ; 0x32a <__vector_1>
8: 0c 94 96 01 jmp 0x32c ; 0x32c <__vector_2>
c: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
10: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
14: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
...
So, what are these mysterious __vector_XX addresses?
You can find out by consulting your datasheet. For example, in the ATmega328P datasheet, reproduced here for educational purposes: Vector 1 is INT0, vector 2 is INT1, and so on.
Good stuff. Thanks.
ReplyDelete