Enabling and Disabling

This document describes how device drivers enable and disable interrupts.

Drivers can enable and disable the interrupts on the relevant interrupt sources while handling the interrupts using the Interrupt class. Typically, handling an interrupt is done with disabled interrupts. The interrupt is then enabled after the completion of interrupt handling.

Interrupt::Disable(aIntId);
...
// handle interrupt
...
Interrupt::Enable(aIntId);
/**
 Interrupt Service Routine (ISR) for the UART driver. This function
 is associated with the UART interrupt, EUartIrq (value obtained from 
 TRM). This function is called whenever there is an interrupt on this 
 interrupt line and the interrupt source is enabled. The ISR must be a 
 static void function, taking a single TAny* parameter, which is an 
 object passed at the time of binding, usually a pointer to the owning
 class. Interrupt::Enable() must be called to start receiving 
 interrupts.
 
 The ISR implementation is hardware and driver specific. The ISR must
 be self-contained as the state of the system is indeterminate. It
 should not signal threads, allocate or de-allocate memory, copy
 memory to or from user processes, or call most Kernel functions.
 Also the whole system is blocked while the ISR is running, so it must be
 kept as short as possible. Any lengthy processing must be done in a
 delayed function call (DFC).
 
 A typical ISR would,
   Clear the interrupt in the peripheral.
   Disable the interrupt.
   Read or write peripheral registers, e.g. to determine errors, or 
   to start a new task.
   Read data from, or write data to, the peripheral.
   Start or stop NTimers or DMA transfer operations.
   Queue DFCs.
 
 @param     aParam
         pointer to object passed as parameter while binding
 */    

void DExUartPhysicalChannelH4::UartIsr(TAny* aParam)
    {
    // Do the high priority device specific interrupt handling
    // i.e. read the interrupt type from device, clear the 
    // interrupt.
    ...
    // Defer the remaining processing by queuing the respective 
    // DFC based on the interrupt type
    ...
    }

Some operations may need to be performed with all the interrupts, not just the particular interrupt source, disabled. In this case, the NKern class must be used to disable and enable all interrupts globally at the Interrupt controller. NKern::DisableAllInterrupts() can disable all IRQs, or IRQs and FIQs. NKern::RestoreInterrupts() can restore the interrupts to their state before disabling.

alevel = 1; // 1 to disable IRQs and 2 to disable IRQs and FIQs
state = NKern::DisableAllInterrupts(aLevel);
...
// perform the required operations
...
NKern::RestoreInterrupts(state);