5.9.4.1 Context Saving On Interrupts

Any registers or compiler temporary locations used by interrupt function could be corrupted if they are also used in main-line code or another interrupt function. These registers might, therefore, need to be saved before the interrupt function executes and restored before it returns. The hardware on some devices can save and restore some of these registers when an interrupt occurs; the remainder must be saved by the compiler using software, known as the context save or context switch code.

The compiler determines exactly which registers and objects are used by an interrupt function or any of the functions that it calls. See Register Usage for those registers that might be used for code generation and that might need to be preserved. Note that the btemp working registers are memory locations allocated by the compiler but treated like registers for code generation purposes, including being preserved by the context switch code. They are typically used when generating code for reentrant functions on Enhanced Mid-range and PIC18 devices. Depending on the device and the program as a whole, there can be a large number of btemp registers in use.

The following registers might be saved in hardware by the device in addition to the PC, which all devices must save.
  • PIC18 devices with the Vectored Interrupt Controller module save the FSRx, PCLATHx and PRODx registers to shadow registers in addition to saving the W, STATUS and BSR registers. Separate shadow registers are available for low- and high-priority interrupts on these devices.
  • Other PIC18 devices will save the W, STATUS and BSR registers to shadow registers for high-priority interrupts only. For the low priority PIC18 interrupts do not allow this feature.
  • Enhanced Mid-range PIC devices save the WREG, STATUS, BSR and FSRx registers in shadow registers.

Note that for some older devices, the compiler will not use the shadow registers if compiling for the MPLAB ICD debugger, as the debugger itself utilizes these shadow registers. Some errata workarounds also prevent the use of the shadow registers (see Errata Option).

If the software stack is in use, the context switch code will also initialize the stack pointer register so it is accessing the area of the stack reserved for the interrupt. See Software Stack Operation for more information on the software stack.

Assembly code placed in-line within the interrupt function is not scanned for register usage. Thus, if you include in-line assembly code into an interrupt function (or functions called by the interrupt function), you may have to add extra assembly code to save and restore any registers used by the in-line assembly.

When functions are using the reentrant model and a large number of working registers must be preserved, the resulting context switch code can become long, leading to increased interrupt latency. To avoid this situation, use the hardware Interrupt Vector Table (IVT) or alternatively the software interrupt vector table features, where supported, so that an interrupt function can be written for each interrupt source. While writing interrupts in this way will not reduce the total number of registers used and that need to be preserved, it will mean that each interrupt function only needs to preserve a smaller subset of these registers. Additionally, the compiler can be requested to use loops where possible to reduce the size of the context switch code. See the Interrupt-context-loops Option option for more information.