Hardware interrupt handling. More...
Typedefs | |
typedef void(* | irq_handler_t) (void) |
Interrupt handler function type. More... | |
Functions | |
void | irq_set_priority (uint num, uint8_t hardware_priority) |
Set specified interrupt's priority. More... | |
uint | irq_get_priority (uint num) |
Get specified interrupt's priority. More... | |
void | irq_set_enabled (uint num, bool enabled) |
Enable or disable a specific interrupt on the executing core. More... | |
bool | irq_is_enabled (uint num) |
Determine if a specific interrupt is enabled on the executing core. More... | |
void | irq_set_mask_enabled (uint32_t mask, bool enabled) |
Enable/disable multiple interrupts on the executing core. More... | |
void | irq_set_exclusive_handler (uint num, irq_handler_t handler) |
Set an exclusive interrupt handler for an interrupt on the executing core. More... | |
irq_handler_t | irq_get_exclusive_handler (uint num) |
Get the exclusive interrupt handler for an interrupt on the executing core. More... | |
void | irq_add_shared_handler (uint num, irq_handler_t handler, uint8_t order_priority) |
Add a shared interrupt handler for an interrupt on the executing core. More... | |
void | irq_remove_handler (uint num, irq_handler_t handler) |
Remove a specific interrupt handler for the given irq number on the executing core. More... | |
bool | irq_has_shared_handler (uint num) |
Determine if the current handler for the given number is shared. More... | |
irq_handler_t | irq_get_vtable_handler (uint num) |
Get the current IRQ handler for the specified IRQ from the currently installed hardware vector table (VTOR) of the execution core. More... | |
static void | irq_clear (uint int_num) |
Clear a specific interrupt on the executing core. More... | |
void | irq_set_pending (uint num) |
Force an interrupt to be pending on the executing core. More... | |
void | user_irq_claim (uint irq_num) |
Claim ownership of a user IRQ on the calling core. More... | |
void | user_irq_unclaim (uint irq_num) |
Mark a user IRQ as no longer used on the calling core. More... | |
int | user_irq_claim_unused (bool required) |
Claim ownership of a free user IRQ on the calling core. More... | |
Hardware interrupt handling.
The RP2040 uses the standard ARM nested vectored interrupt controller (NVIC).
Interrupts are identified by a number from 0 to 31.
On the RP2040, only the lower 26 IRQ signals are connected on the NVIC; IRQs 26 to 31 are tied to zero (never firing).
There is one NVIC per core, and each core's NVIC has the same hardware interrupt lines routed to it, with the exception of the IO interrupts where there is one IO interrupt per bank, per core. These are completely independent, so, for example, processor 0 can be interrupted by GPIO 0 in bank 0, and processor 1 by GPIO 1 in the same bank.
There are three different ways to set handlers for an IRQ:
isr_dma_0
will make that function the handler for the DMA_IRQ_0 on core 0, and you will not be able to change it using the above APIs at runtime). Using this method can cause link conflicts at runtime, and offers no runtime performance benefit (i.e, it should not generally be used).Interrupts are numbered as follows, a set of defines is available (intctrl.h) with these names to avoid using the numbers directly.
IRQ | Interrupt Source |
---|---|
0 | TIMER_IRQ_0 |
1 | TIMER_IRQ_1 |
2 | TIMER_IRQ_2 |
3 | TIMER_IRQ_3 |
4 | PWM_IRQ_WRAP |
5 | USBCTRL_IRQ |
6 | XIP_IRQ |
7 | PIO0_IRQ_0 |
8 | PIO0_IRQ_1 |
9 | PIO1_IRQ_0 |
10 | PIO1_IRQ_1 |
11 | DMA_IRQ_0 |
12 | DMA_IRQ_1 |
13 | IO_IRQ_BANK0 |
14 | IO_IRQ_QSPI |
15 | SIO_IRQ_PROC0 |
16 | SIO_IRQ_PROC1 |
17 | CLOCKS_IRQ |
18 | SPI0_IRQ |
19 | SPI1_IRQ |
20 | UART0_IRQ |
21 | UART1_IRQ |
22 | ADC0_IRQ_FIFO |
23 | I2C0_IRQ |
24 | I2C1_IRQ |
25 | RTC_IRQ |
typedef void(* irq_handler_t) (void) |
Interrupt handler function type.
All interrupts handlers should be of this type, and follow normal ARM EABI register saving conventions
void irq_add_shared_handler | ( | uint | num, |
irq_handler_t | handler, | ||
uint8_t | order_priority | ||
) |
Add a shared interrupt handler for an interrupt on the executing core.
Use this method to add a handler on an irq number shared between multiple distinct hardware sources (e.g. GPIO, DMA or PIO IRQs). Handlers added by this method will all be called in sequence from highest order_priority to lowest. The irq_set_exclusive_handler() method should be used instead if you know there will or should only ever be one handler for the interrupt.
This method will assert if there is an exclusive interrupt handler set for this irq number on this core, or if the (total across all IRQs on both cores) maximum (configurable via PICO_MAX_SHARED_IRQ_HANDLERS) number of shared handlers would be exceeded.
num | Interrupt number Interrupt Numbers |
handler | The handler to set. See irq_handler_t |
order_priority | The order priority controls the order that handlers for the same IRQ number on the core are called. The shared irq handlers for an interrupt are all called when an IRQ fires, however the order of the calls is based on the order_priority (higher priorities are called first, identical priorities are called in undefined order). A good rule of thumb is to use PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY if you don't much care, as it is in the middle of the priority range by default. |
|
inlinestatic |
Clear a specific interrupt on the executing core.
This method is only useful for "software" IRQs that are not connected to hardware (i.e. IRQs 26-31) as the the NVIC always reflects the current state of the IRQ state of the hardware for hardware IRQs, and clearing of the IRQ state of the hardware is performed via the hardware's registers instead.
int_num | Interrupt number Interrupt Numbers |
irq_handler_t irq_get_exclusive_handler | ( | uint | num | ) |
Get the exclusive interrupt handler for an interrupt on the executing core.
This method will return an exclusive IRQ handler set on this core by irq_set_exclusive_handler if there is one.
num | Interrupt number Interrupt Numbers |
uint irq_get_priority | ( | uint | num | ) |
Get specified interrupt's priority.
Numerically-lower values indicate a higher priority. Hardware priorities range from 0 (highest priority) to 255 (lowest priority) though only the top 2 bits are significant on ARM Cortex-M0+. To make it easier to specify higher or lower priorities than the default, all IRQ priorities are initialized to PICO_DEFAULT_IRQ_PRIORITY by the SDK runtime at startup. PICO_DEFAULT_IRQ_PRIORITY defaults to 0x80
num | Interrupt number Interrupt Numbers |
irq_handler_t irq_get_vtable_handler | ( | uint | num | ) |
Get the current IRQ handler for the specified IRQ from the currently installed hardware vector table (VTOR) of the execution core.
num | Interrupt number Interrupt Numbers |
bool irq_has_shared_handler | ( | uint | num | ) |
Determine if the current handler for the given number is shared.
num | Interrupt number Interrupt Numbers |
bool irq_is_enabled | ( | uint | num | ) |
Determine if a specific interrupt is enabled on the executing core.
num | Interrupt number Interrupt Numbers |
void irq_remove_handler | ( | uint | num, |
irq_handler_t | handler | ||
) |
Remove a specific interrupt handler for the given irq number on the executing core.
This method may be used to remove an irq set via either irq_set_exclusive_handler() or irq_add_shared_handler(), and will assert if the handler is not currently installed for the given IRQ number
num | Interrupt number Interrupt Numbers |
handler | The handler to removed. |
void irq_set_enabled | ( | uint | num, |
bool | enabled | ||
) |
Enable or disable a specific interrupt on the executing core.
num | Interrupt number Interrupt Numbers |
enabled | true to enable the interrupt, false to disable |
void irq_set_exclusive_handler | ( | uint | num, |
irq_handler_t | handler | ||
) |
Set an exclusive interrupt handler for an interrupt on the executing core.
Use this method to set a handler for single IRQ source interrupts, or when your code, use case or performance requirements dictate that there should no other handlers for the interrupt.
This method will assert if there is already any sort of interrupt handler installed for the specified irq number.
num | Interrupt number Interrupt Numbers |
handler | The handler to set. See irq_handler_t |
void irq_set_mask_enabled | ( | uint32_t | mask, |
bool | enabled | ||
) |
Enable/disable multiple interrupts on the executing core.
mask | 32-bit mask with one bits set for the interrupts to enable/disable Interrupt Numbers |
enabled | true to enable the interrupts, false to disable them. |
void irq_set_pending | ( | uint | num | ) |
Force an interrupt to be pending on the executing core.
This should generally not be used for IRQs connected to hardware.
num | Interrupt number Interrupt Numbers |
void irq_set_priority | ( | uint | num, |
uint8_t | hardware_priority | ||
) |
Set specified interrupt's priority.
num | Interrupt number Interrupt Numbers |
hardware_priority | Priority to set. Numerically-lower values indicate a higher priority. Hardware priorities range from 0 (highest priority) to 255 (lowest priority) though only the top 2 bits are significant on ARM Cortex-M0+. To make it easier to specify higher or lower priorities than the default, all IRQ priorities are initialized to PICO_DEFAULT_IRQ_PRIORITY by the SDK runtime at startup. PICO_DEFAULT_IRQ_PRIORITY defaults to 0x80 |
void user_irq_claim | ( | uint | irq_num | ) |
Claim ownership of a user IRQ on the calling core.
User IRQs are numbered 26-31 and are not connected to any hardware, but can be triggered by irq_set_pending.
This method explicitly claims ownership of a user IRQ, so other code can know it is being used.
irq_num | the user IRQ to claim |
int user_irq_claim_unused | ( | bool | required | ) |
Claim ownership of a free user IRQ on the calling core.
User IRQs are numbered 26-31 and are not connected to any hardware, but can be triggered by irq_set_pending.
This method explicitly claims ownership of an unused user IRQ if there is one, so other code can know it is being used.
required | if true the function will panic if none are available |
void user_irq_unclaim | ( | uint | irq_num | ) |
Mark a user IRQ as no longer used on the calling core.
User IRQs are numbered 26-31 and are not connected to any hardware, but can be triggered by irq_set_pending.
This method explicitly releases ownership of a user IRQ, so other code can know it is free to use.
irq_num | the irq irq_num to unclaim |