It's nearly impossible to find compilers that agree on how to handle interrupt code. Since the C language tries to stay away from machine dependent details, each compiler writer is forced to design their method of support.
In the AVR-GCC environment, the vector table is predefined to point to interrupt routines with predetermined names. By using the appropriate name, your routine will be called when the correspondi ng interrupt occurs. The device library provides a set of default interrupt routines, which will get used if you don't define your own.
Patching into the vector table is only one part of the problem. The compiler uses, by convention, a set of registers when it's normally executing compiler-generated code. It's important that these registers, as well as the status register, get saved and restored. The extra code needed to do this is enabled by tagging the interrupt function with __attribute__((interrupt)).
These details seem to make interrupt routines a little messy, but all these details are handled by the Interrupt API. An interrupt routine is defined with one of two macros, INTERRUPT() and SIGNAL(). The interrupt is chosen by supplying one of the symbols in Table 6-1. These macros register and mark the routine as an interrupt handler for the specified peripheral. See the entries for INTERRUPT() and SIGNAL() for examples of their use.
Unused interrupt vectors point to a routine called _unexpected_. The default version of this function simply consists of a reti instruction. You can define your own handler, if you want to handle unexpected interrupts differently.
Table 6-1. Signal names
Name | Description |
---|---|
SIG_INTERRUPT0 | External Interrupt0 |
SIG_INTERRUPT1 | External Interrupt1 |
SIG_INTERRUPT2 | External Interrupt2 |
SIG_INTERRUPT3 | External Interrupt3 |
SIG_INTERRUPT4 | External Interrupt4 |
SIG_INTERRUPT5 | External Interrupt5 |
SIG_INTERRUPT6 | External Interrupt6 |
SIG_INTERRUPT7 | External Interrupt7 |
SIG_OUTPUT_COMPARE2 | Output Compare2 Interrupt |
SIG_OVERFLOW2 | Overflow2 Interrupt |
SIG_INPUT_CAPTURE1 | Input Capture1 Interrupt |
SIG_OUTPUT_COMPARE1A | Output Compare1(A) Interrupt |
SIG_OUTPUT_COMPARE1B | Output Compare1(B) Interrupt |
SIG_OVERFLOW1 | Overflow1 Interrupt |
SIG_OUTPUT_COMPARE0 | Output Compare0 Interrupt |
SIG_OVERFLOW0 | Overflow0 Interrupt |
SIG_SPI | SPI Interrupt |
SIG_UART_RECV | UART(0) Receive Complete Interrupt |
SIG_UART1_RECV | UART(1) Receive Complete Interrupt |
SIG_UART_DATA | UART(0) Data Register Empty Interrupt |
SIG_UART1_DATA | UART(1) Data Register Empty Interrupt |
SIG_UART_TRANS | UART(0) Transmit Complete Interrupt |
SIG_UART1_TRANS | UART(1) Transmit Complete Interrupt |
SIG_ADC | ADC Conversion complete |
SIG_EEPROM | Eeprom ready |
SIG_COMPARATOR | Analog Comparator Interrupt |
description. Disables all interrupts by clearing the global interrupt mask. This function actually compiles into a single line of assembly, so there is no function call overhead.
description. This function gives access to the gimsk register (or eimsk register if using an AVR Mega device). Although this function is essentially the same as using the outp() function, it does adapt slightly to the type of device being used.
description. This macro creates the prototype and opening of a function that is to be used as an interrupt. signame should be one of the symbols found in Table 6-1. The routine will be executed with interrupts enabled. If you want interrupts disabled, use the SIGNAL() macro instead. Example 6-1 sets up an empty routine which gets called when the ADC has completed a conversion.
see also. SIGNAL()
description. Enables interrupts by clearing the global interrupt mask. This function actually compiles into a single line of assembly, so there is no function call overhead.
description. This macro creates the prototype and opening of a function that is to be used as an interrupt. The argument signame should be one of the symbols found in Table 6-1. The routine will be executed with interrupts disabled. If you want interrupts enabled, use the INTERRUPT() macro instead.
Example 6-2 sets up an empty routine which gets called when the ADC has completed a conversion.
see also. INTERRUPT()