Implementing an ISR

An interrupt service routine (ISR) is code that handles interrupt requests (IRQs) on your target device. The ISR is the core of the OAL and is responsible for locating an interrupt source, masking it, and returning a unique identifier to the Windows CE kernel to indicate which driver needs to be used to handle the event.

The ISR only needs to focus on the tick timer interrupt until other user peripherals such as keyboard, mouse, PCMCIA, and USB, are added. When support for other interrupt sources are added to the ISR, there are other interrupt support routines which will need to be implemented for mapping hardware interrupts to unique identifiers — IRQ->SYSINTR mappings, enabling and disabling interrupts, and so on.

Using your OAL code, Windows CE associates each IRQ with an ISR. When an interrupt occurs, the kernel's exception handler calls the registered ISR for that interrupt. Microsoft has optimized the kernel for each microprocessor and defines constants that specify the number of IRQ lines available for each microprocessor. Using the HookInterrupt function in the OAL, you can register only one ISR for each IRQ line. However, you can associate an ISR with one or more interrupt identifiers. In addition, each ISR has the following characteristics:

  • Performs minimal interrupt processing that is enough to verify and acknowledge the hardware that is asserting the interrupt, leaving most of the processing to be performed by the interrupt service thread (IST).
  • Returns an interrupt identifier to the kernel when finished. This causes the kernel to schedule the appropriate IST later.

Note   The Windows CE exception handler only saves and restores a few registers depending on the microprocessor being used. The following table shows the registers you can use.

Microprocessor Registers
ARM All registers are available for use.
MIPS Registers v0, AT, and a0-a3 are available for use.
SHx Registers r0-r3 and r6 are available for use.
x86 All registers are available for use.

A device driver or the OAL can associate the interrupt identifier with an event by creating an IST and calling the InterruptInitialize function. The IST then waits for the event. When the ISR returns to the kernel, the kernel examines the returned interrupt identifier and sets the associated event. The interrupt service handler of the kernel schedules execution of the IST that the driver or OAL created. The IST calls functions in the platform-dependent driver layer to read from and write to the target device.

To manage ISRs, you must implement the ISR management functions that allow the kernel to begin, service, and complete interrupt processing. The following table shows the functions you must implement to support ISR management.

Function Description
OEMInterruptDisable Disables a specified hardware interrupt.
OEMInterruptDone Signals completion of interrupt processing.
OEMInterruptEnable Performs any hardware operations necessary to enable a specified hardware interrupt.

A device driver calls the InterruptInitialize, InterruptDisable, and InterruptDone functions to enable or disable interrupts or to signal the kernel that processing is complete for an interrupt. The kernel translates these calls into the OEMInterruptEnable, OEMInterruptDisable, and OEMInterruptDone functions, respectively. You can use the information that the kernel passes to OEMInterruptEnable to initialize an interrupt or to allocate scratch space for the vendor-defined firmware ISR. When a driver calls InterruptInitialize, the kernel will then call OEMInterruptEnable.

ISR management functions typically use switch statements to decode the interrupt identifier and act on the associated hardware interrupt. The following code example shows how OEMInterruptEnable checks for each of the supported interrupt identifiers.

BOOL OEMInterruptEnable (DWORD idInt, LPVOID pvData, DWORD cbData)
{
  BOOL bRet = TRUE;    // Assume successful return value.

switch (idInt) {
  case SYSINTR_TOUCH:    
    // Enable touch screen analog-to-digital. converter (ADC) interrupt
    break;
  ...
  case SYSINTR_PCMCIA_EDGE:
    // Enable pcmcia edge interrupt and clear it, if one is pending
    break;
  ...
  default:
    bRet = FALSE;      // Return FALSE for an invalid interrupt. 
  }
return bRet;
}

For more information about interrupts, see the following topics:

See Also

How to Develop an OEM Adaptation Layer | Driver Development

Last updated on Wednesday, April 13, 2005

© 2005 Microsoft Corporation. All rights reserved.