An INTERRUPT procedure is to be executed in the case of a processor hardware interrupt.
Its declaration needs to be qualified with the INTERRUPT keyword and it cannot have arguments:
PROCEDURE InterruptProc; INTERRUPT;
And for PIC18+ processors that have 2 levels of interrupts (note that HIGH is assumed if omitted):
PROCEDURE InterruptProc; INTERRUPT; LOW;
PROCEDURE InterruptProc; INTERRUPT; HIGH;
// Or:
PROCEDURE InterruptProc; INTERRUPT; HIGH; FAST;
The FAST qualifier is used to specify that the PIC18 FAST registers saving and restore have to be used. Due to the behaviors of this mode, only one level of priority may be used.
Interrupt procedures may be multiple and in several units or in the main program (see also the $INTERRUPTS directive).
The compiler inserts the necessary context save / restore code for common registers and system variables.
According to the $INTERRUPTS directive, the code scheme is different:
If $INTERRUPTS MULTIPLE (default):
There may be several interrupt procedures (per priority if PIC18). Each interrupt procedure is called in turn. The order is the order of unit compilations. It is the responsibility to the programmer to check interrupt conditions and pertinence at the beginning of each procedure.
Interrupt code generated by the compiler:
<Context save>
<Call to the 1st interrupt procedure>
…
<Call to the nth interrupt procedure>
<Context restore>
<RETFIE>
If $INTERRUPTS UNIQUE:
This option saves one hardware stack level and may be useful for simple treatments. There may be only one interrupt procedure (per priority if PIC18). It is the responsibility to the programmer to check interrupt conditions and pertinence at the beginning of the procedure.
Interrupt code generated by the compiler:
<Context save>
<Interrupt procedure body>
<Context restore>
<RETFIE>
On context saving:
The context saving is made regarding to the PIC registers and PMP internal variables that are used in the interrupt procedures and all nested calls within the interrupt procedure and the called procedures and functions, along with one level of called internal subroutines.
This does not include procedure and functions parameters and internal variables, so they are definitely not re-entrant if such variables are defined.
The "one level" scheme is not waterproof; within an interrupt procedure it should be avoided to use constructions or to call procedures and functions that may use nested internal subroutines; this includes (not limited to): FP math, all "big" block moves and some built-in functions and procedures like WRITE.
Likewise, PMP internal subroutines should be used with care since most of them may be not re-entrant and some special functions passing arguments are not saved and would be destroyed.
Using the $OPTIMIZE SPEED directive inside the interrupt procedure may help to limit calls to subroutines.
Generally PMP warns about possible reentry issue but again, this is not bulletproof.
There is no special limitation in interrupt procedures, local variables, constants and types may be used.
Assignments to global variables greater than a single byte or boolean should be used with care since global variable read or writes may be interrupted in the middle of the variable move and the result may be unpredictable (“atomic” problem; this is not PMP or PIC specific).