ARM11 Interrupts: Difference between revisions
| Line 12: | Line 12: | ||
!  Description  | !  Description  | ||
|-  | |-  | ||
| 0-  | | 0-0x3  | ||
|    | |    | ||
| MPCore software-interrupt.  | | MPCore software-interrupt.  | ||
|-  | |||
| 0x4  | |||
| Kernel  | |||
| MPCore software-interrupt.  | |||
|-  | |||
| 0x5  | |||
| Kernel  | |||
| MPCore software-interrupt. Does apparently nothing.  | |||
|-  | |-  | ||
| 0x6  | | 0x6  | ||
| Kernel  | | Kernel  | ||
| MPCore software-interrupt.  | | MPCore software-interrupt. Extensively used by [[SVC|KernelSetState]] (and contains most of the actual code of the latter).  | ||
|-  | |-  | ||
| 0x7  | | 0x7  | ||
|    | | Kernel  | ||
| MPCore software-interrupt.  | | MPCore software-interrupt.  | ||
|-  | |-  | ||
| Line 28: | Line 36: | ||
| MPCore software-interrupt. Used for scheduling.  | | MPCore software-interrupt. Used for scheduling.  | ||
|-  | |-  | ||
| 0x9-0xE  | | 0x9  | ||
|    | | Kernel  | ||
| MPCore software-interrupt. Used by, e.g., [[SVC|FlushProcessDataCache]].  | |||
|-  | |||
| 0xA  | |||
| Kernel  | |||
| MPCore software-interrupt.  | |||
|-  | |||
| 0xB-0xE  | |||
|  | |||
| MPCore software-interrupt.  | | MPCore software-interrupt.  | ||
|-  | |-  | ||
| 0xF  | | 0xF  | ||
| dmnt/debugger  | | dmnt/debugger  | ||
| MPCore software-interrupt. Used to abstract FIQ (debug).  | | MPCore software-interrupt. Used to abstract FIQ (debug). This interrupt is never sent to core2 nor core3 on N3DS.  | ||
|-  | |-  | ||
| 0x1D  | | 0x1D  | ||
Revision as of 03:06, 19 November 2016
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-0x3 | MPCore software-interrupt. | |
| 0x4 | Kernel | MPCore software-interrupt. | 
| 0x5 | Kernel | MPCore software-interrupt. Does apparently nothing. | 
| 0x6 | Kernel | MPCore software-interrupt. Extensively used by KernelSetState (and contains most of the actual code of the latter). | 
| 0x7 | Kernel | MPCore software-interrupt. | 
| 0x8 | Kernel | MPCore software-interrupt. Used for scheduling. | 
| 0x9 | Kernel | MPCore software-interrupt. Used by, e.g., FlushProcessDataCache. | 
| 0xA | Kernel | MPCore software-interrupt. | 
| 0xB-0xE | MPCore software-interrupt. | |
| 0xF | dmnt/debugger | MPCore software-interrupt. Used to abstract FIQ (debug). This interrupt is never sent to core2 nor core3 on N3DS. | 
| 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
Abstract base class for interrupt events.
| Offset | Type | Description | 
|---|---|---|
| 0x0 | void ** | Pointer to vtable | 
| 0x4 | u32 | Unknown | 
The first method in the table is virtual KInterruptEvent* InterruptEvent::getKInterruptEvent(u32 interruptID) = 0. It's actually the function called by the IRQ handler, which returns a KInterruptEvent to signal.
If NULL or 1 is returned, no event will be signaled. If NULL is returned, no post-interrupt rescheduling will be done.
The second method is virtual void InterruptEvent::signalEvent(void) = 0, which signals the associated KEvent object.
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).