−Table of Contents
IRQ controller
The IRQ controller is presumably able to schedule and distribute IRQs based on a priority order.
Registers
The IRQ controller has the following registers:
Address | Desc. |
---|---|
0xF0001200 | Shorthand IRQ enable for IRQ 0x00..0x0F |
0xF0001204 | Shorthand IRQ enable for IRQ 0x10..0x1F |
0xF0001208+(N*4) | IRQ enable for IRQ N |
0xF00013F0 | Current IRQ index |
0xF00013F4 | Last IRQ index? |
0xF00013F8 | IRQ priority mask and acknowledge |
0xF00013FC | IRQ priority mask read and clear |
0xF0001420+(N*4) | IRQ trigger type for IRQ N |
0xF00019D8 | General IRQ enable? |
0xF00019DC | Unknown, set to 0 |
0xF00019F8 | Read-only mirror of 0xF00013F8 |
0xF00019FC | Read-only mirror of 0xF00013FC |
Stock firmware tries to initialize registers 0xF0001520..0xF000153C. These registers don't seem to actually exist. Likely, this is a mistake, and that code was intended to access registers 0xF00014A0..0xF00014BC.
0xF0001200
Shorthand IRQ enable for IRQ 0x00..0x0F.
Bits 0..15 correspond to IRQ 0x00..0x0F respectively. A 0 bit enables an IRQ, a 1 bit disables it.
Changing this register changes bit 6 in the corresponding IRQs' enable registers, and vice versa. This register is useful for quickly enabling or disabling multiple IRQs in a row.
0xF0001204
Shorthand IRQ enable for IRQ 0x10..0x1F.
Function same as 0xF0001200.
0xF0001208+(N*4)
IRQ enable.
Bits | Desc. |
---|---|
0-3 | Priority |
4 | ?? |
5 | ?? |
6 | IRQ disable; 0=enable, 1=disable |
8 | ?? |
12 | ?? line value? (read only; for IRQ 0x20-0x28, maybe others?) |
13 | ?? |
14 | ?? |
0xF00013F0
Index of the source of the IRQ currently being serviced.
When there is a pending IRQ, reading from this register resets the IRQ priority mask at 0xF00013F8 to zero, effectively masking out all interrupts until the current interrupt is handled. Register 0xF00013F0 is also reset to 0x80 after a read.
Reads as 0x80 when there is no pending IRQ.
0xF00013F4
Seems to be the index of the last IRQ? When reading 0xF00013F0, the value that is read out is copied to 0xF00013F4.
However, reading 0xF00013F4 has no side effect.
0xF00013F8
4-bit IRQ priority “mask”. Actually a number that masks out interrupts with priority equal to or above it. 0xF is the lightest setting, which only masks out priority 0xF.
This register is copied to 0xF00013FC upon IRQ.
Writing to this register also acknowledges the current interrupt.
0xF00013FC
4-bit IRQ priority “mask” read and clear. This value is meant to be written back to 0xF00013F8 once the current interrupt is handled.
This register is read-only.
0xF0001420+(N*4)
Affects the way each IRQ is triggered, but it is not yet known in which way exactly. Observed values are 1 and 5. It appears that 1 means edge trigger and 5 means level trigger. Not sure if other values are possible.
Some IRQ sources will not function correctly without the correct trigger type. For example, VBlank IRQs will only fire once if their trigger type is set to 5.
In practice, some IRQ lines likely stay active only for a very short time, while others will stay active as long as the underlying IRQ conditions are met (ie. from hardware components that have their own IRQ status registers; the IRQ line may stay active until the IRQ status register is cleared).
IRQ trigger type 5 seems to fail to register an interrupt when the pulse is too short (ie. doesn't work for VBlank IRQ).
The trigger type might also play a role in whether/how the IRQ line is buffered or treated? Values 0-7 are possible. Different values affect the different bits (8/12/13/14) in the IRQ enable registers. Some values don't work at all.
Typically, it seems that 1 is used for IRQ sources that are “self-acknowledging” (ie. VBlank, timers, DMA, …), and 5 is used for IRQ sources that need explicit acknowledgement (ie. SPI, I2C, audio, …).
0xF00019D8
Initialized to 1. Setting to 0 disables interrupts.
0xF00019DC
Initialized to 0. Setting to 1 disables interrupts.
Unlike 0xF00019D8, this register seems to completely disable IRQ input/processing.
0xF00019F8
Read-only mirror of 0xF00013F8.
0xF00019FC
Mirror of 0xF00013FC.
IRQ sources
Here are the indexes of the possible IRQ sources, and the settings the stock firmware assigns them:
IRQ index | Trigger | Desc. |
---|---|---|
0x00 | 1 | Timer 0 |
0x01 | 1 | Timer 1 |
0x02 | 1 | SDIO |
0x03 | 5 | UART0 |
0x04 | 5 | UART1 |
0x05 | 5 | UART2 |
0x06 | 5 | SPI |
0x07 | 5 | SPI related? |
0x08 | 1 | DMA0 |
0x09 | 1 | DMA1 |
0x0A | 1 | ??? |
0x0B | 1 | ??? |
0x0C | 1 | DMA4 |
0x0D | 1 | DMA2 |
0x0E | 1 | DMA3 |
0x0F | 5 | I2C |
0x10 | 5 | vcapt/camera |
0x11 | 5 | vcapt/camera |
0x12 | 5 | vout |
0x13 | 5 | ??? |
0x14 | 5 | vcapt/camera |
0x15 | 1 | VBlank end |
0x16 | 1 | VBlank start |
0x17 | 5 | Audio output event |
0x18 | 5 | Audio input event |
0x19 | 5 | ??? |
0x1A | 5 | ??? |
0x1B | 5 | ??? |
0x1C | 5 | ??? |
0x1D | 5 | vcapt/camera |
0x1E | 1 | VCount match |
0x1F | 1 | ??? |
0x20 | 1? | ??? |
0x21 | 1? | ??? |
0x22 | 1? | ??? |
0x23 | 1? | ??? |
0x24 | 1? | ??? (video related, 0xF00094F8) |
0x25 | 1? | ??? |
0x26 | 1? | ??? (video related, 0xF000940C) |
0x27 | 1? | ??? |
Note: trigger type for IRQ 0x02 is set to 1, which can cause a SDIO IRQ to be missed if it fires while another SDIO IRQ is being processed. Changing it to 5 fixes that problem. The stock firmware doesn't have that problem because it only uses the SDIO IRQ for the wifi card IRQ, and uses busy-loop polling to sense the end of SDIO transfers.
IRQ 0x20..0x27 are actually FIQ sources. Not known what they're all about. Also unknown how to acknowledge a FIQ? Register 0xF00013F0 reads as 0x80 during a FIQ.
The stock firmware doesn't use FIQs, and doesn't even have a FIQ handler (FIQ is redirected to the general exception handler).