17.2.1 Interrupt Attribute

Use the interrupt attribute to indicate that the specified function is an interrupt handler. The compiler generates function entry and exit sequences suitable for use in an interrupt handler when this attribute is present. The generated code preserves context by either using a shadow register set (SRS) or using generated software instructions (SOFT) to push context onto the stack.

The attribute has the general form:
__attribute__((interrupt([IPLn[SRS|SOFT|AUTO]])))
where n is in the range of 0 through 7, inclusive.

Interrupt Attribute

void __attribute__((interrupt(IPL7SRS))) bambam (void)
{
  // interrupt code goes here
}
When programming in C++, the interrupt handler symbol must be allocated to the C namespace, which can be accomplished using extern "C" with the definition, for example:
extern "C"
void __attribute__((interrupt(IPL7SRS))) bambam (void)
{
  // interrupt code goes here
}
Note: Some PIC32 target devices allow the exception/interrupt code to be in either the MIPS32® or microMIPS™ ISA mode via a device configuration bit (BOOTISA). On these devices, if your BOOTISA bit is set to microMIPS mode, add the 'micromips' attribute to your interrupt function. If your BOOTISA bit is set to MIPS32 mode, add the 'nomicromips' attribute to your interrupt function. See your device data sheet for more information on this configuration bit.

Many PIC32 devices allow us to specify, via configuration-bit settings, which interrupt priority level will use the shadow register set (for example, #pragma config FSRSSEL=PRIORITY_7). Refer to the device data sheet to determine if your PIC32 target device supports this feature. This means we must specify which context-saving mechanism to use for each interrupt handler. The compiler will generate interrupt function prologue and epilogue code utilizing shadow register context saving for the IPLnSRS Interrupt Priority Level (IPL) specifier. It will use software context saving for the IPLnSOFT IPL specifier.

Other PIC32 variants may have 8 register sets (1 standard set and 7 shadow register sets) meaning that there are enough shadow register sets for every interrupt priority level. Therefore, you should use the IPLnSRS IPL specifier for every interrupt service routine on these device variants.

Note: Application code is responsible for applying the correct IPL specifier value to each ISR. The interrupt source’s priority level must match the ISR’s IPL value (for example, IPLnSRS) or the interrupt will not be handled correctly. Mismatching priority levels may result in critical runtime problems such as a stack overflow that overwrites data memory. This can include corruption of memory reserved for use by the Debug Executive, causing the debug tool to behave erratically.

The compiler also supports an IPLnAUTO IPL specifier that uses the run-time value in SRSCTL to determine whether it should use software or SRS context-saving code. The compiler defaults to using IPLnAUTO when the IPL specifier is omitted from the interrupt() attribute.

For devices that do not support a shadow register set for interrupt context saving, use IPLnSOFT for all interrupt handlers.

Note: SRS has the shortest latency and SOFT has a longer latency due to registers saved on the stack. AUTO adds a few cycles to test if SRS or SOFT should be used.

For IPL7(SRS | SOFT | AUTO), the compiler assumes that nothing can interrupt priority 7. This means that there is no reason to save EPC or SRSCtl and that global disabling of interrupts is unnecessary.

The IPLnSAVEALL interrupt priority specifier can be used with the interrupt attribute. Use this specifier in place of IPLnSOFT to force software context saving of all software-saved general registers even if they are not used within the Interrupt Service Routine (ISR). This attribute can be useful for some RTOS implementations.

The keep_interrupts_masked attribute can be used to modify the behavior of an interrupt handler. The attribute keeps interrupts masked for the whole function. Without this attribute, the XC32 compiler re-enables interrupts for as much of the function as it can. By keeping interrupts masked, support for nested interrupts is disables. Users can re-enable them as necessary in their own code.

The attribute keep_interrupts_masked can be combined with the interrupt attribute. This attribute causes the Interrupt Service Routine (ISR) prologue code to not re-enable interrupts. Application code may then choose whether and when to re-enable interrupts in the ISR.