15.3.1 Interrupt Vector Usage
To field an interrupt, a function’s address must be placed at the appropriate address in one of the vector tables, with the function preserving any system resources that it uses. It must return to the foreground task using a RETFIE processor instruction. Interrupt functions may be written in C. When a C function is designated as an interrupt handler, the compiler arranges to preserve all the system resources that the compiler uses, and to return from the function using the appropriate instruction. The compiler can optionally arrange for the interrupt vector table to be populated with the interrupt function’s address.
To arrange for the compiler to fill in the interrupt vector to point to the interrupt function, name the function as denoted in the vector tables (see section 15.3.2 Interrupt Vector Tables.
As an example for dsPIC33C/E/F and dsPIC30 devices, the stack error vector will automatically be filled if the following function is defined:
void __attribute__((interrupt(auto_psv)))
_StackError(void);
Note the use of the leading underscore. Similarly, the alternate stack error vector will automatically be filled if the following function is defined:
void __attribute__((interrupt(auto_psv)))
_AltStackError(void);
Again, note the use of the leading underscore.
For dsPIC33A devices, the vector name is _StackErrorTrap
and does not
require the auto_psv
sub-attribute. So for the stack error vector:
void __attribute__((interrupt)) _StackErrorTrap(void);
For all interrupt vectors without specific handlers, a default interrupt
handler will be installed. The default interrupt handler is supplied by the linker and
simply resets the device. An application may also provide a default interrupt handler by
declaring an interrupt function with the name _DefaultInterrupt
.
The last nine interrupt vectors in each table do not have predefined
hardware functions. The vectors for these interrupts may be filled by using the names
indicated in the vector tables (15.3.2 Interrupt Vector Tables), or you may use names more appropriate to the application, while
still filling the appropriate vector entry by using the irq
or
altirq
parameter of the interrupt attribute. For example, to
specify that a function should use primary interrupt vector 52, use the following:
void __attribute__((interrupt(auto_psv, irq(52))))
MyIRQ(void);
Similarly, to specify that a function should use alternate interrupt vector 53, use the following:
void __attribute__((interrupt(auto_psv, altirq(52))))
MyAltIRQ(void);
The irq
/altirq
number can be one of
the interrupt request numbers 45 to 53. If the irq
parameter of the
interrupt attribute is used, the compiler creates the external symbol name
__Interruptn
, where n
is the
vector number. Therefore, the C identifiers _Interrupt45
through
_Interrupt53
are reserved by the compiler. In the same way, if the
altirq
parameter of the interrupt attribute is used, the compiler
creates the external symbol name __AltInterruptn
, where n is the vector
number. Therefore, the C identifiers _AltInterrupt45
through
_AltInterrupt53
are reserved by the compiler.