17.5 Interrupt Service Routine Context Switching

When using Cortex-M devices, the hardware saves and restores the argument registers (r0 to r3), the IP register (r12) the link register (r14), the return address, and the program status registers when the interrupt occurs and returns. Other registers must be preserved by the interrupt handler function, as with any other function. The compiler will do this automatically for C functions. If you write your own handler in assembly, be sure to follow the procedure call standard.

It is possible for other exceptions to occur during the context switch. The work for this is handled in hardware. Details of this can be found in the appropriate architecture reference manual, but in essence, the context switching does not occur twice. Instead, the higher priority interrupt is run with the other interrupt set to pending.

When targeting Cortex-A devices, the compiler must generate application code to save and restore the device context; however the Floating-point Unit (FPU) registers are never saved by interrupt handlers. Applications on these devices that need to use the FPU from an interrupt context require bespoke interrupt handlers. Consider writing the interrupt handler in assembly code, having them push all the registers that need to be saved, call the function for the handler, restore the registers, and then return. This assembly wrapper function would need to be applied to every interrupt handler (or at least those that use FPU registers). In this case, C functions should not set the interrupt attribute. Registers r0-r12, r14, d0-d7, d16-d32, and the status registers must be saved if they have been used in the handler. This is potentially a large number of registers that need to be saved, which would require a significant amount of stack space to have them preserved and a significant amount of time for that preservation code to execute.