|This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.|
Most peripheral devices cause or signal interrupts on the bus of a Windows CE–based platform in order to receive service from the operating system. Some examples of devices that can use interrupts are PC Cards, onboard timers, audio input devices, keyboards, touch screens, pointing devices, etc. Nearly any type of peripheral, whether it is built into a Windows CE-based platform or not, might use interrupts as the principle method of initiating servicing actions by the operating system. Because these peripheral devices can cause or signal interrupts, their device drivers must process interrupts in order to service their devices. Device drivers for USB client devices that use interrupt transfers are a special case; such USB client devices do generate interrupts, but the interrupts are processed by the USB host controller, not by the device drivers themselves.
Interrupt processing in Windows CE is broken into two components, a kernel-mode Interrupt Service Routine (ISR) and a user-mode Interrupt Service Thread (IST). ISRs are generally small, very fast pieces of assembly code. Their sole job is to return a logical interrupt ID to the kernel. The kernel then invokes the proper IST to perform any possibly lengthy operations that must occur to fully process the interrupt. For example, a serial port might raise an interrupt when data arrives from a modem device. The serial port ISR would inform the kernel that the serial port had an interrupt. The kernel would call the serial port IST, which could then access the serial port hardware's receive buffer to transfer the data into a buffer, for use by an application.
Device drivers must therefore do two things when they are loaded at boot time. First, they must register their ISR with the kernel, so that the kernel calls the ISR when the appropriate physical interrupt occurs. Second, they must spawn an IST, which then registers to receive interrupt notifications. ISTs can use the InterruptInitializefunction to register themselves, and use the WaitForSingleObjectfunction to wait for interrupt events. Stream interface drivers generally do these things when their XXX_Init function is called; native device drivers that do not use the stream interface must find a convenient time during initialization to register their ISR and spawn an IST.
The following illustration shows the interaction of components during interrupt processing.
The exception handler is the primary target of all interrupts. When an interrupt occurs, the kernel jumps directly to the exception handler. The exception handler then calls the ISR registered to handle the current interrupt. OEMs register their ISRs with the exception handler at system boot time. First, the kernel calls the OEMInitfunction in the OAL. Next, OEMInitcalls the HookInterruptfunction to inform the exception handler of which ISRs correspond to individual physical interrupt lines. A few subroutines in the OAL, such as the OEMInterruptEnable, OEMInterruptDisable, and OEMInterruptDonefunctions, are also used in interrupt processing. The interrupt handler manages the details of registering a driver for a particular interrupt and deregistering it later. It also maintains communication among the ISR, the IST, and subroutines within the OAL.
Monolithic drivers can use the Interrupt Event Handler Supportinterface provided by the kernel. This interface is a lightweight process-synchronization model based on standard Win32 events. The interface consists of event-related functions, such as CreateEvent, SetEvent, ResetEvent, and WaitForSingleObject, and the Windows CE kernel InterruptDone, InterruptDisable, and InterruptInitializefunctions. Layered drivers use the same functions to process interrupts, but you need not use these functions to port layered drivers because the model device driver (MDD) layer — which does not require modification — already contains the proper calls to these functions.
Windows CE uses this two-level structure for interrupt processing because, when an interrupt occurs, some other interrupts may be masked while the ISR is running. In Windows CE 2.12 and earlier, interrupts could not be nested at all, so all interrupts were masked while an ISR was in progress. Therefore, in Windows CE 2.12 and earlier, it was critically important that ISRs complete in a minimum amount of time. An ISR that used too much time could cause other interrupts to be missed entirely, resulting in erratic or sluggish performance of the whole system. By separating interrupt processing into a very short ISR and a longer IST, interrupts could be masked for as little time as possible.
Windows CE 3.0 and later allow nested interrupts, in conjunction with the Real-Time Priority System. In Windows CE 3.0 and later, interrupts of a higher priority may preempt ISRs of a lower priority; ISRs now only mask interrupts of equal or lower priority than themselves. The kernel handles the details of saving an ISR's state when a higher priority interrupt occurs and restoring it after the high priority ISR has completed. In most cases, a preempted ISR does not detect that it has been preempted. The level of interrupt nesting is limited solely by what the Windows CE-based platform's hardware can support.
ISTs for some types of peripheral devices do not receive interrupt notifications from the kernel directly. For peripherals that connect to a Windows CE-based platform via some intermediate hardware, the device driver for that intermediate hardware should have a mechanism for passing the interrupt notification up to the top level device driver. For example, PC Cards connect to Windows CE-based platforms through a PC Card slot, which is a separate piece of hardware and has its own device driver. Thus, when a PC Card device raises an interrupt, it is actually the PC Card slot hardware that signals the physical interrupt on the system bus. The PC Card slot's device driver has an ISR and IST that handle the physical interrupt, and pass it to the device driver for the PC Card device by means of the CardRequestIRQfunction. Other peripherals with similar connection methods behave similarly. Generally, the intermediate hardware's device driver has some facility that allows another device driver to register a callback function, which the intermediate device driver calls when an interrupt occurs.
Last updated on Tuesday, July 13, 2004