BCM2835 Interrupt Controller
The BCM2835 Interrupt Controller is a memory-mapped peripheral available on the BCM2835 System-on-a-Chip used in the Raspberry Pi. It allows software to enable or disable specific IRQs. Each IRQ usually corresponds to some sort of device available on the chip.
Hardware Details
It is important to understand that on the BCM2835, some IRQs are shared between the ARM CPU and VideoCore GPU. This interrupt controller controls both these shared IRQs as well as a few ARM-specific IRQs, and the layout of the registers reflects this separation. Some of the shared IRQs are already enabled by the GPU and therefore should not be enabled. However, this interrupt controller is only used by the ARM to control which interrupts actually get routed to the ARM; the GPU most likely has its own interrupt controller.
Offset | Name | Description |
---|---|---|
0x00 | IRQ_basic_pending | Bitmask of pending ARM-specific IRQs, as well as additional bits (not currently used by Embedded Xinu) to accelerate interrupt handling. |
0x04 | IRQ_pending_1 | Bitmask of pending shared IRQs 0-31 |
0x08 | IRQ_pending_2 | Bitmask of pending shared IRQs 32-63 |
0x0C | FIQ_control | TODO |
0x10 | Enable_IRQs_1 | Write 1 to the corresponding bit(s) to enable one or more shared IRQs in the range 0-31 |
0x14 | Enable_IRQs_2 | Write 1 to the corresponding bit(s) to enable one or more shared IRQs in the range 32-63 |
0x18 | Enable_Basic_IRQs | Write 1 to the corresponding bit(s) to enable one or more ARM-specific IRQs |
0x1C | Disable_IRQs_1 | Write 1 to the corresponding bit(s) to disable one or more shared IRQs in the range 0-31 |
0x20 | Disable_IRQs_2 | Write 1 to the corresponding bit(s) to disable one or more shared IRQs in the range 32-63 |
0x24 | Disable_Basic_IRQs | Write 1 to the corresponding bit(s) to disable one or more ARM-specific IRQs |
IRQ | Device | Notes |
---|---|---|
0 | System Timer Compare Register 0 | Do not enable this IRQ; it's already used by the GPU. |
1 | System Timer Compare Register 1 | See BCM2835 System Timer. |
2 | System Timer Compare Register 2 | Do not enable this IRQ; it's already used by the GPU. |
3 | System Timer Compare Register 3 | See BCM2835 System Timer. |
9 | USB Controller | This is the only USB IRQ because all communication with USB devices happens through the USB Controller. See USB Host Controller (Synopsys DesignWare OTG). |
55 | PCM Audio | |
57 | PL011 UART | See PL011 UART. |
62 | SD Host Controller |
Notes:
- Software cannot "clear" interrupts using the interrupt controller. Instead, interrupts must be cleared in a device-specific way.
- Although some shared interrupts appear in the IRQ_Basic_Pending register as well as in the IRQ_Pending_1 or IRQ_Pending_2 registers, they cannot be enabled or disabled in Enable_Basic_IRQs or Disable_Basic_IRQs.
Use in Embedded Xinu
Embedded Xinu uses the BCM2835 Interrupt Controller to implement enable_irq() and disable_irq(). The code is in system/platforms/arm-rpi/dispatch.c. These functions simply are passed the number of the IRQ to enable or disable. Shared IRQs are numbered 0-63, while ARM-specific IRQs (currently not actually used) are numbered starting at 64. Also in this file you will find dispatch(), which is called from the assembly language IRQ handler in system/platforms/arm-rpi/irq_handler.S to handle an interrupt. The point of dispatch() is to figure out which number IRQs are actually pending, then call the registered interrupt handler for each.