AU1200 ISR (HAL Interrupt Install)
CE abstracts hardware interrupts into a hardware-independent
handle called a SYSINTR. When a CE device driver acquires use of
a hardware interrupt via the OEMInterruptConnect() call, a
SYSINTR is allocated and associated with the hardware interrupt.
All future references by the device driver to the interrupt utilize
the SYSINTR, for example WaitForSingleOjbect() and InterruptDone().
For the Au1x00, the file intr.c contains all the high-level interrupt
processing required by the HAL. This file contains the code and data
structures for mapping a hardware interrupt to a SYSINTR, and vice
versa. Specifically the structure HwIntrMap[] contains this mapping.
HwIntrMap[] contains 64 entries, exactly the number of interrupt
sources possible with the Au1x00 interrupt controllers. The Au1x00
interrupts are simply numbered 0-31 for IC0, and 32-63 for IC1. Thus
the hardware interrupt number maps directly to the index into HwIntrMap[].
This technique yields best performance since a table lookup is avoided.
The priority of MIPS interrupts is purely a function of the software
(that is, all MIPS interrupts are of equal priority to the processor).
In Windows CE, the CE MIPS kernel extracts the six bit Cause[15:10] field
and uses that value as an index into the IntrPriority[] table to return one
of the possible six hardware interrupt sources. CE kernel then invokes the
ISR associated with that IRQ number. The priority of the six hardware
interrupts as implemented by IntrPriority[] is the following:
Highest Cause[15] Cp0 Count/Compare
Cause[10] Ic0 Request 0
Cause[11] Ic0 Request 1
Cause[12] Ic1 Request 0
Cause[13] Ic1 Request 1
Lowest Cause[14] Au1x00 perf count interface
The interrupt controllers of the Au1x00 assign an interrupt source to one
of two possible request slots: Request 0 or Request 1. This CE interrupt
handling scheme assigns the system timer tick and wakeup timer to Request 0,
all other peripherals are assigned to Request 1. This has the net effect of
making the system timer tick the highest priority interrupt within the
system, as it is needed to be.
Thus, the interrupt arrangement for the Au1x00 is the following:
IRQ Ctrlr Req Cause[IP] Handler Description
=========================================================================
0 0 0 10 Ic0Req0 IC0 Request 0 (High priority, system timer)
1 0 1 11 Ic0Req1 IC0 Request 1 (Low priority, peripherals)
2 1 0 12 Ic1Req0 IC1 Request 0 (High priority)
3 1 1 13 Ic1Req1 IC1 Request 1 (Low priority)
4 - - 14 - Au1x00 perf counters interface
5 - - 15 Cp0Count CP0 Count/Compare (Highest priority, system timer)
There are five low-level ISRs for handling interrupts: Ic0Req0Handler(),
Ic0Req1Handler(), Ic1Req0Handler(), Ic1Req1Handler() and Cp0CountHandler().
These handlers are written in assembly language, and are installed by the calls
to HookInterrupt() in OEMInterruptInit().
Upon taking an interrupt exception, the CE kernel performs basic handling,
extracts Cause[15:10] and indexes into IntrPriority to obtain the hardware
interrupt vector, changes Status[IM] to disable lower priority interrupts
as determined by the IntrMask table and then invokes the appropriate ISR
(registered via the HookInterrupt() call in OEMInterruptInit()). The ISR
runs, examining the information provided in the Au1x00 interrupt controllers,
masks and acknowledges the interrupt in the controller, and then returns the
SYSINTR value for the associated hardware interrupt. CE then uses the SYSINTR
value to schedule an IST or the scheduler, and resumes execution of tasks/threads.
Note: ISRs may only use registers AT, V0, A0, A1, A2, and A3
All ISRs must return via "j ra"