Page 433 - Programming Microcontrollers in C
P. 433
418 Chapter 8 MCORE, A RISC Machine
save these registers on the stack. The following two assembly
instructions load the address of table into R2 and the address of
fIpnd1 into R3. We want the contents of the value found in the
FPIND register. Therefore, we must dereference the value in R3 twice,
once to get the address of FPIND and then to get the contents of
FPIND. This value has a bit set for every pending fast interrupt. When
this value is operated on by the FF1 instruction, the register R3 will
contain the 32 minus the bit number of the highest priority pending
interrupt. If you look at how table() is constructed, you will find
that the highest priority interrupts are listed first down to the lowest
priority. Each entry in the table requires four bytes to hold a function
pointer with this system. Therefore, we must multiply the value found
in R3 by 4, shift it left 2, and then add the result to the value in R2 to
find the address of the desired interrupt service routine.
All of that is exactly what is done with the assembly language
insert shown above. The last instruction jsr R2 passes control of
the computer to the specified interrupt service routine. If you look at
the C code generated by handler() you will find first that the
necessary computer status is saved and then the assembly code in the
macro Do_Interrupt() is executed. The last instruction here is
the jsr R2 instruction mentioned above. After the code needed for
the interrupt service routine is completed, control is returned to
handler() where the machine status is restored and control is
returned to the interrupted program with an rfi, return from fast
interrupt, instruction.
The compiler has a #pragma interrupt isr_function. This
#pragma causes the function specified by the isr_function to
be compiled as an interrupt service routine. These functions save a
portion of the machine status, execute the code specified in the
isr_function, and restore the machine status before returning
to the interrupted program with an rfi instruction. When writing a
general function such as the one above, it was found that the partial
status save was not enough. No functions could be called from within
the interrupt service routine. This limitation was too great for a
general-purpose handler like that above, so in this routine, the entire
status of the computer is saved and restored rather than the partial
save and restore generated by the #pragma. It is safe to execute
functions within the interrupt service routines in the handler above.