// Handle the interrupt.
InterruptDone(pIst->sysIntr);
}
When the IST has completed processing an IRQ, it should call InterruptDone to inform the system that the interrupt was processed, that the IST is ready to handle the next IRQ, and that the interrupt can be reenabled by means of an OEMInterruptDone call. Table 6-6 lists the OAL functions that the system uses to interact with the interrupt controller to manage interrupts.
Table 6-6 OAL functions for interrupt management
Function | Description |
---|---|
OEMInterruptEnable | This function is called by the kernel in response to InterruptInitialize and enables the specified interrupt in the interrupt controller. |
OEMInterruptDone | This function is called by the kernel in response to InterruptDone and should unmask the interrupt and acknowledge the interrupt in the interrupt controller. |
OEMInterruptDisable | This function disables the interrupt in the interrupt controller and is called in response to the InterruptDisable function. |
OEMInterruptHandler | For ARM processors only, this function identifies the interrupt SYSINTR that occurs by looking at the status of the interrupt controller. |
HookInterrupt | For processors other than ARM, this function registers a callback function for a specified interrupt ID. This function must be called in the OEMInit function to register mandatory interrupts. |
OEMInterruptHandlerFIQ | For ARM processors, used to handle interrupts for the Fast Interrupt (FIQ) line. |
Do not use the WaitForMultipleObjects function to wait for an interrupt event. If you must wait for multiple interrupt events, you should create an IST for each interrupt.
Interrupt Identifiers (IRQ and SYSINTR)
Each hardware interrupt line corresponds to an IRQ value in the interrupt controller registers. Each IRQ value can be associated with only one ISR, but an ISR can map to multiple IRQs. The kernel does not need to maintain the IRQs. It just determines and signals events associated with the SYSINTR values returned from the ISR in response to the IRQ. The ability to return varying SYSINTR values from an ISR provides the basis to support multiple devices that use the same shared interrupt.
Target devices that only support a single IRQ, such as ARM-based systems, use the OEMInterruptHandler function as the ISR to identify the embedded peripheral that triggered the interrupt. Original equipment manufacturers (OEMs) must implement this function as part of the OAL. On platforms that support multiple IRQs, such as Intel x86-based systems, you can associate the IRQs with individual ISRs by calling HookInterrupt.
Static Interrupt Mappings
For the ISR to determine a correct SYSINTR return value there must be a mapping between the IRQ and the SYSINTR, which can be hardcoded into the OAL. The Bsp_cfg.h file for the Device Emulator BSP demonstrates how to define a SYSINTR value in the OAL for a target device relative to the SYSINTR_FIRMWARE value. If you want to define additional identifiers in your OAL for a custom target device, keep in mind that the kernel reserves all values below SYSINTR_FIRMWARE for future use and the maximum value should be less than SYSINTR_MAXIMUM.
To add a mapping of static SYSINTR values to IRQs on a target device, you can call the OALIntrStaticTranslate function during system initialization. For example, the Device Emulator BSP calls OALIntrStaticTranslate in the BSPIntrInit function to register a custom SYSINTR value for the built-in Open Host Controller Interface (OHCI) in the kernel's interrupt mapping arrays (g_oalSysIntr2Irq and g_oalIrq2SysIntr). However, static SYSINTR values and mappings are not a common way to associate IRQs with SYSINTRs because it is difficult and requires OAL code changes to implement custom interrupt handling. Static SYSINTR values are typically used for core hardware components of a target device where there is no explicit device driver and the ISR resides in the OAL.
Dynamic Interrupt Mappings
The good news is that you do not need to hardcode SYSINTR values into the OAL if you call KernelIoControl in your device drivers with an IO control code of IOCTL_HAL_REQUEST_SYSINTR to register IRQ/SYSINTR mappings. The call eventually ends in the OALIntrRequestSysIntr function, which dynamically allocates a new SYSINTR for the given IRQ, and then registers the IRQ and SYSINTR mappings in the kernel's interrupt mapping