AT91RM9200 interrupt controller — Advanced Interrupt Controller definitions and usage

Interrupt controller definitions

The file <cyg/hal/var_ints.h> (located at hal/arm/arm9/at91rm9200/VERSION/include/var_ints.h in the eCos source repository) contains interrupt vector number definitions for use with the eCos kernel and driver interrupt APIs:

#define CYGNUM_HAL_INTERRUPT_FIQ     0 // Advanced Interrupt Controller (FIQ)
#define CYGNUM_HAL_INTERRUPT_SYSTEM  1 // System Peripheral (debug unit, system timer)
#define CYGNUM_HAL_INTERRUPT_PIOA    2 // Parallel IO Controller A
#define CYGNUM_HAL_INTERRUPT_PIOB    3 // Parallel IO Controller B
#define CYGNUM_HAL_INTERRUPT_PIOC    4 // Parallel IO Controller C
#define CYGNUM_HAL_INTERRUPT_PIOD    5 // Parallel IO Controller D
#define CYGNUM_HAL_INTERRUPT_MCI    10 // Multimedia Card Interface
#define CYGNUM_HAL_INTERRUPT_UDP    11 // USB Device Port
#define CYGNUM_HAL_INTERRUPT_TWI    12 // Two-Wire Interface
#define CYGNUM_HAL_INTERRUPT_SPI    13 // Serial Peripheral Interface
#define CYGNUM_HAL_INTERRUPT_SSC0   14 // Serial Synchronous Controller 0
#define CYGNUM_HAL_INTERRUPT_SSC1   15 // Serial Synchronous Controller 1
#define CYGNUM_HAL_INTERRUPT_SSC2   16 // Serial Synchronous Controller 2
#define CYGNUM_HAL_INTERRUPT_TC0    17 // Timer Counter 0
#define CYGNUM_HAL_INTERRUPT_TC1    18 // Timer Counter 1
#define CYGNUM_HAL_INTERRUPT_TC2    19 // Timer Counter 2
#define CYGNUM_HAL_INTERRUPT_TC3    20 // Timer Counter 3
#define CYGNUM_HAL_INTERRUPT_TC4    21 // Timer Counter 4
#define CYGNUM_HAL_INTERRUPT_TC5    22 // Timer Counter 5
#define CYGNUM_HAL_INTERRUPT_UHP    23 // USB Host port
#define CYGNUM_HAL_INTERRUPT_EMAC   24 // Ethernet MAC
#define CYGNUM_HAL_INTERRUPT_IRQ0   25 // Advanced Interrupt Controller (IRQ0)
#define CYGNUM_HAL_INTERRUPT_IRQ1   26 // Advanced Interrupt Controller (IRQ1)
#define CYGNUM_HAL_INTERRUPT_IRQ2   27 // Advanced Interrupt Controller (IRQ2)
#define CYGNUM_HAL_INTERRUPT_IRQ3   28 // Advanced Interrupt Controller (IRQ3)
#define CYGNUM_HAL_INTERRUPT_IRQ4   29 // Advanced Interrupt Controller (IRQ4)
#define CYGNUM_HAL_INTERRUPT_IRQ5   30 // Advanced Interrupt Controller (IRQ5)
#define CYGNUM_HAL_INTERRUPT_IRQ6   31 // Advanced Interrupt Controller (IRQ6)

// The following interrupts are derived from the SYSTEM interrupt
#define CYGNUM_HAL_INTERRUPT_DEBUG  32 // Debug unit
#define CYGNUM_HAL_INTERRUPT_PMC    33 // Power Management Controller
#define CYGNUM_HAL_INTERRUPT_RTCH   34 // Real Time Clock
#define CYGNUM_HAL_INTERRUPT_PIT    35 // System Timer Period Interval Timer
#define CYGNUM_HAL_INTERRUPT_WDOVF  36 // System Timer Watchdog Overflow
#define CYGNUM_HAL_INTERRUPT_RTTINC 37 // System Timer Real-Time Timer Increment
#define CYGNUM_HAL_INTERRUPT_ALM    38 // System Timer Alarm

As indicated above, further decoding is performed on the SYSTEM interrupt to identify the cause more specifically. Note that as a result, placing an interrupt handler on the SYSTEM interrupt will not work as expected. Conversely, masking a decoded derivative of the SYSTEM interrupt will not work as this would mask other SYSTEM interrupts, but masking the SYSTEM interrupt itself will work. On the other hand, unmasking a decoded SYSTEM interrupt will unmask the SYSTEM interrupt as a whole, thus unmasking interrupts for the other units on this shared interrupt.

The list of interrupt vectors may be augmented on a per-platform basis. Consult the platform HAL documentation for your platform for whether this is the case.

Interrupt controller functions

The source file src/at91rm9200_misc.c within this package provides most of the support functions to manipulate the interrupt controller. The hal_IRQ_handler queries the IRQ status register to determine the interrupt cause. Functions hal_interrupt_mask and hal_interrupt_unmask enable or disable interrupts within the interrupt controller.

Interrupts are configured in the hal_interrupt_configure function, where the level and up arguments are interpreted as follows:

levelupinterrupt on
00Falling Edge
01Rising Edge
10Low Level
11High Level

To fit into the eCos interrupt model, interrupts essentially must be acknowledged immediately once decoded, and as a result, the hal_interrupt_acknowledge function is empty.

The hal_interrupt_set_level is used to set the priority level of the supplied interrupt within the Advanced Interrupt Controller.

Note that in all the above, it is not recommended to call the described functions directly. Instead either the HAL macros (HAL_INTERRUPT_MASK et al) or preferably the kernel or driver APIs should be used to control interrupts.

Using the Advanced Interrupt Controller for VSRs

The AT91RM9200 HAL has been designed to exploit benefits of the on-chip Advanced Interrupt Controller (AIC) on the AT91RM9200. Support has been included for exploiting its ability to provide hardware vectoring for VSR interrupt handlers.

This support is dependent on definitions that may only be provided by the platform HAL and therefore is only enabled if the platform HAL package implements the CYGINT_HAL_AT91RM9200_AIC_VSR CDL interface. The necessary definitions are available to all platform HALs which use the facilities of the header file.

The interrupt decoding path has been optimised by allowing the AIC to be interrogated for the interrupt handler VSR to use. These vectored interrupts are by default still configured to point to the default ARM architecture HAL IRQ and FIQ VSRs. However applications may set their own VSRs to override this default behaviour to allow optimised interrupt handling.

The VSR vector numbers to use when overriding are defined as follows:

#define CYGNUM_HAL_VECTOR_FIQ     7 // FIQ
#define CYGNUM_HAL_VECTOR_SYSTEM  8 // System Peripheral (debug unit, system timer)
#define CYGNUM_HAL_VECTOR_PIOA    9 // Parallel IO Controller A
#define CYGNUM_HAL_VECTOR_PIOB   10 // Parallel IO Controller B
#define CYGNUM_HAL_VECTOR_PIOC   11 // Parallel IO Controller C
#define CYGNUM_HAL_VECTOR_PIOD   12 // Parallel IO Controller D
#define CYGNUM_HAL_VECTOR_US0    13 // USART 0
#define CYGNUM_HAL_VECTOR_US1    14 // USART 1
#define CYGNUM_HAL_VECTOR_US2    15 // USART 2
#define CYGNUM_HAL_VECTOR_US3    16 // USART 3
#define CYGNUM_HAL_VECTOR_MCI    17 // Multimedia Card Interface
#define CYGNUM_HAL_VECTOR_UDP    18 // USB Device Port
#define CYGNUM_HAL_VECTOR_TWI    19 // Two-Wire Interface
#define CYGNUM_HAL_VECTOR_SPI    20 // Serial Peripheral Interface
#define CYGNUM_HAL_VECTOR_SSC0   21 // Serial Synchronous Controller 0
#define CYGNUM_HAL_VECTOR_SSC1   22 // Serial Synchronous Controller 1
#define CYGNUM_HAL_VECTOR_SSC2   23 // Serial Synchronous Controller 2
#define CYGNUM_HAL_VECTOR_TC0    24 // Timer Counter 0
#define CYGNUM_HAL_VECTOR_TC1    25 // Timer Counter 1
#define CYGNUM_HAL_VECTOR_TC2    26 // Timer Counter 2
#define CYGNUM_HAL_VECTOR_TC3    27 // Timer Counter 3
#define CYGNUM_HAL_VECTOR_TC4    28 // Timer Counter 4
#define CYGNUM_HAL_VECTOR_TC5    29 // Timer Counter 5
#define CYGNUM_HAL_VECTOR_UHP    30 // USB Host port
#define CYGNUM_HAL_VECTOR_EMAC   31 // Ethernet MAC
#define CYGNUM_HAL_VECTOR_IRQ0   32 // Advanced Interrupt Controller (IRQ0)
#define CYGNUM_HAL_VECTOR_IRQ1   33 // Advanced Interrupt Controller (IRQ1)
#define CYGNUM_HAL_VECTOR_IRQ2   34 // Advanced Interrupt Controller (IRQ2)
#define CYGNUM_HAL_VECTOR_IRQ3   35 // Advanced Interrupt Controller (IRQ3)
#define CYGNUM_HAL_VECTOR_IRQ4   36 // Advanced Interrupt Controller (IRQ4)
#define CYGNUM_HAL_VECTOR_IRQ5   37 // Advanced Interrupt Controller (IRQ5)
#define CYGNUM_HAL_VECTOR_IRQ6   38 // Advanced Interrupt Controller (IRQ6)

Consult the kernel and generic HAL documentation for more information on VSRs and how to set them.

Interrupt handling within standalone applications

For non-eCos standalone applications running under RedBoot, it is possible to install an interrupt handler into the interrupt vector table manually. Memory mappings are platform-dependent and so the platform documentation should be consulted, but in general the address of the interrupt table can be determined by analyzing RedBoot's symbol table, and searching for the address of the symbol name hal_interrupt_handlers. Table slots correspond to the interrupt numbers above. Pointers inserted in this table should be pointers to a C/C++ function with the following prototype:

extern unsigned int isr( unsigned int vector, unsigned int data );

For non-eCos applications run from RedBoot, the return value can be ignored. The vector argument will also be the interrupt vector number. The data argument is extracted from a corresponding table named hal_interrupt_data which immediately follows the interrupt vector table. It is still the responsibility of the application to enable and configure the interrupt source appropriately if needed.