Implementing an ISR (Windows Embedded CE 6.0)

1/5/2010

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 Embedded 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 Embedded 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 Embedded 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, v1, AT, t0 through t7, and a0 through a3 are available for use.

    SHx

    Registers r0 through r7 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 hardware 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 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

Tasks

How to Develop an OEM Adaptation Layer

Other Resources

Developing a Device Driver