User`s manual

186 digi.com Using Assembly Language
11.7 Interrupt Routines in Assembly
Interrupt Service Routines (ISRs) may be written in Dynamic C (declared with the keyword interrupt). But
since an assembly routine may be more efficient than the equivalent C function, assembly is more suitable
for an ISR. Even if the execution time of an ISR is not critical, the latency of one ISR may affect the
latency of other ISRs.
Either stand-alone assembly code or embedded assembly code may be used for ISRs. The benefit of
embedding assembly code in a C-language ISR is that there is no need to worry about saving and restoring
registers or reenabling interrupts. The drawback is that the C interrupt function does save all registers,
which takes some amount of time. A stand-alone assembly routine needs to save and restore only the regis-
ters it uses.
11.7.1 Steps Followed by an ISR
The CPU loads the Interrupt Priority register (IP) with the priority of the interrupt before the ISR is called.
This effectively turns off interrupts that are of the same or lower priority. Generally, the ISR performs the
following actions:
1. Save all registers that will be used, i.e., push them on the stack. Interrupt routines written in C save all
registers automatically. Stand-alone assembly routines must push the registers explicitly.
2. Push and pop the LXPC as a defensive programming strategy to avoid corrupting large memory support.
For example, the LCALL instruction clears the LXPC so it is essential that this register is saved before
issuing an LCALL and restored after the LRET.
3. Determine the cause of the interrupt. Some devices map multiple causes to the same interrupt vector. An
interrupt handler must determine what actually caused the interrupt.
4. Remove the cause of the interrupt.
5. If an interrupt has more than one possible cause, check for all the causes and remove all the causes at the
same time.
6. When finished, restore registers saved on the stack. Naturally, this code must match the code that saved
the registers. Interrupt routines written in C perform this automatically. Stand-alone assembly routines
must pop the registers explicitly.
7. Restore the interrupt priority level so that other interrupts can get the attention of the CPU. ISRs written
in C restore the interrupt priority level automatically when the function returns. However, stand-alone
assembly ISRs must restore the interrupt priority level explicitly by calling ipres.
The interrupt priority level must be restored immediately before the return instructions ret or
reti. If the interrupts are enabled earlier, the system can stack up the interrupts. This may or
may not be acceptable because there is the potential to overflow the stack.
8. Return. There are two types of interrupt returns: ret and reti.
The value in IP is shown in the status bar at the bottom of the Dynamic C window. If a breakpoint is
encountered, the IP value shown on the status bar reflects the saved context of IP from just before the
breakpoint.