What do I need to do to get interrupts working?

C Interrupt Handlers Interrupt handlers can be written in C. In the file where you define the function, before the function definition you must inform the compiler that the function is an interrupt handler by using a pragma:

#pragma interrupt_handler <name>:<vector number> *

"vector number" is the interrupt's vector number. Note that the vector number starts with one, which is the reset vector. This pragma has two effects:

For an interrupt function, the compiler generates the reti instruction instead of the ret instruction, and saves and restores all registers used in the function.

        The compiler generates the interrupt vector based on the vector number and the target device. 

For example,

#pragma interrupt_handler timer_handler:4

...

void timer_handler(void)

        {
...
}

The compiler generates the instruction

rjmp _timer_handler ; for classic devices, or

jmp _timer_handler ; for Mega devices

at location 0x06 (byte address) for the classic devices and 0xC (byte address) for the Mega devices (Mega devices use 2 word interrupt vector entries vs. 1 word for the classic non-Mega devices).

You may place multiple names in a single interrupt_handler pragma, separated by spaces. If you wish to use one interrupt handler for multiple interrupt entries, just declare it multiple times with different vector numbers. For example:

#pragma interrupt_handler timer_ovf:7 timer_ovf:8

The new C header files "ioXXXXv.h" define consistent global names for interrupt vector numbers, enabling fully symbolic interrupt_handler pragma and easy target swapping. Global interrupt vector numbers are named "iv_<vector_name>" with <vector_name> as in AVR data sheets. For example,

#pragma interrupt_handler timer0_handler: iv_TIMER0_OVF

#pragma interrupt_handler eep_handler: iv_EE_READY

#pragma interrupt_handler adc_handler: iv_ADC

Since interrupt vector number names are defined in header file, they easily can be changed for another target AVR by simply including another header file. New target must meet hardware requirements, of course. For names supported by distinct header see avr_c_lst and mega_c_lst files in ICCAVR include directory.

Assembly Interrupt Handlers

You may write interrupt handlers in assembly. However, beware that if you call C functions inside your assembly handler, then the assembly routine must save and restore the volatile registers (see Assembly Interface) since the C functions do not do that (unless they are declared as interrupt handlers, but then they should not be called directly).

If you use assembly interrupt handlers, then you must define the vectors yourself. You use the "abs" attribute to declare an absolute area (see Assembler Directives) and use the ".org" statement to assign the rjmp or jmp instruction at the right location. Note that the ".org" statement uses byte address.

; for all but the ATMega devices

.area vectors(abs) ; interrupt vectors

.org 0x6

rjmp _timer

; for the ATMega devices

.area vectors(abs) ; interrupt vectors

.org 0xC

jmp _timer

Asm header files "aioXXXX.s" support macros for symbolic interrupt vector defintion. Syntax:

set_vector_<vector_name> <jumpto_label>

with <vector_name> as in AVR data sheets and <jumpto_label> equate to user's asm ISR. Examples:

set_vector_TIMER0_OVF t0_asm_handler

set_vector_ADC adc_asm_handler

set_vector_UART0_DRE u0dre_asm_handler

Depending on target macro expansion may result in different code. For names supported by distinct header see avr_asm_lst and mega_asm_lst files in ICCAVR include directory.
[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章