Interrupts
Interrupt priority is 0-0xF
Private Interrupts
Each CPU core has 32 software interrupts that are private and belong to that core. These interrupts are numbers 0-0x1F for each core. The hardware interrupts are not core-specific and start at interrupt ID 0x20.
IRQ | Listener | Description |
---|---|---|
0-0x5 | MPCore software-interrupt. | |
0x6 | Kernel | MPCore software-interrupt. |
0x7 | MPCore software-interrupt. | |
0x8 | Kernel | MPCore software-interrupt. Used for scheduling. |
0x9-0xE | MPCore software-interrupt. | |
0xF | dmnt/debugger | MPCore software-interrupt. Used to abstract FIQ (debug). |
0x1D | Kernel | MPCore timer. |
0x1E | Kernel | MPCore watchdog - set when the watchdog counter reaches 0 in timer mode, causes interrupt 30 to set as pending. Only set on core 1 as core 1's timer is used for everything. |
Hardware Interrupts
There are 0x60 hardware interrupts starting at 0x20 and continuing up to 0x7F. These are not private and are accessible from any core.
IRQ | Listener | Description |
---|---|---|
0x28 | gsp, TwlBg | PSC0? |
0x29 | gsp, TwlBg | PSC1? |
0x2A | gsp, TwlBg | PDC0? |
0x2B | gsp, TwlBg | PDC1? |
0x2C | gsp, TwlBg | PPF? |
0x2D | gsp, TwlBg | ? |
0x30 | Kernel | ? |
0x39 | Kernel | DMA |
0x3A | Kernel | DMA |
0x3B | Kernel | DMA |
0x40 | nwm | WIFI SDIO Controller @ 0x10122000 |
0x41 | nwm | ? |
0x42 | nwm_dev? | WIFI SDIO Controller @ 0x10100000 |
0x45 | mvd (New3DS) | ? |
0x46 | mvd (New3DS) | ? |
0x48 | camera | ? |
0x49 | camera | ? |
0x4A | dsp | ? |
0x4B | camera | Y2R Conversion Finished |
0x4C | TwlBg | ? |
0x4D | TwlBg | ? |
0x4E | mvd (New3DS) | ? |
0x4F | mvd (New3DS) | ? |
0x50 | pxi, TwlBg | Sync |
0x51 | pxi, TwlBg | ? |
0x52 | pxi, TwlBg | Send Fifo Empty |
0x53 | pxi, TwlBg | Receive Fifo Not Empty |
0x54 | i2c, TwlBg | ? |
0x55 | i2c, TwlBg | ? |
0x56 | spi, TwlBg | ? |
0x57 | spi, TwlBg | ? |
0x58 | Kernel | PDN |
0x59 | TwlBg | ? |
0x5A | mic | ? |
0x5C | i2c, TwlBg | ? |
0x60 | gpio, TwlBg | Asserted when shell is opened? |
0x62 | gpio, TwlBg | Asserted when shell is closed? |
0x63 | gpio, TwlBg | Touchscreen |
0x64 | gpio, TwlBg | Headphone jack plugged in |
0x66 | gpio, TwlBg | ? |
0x68 | gpio, TwlBg | IR? |
0x69 | gpio, TwlBg | ? |
0x6A | gpio, TwlBg | ? |
0x6B | gpio, TwlBg | ? |
0x6C | gpio, TwlBg | ? |
0x6D | gpio, TwlBg | ? |
0x6E | gpio, TwlBg | ? |
0x6F | gpio, TwlBg | ? |
0x70 | gpio, TwlBg | Headphone jack plugged out |
0x71 | gpio, TwlBg | MCU (HOME/POWER pressed) |
0x72 | gpio, TwlBg | ? |
0x73 | TwlBg | ? |
0x74 | ? | Gamecard related |
0x75 | ? | Gamecard inserted |
There are 2 tables in the ARM11 kernel: the first has 32 * 2(or 32 * 4) 8-byte entries. This table is for the private interrupts that belong to each core. The data for each interrupt can be found by doing table_base + (core_num * 0x100) + (intr_num * 8). The second table is for public hardware interrupts and the data for each interrupt can be retrieved by doing table_base + (intr_num * 8).
InterruptData
Offset | Type | Description |
---|---|---|
0x0 | InterruptEvent * | Pointer to the InterruptEvent object for that interrupt |
0x4 | u8 | Interrupt will be masked by the IRQ handler as soon as it is acknowledged |
0x5 | u8 | Interrupt is masked |
0x6 | u8 | Interrupt priority |
0x7 | u8 | Unused, alignment |
Interrupt Table (New3DS)
(0xFFF318F4 in 10.3)
Offset | Type | Description |
---|---|---|
0x0 | InterruptData[224] | Data for all hardware and software interrupts |
0x700 | KThread* | Thread currently acting on the interrupt table |
0x704 | s16 | Error tracker for thread above |
0x706 | u16 | Alignment |
InterruptEvent
Base class for interrupt events.
The kernel uses the KInterruptEvent field of a KEvent when binding public interrupts per svcBindInterrupt request, whereas it internally uses a static object of another subclass to bind interrupt 0x0F (FIQ abstraction).
The first first word in the object is a pointer to the object's vtable and the first function in the vtable is the interrupt handler for that interrupt number. When an interrupt runs, the function is passed its object in r0 and the interrupt number in r1.