hardware-irq
硬件中断处理 API。
详细描述
RP2040 使用标准的 ARM 嵌套向量中断控制器(NVIC)。
中断由 0 到 31 的编号标识。
在 RP2040 上,NVIC 上只连接了低 26 个 IRQ 信号;IRQ 26 到 31 被置零(永不触发)。
每个核心有一个 NVIC,每个核心的 NVIC 连接相同的硬件中断线,但 IO 中断除外——每个 bank、每个核心各有一个 IO 中断。这些中断完全独立,例如,处理器 0 可以被 bank 0 中的 GPIO 0 中断,处理器 1 可以被同一 bank 中的 GPIO 1 中断。
所有 IRQ API 仅影响正在执行的核心(即调用该函数的核心)。
不应在两个核心上同时启用同一(共享)IRQ 编号,因为这会导致竞态条件或其中一个核心饥饿。此外,请记住,在一个核心上禁用中断不会禁用另一个核心上的中断。
有三种不同的方式为 IRQ 设置处理程序:
-
在运行时调用 irq_add_shared_handler() 为当前核心上的多路复用中断(例如 GPIO bank)添加处理程序。每个处理程序都应检查并清除相关的硬件中断源
-
在运行时调用 irq_set_exclusive_handler() 为当前核心上的中断安装单一处理程序
-
在应用程序中显式定义中断处理程序(例如,定义 void isr_dma_0 将使该函数成为核心 0 上 DMA_IRQ_0 的处理程序,并且无法在运行时使用上述 API 更改)。使用此方法可能在运行时导致链接冲突,且不提供运行时性能优势(即通常不应使用此方法)。
如果启用了 IRQ 但触发时未安装处理程序,将命中断点,且 IRQ 编号将存在于寄存器 r0 中。
中断编号
提供了一组定义([intctrl.h]),使用这些名称可避免直接使用数字。
RP2040 的中断编号如下:
| IRQ | 中断源 |
|---|---|
| 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 | ADC_IRQ_FIFO |
| 23 | I2C0_IRQ |
| 24 | I2C1_IRQ |
| 25 | RTC_IRQ |
RP2350 的中断编号如下:
| IRQ | 中断源 |
|---|---|
| 0 | TIMER0_IRQ_0 |
| 1 | TIMER0_IRQ_1 |
| 2 | TIMER0_IRQ_2 |
| 3 | TIMER0_IRQ_3 |
| 4 | TIMER1_IRQ_0 |
| 5 | TIMER1_IRQ_1 |
| 6 | TIMER1_IRQ_2 |
| 7 | TIMER1_IRQ_3 |
| 8 | PWM_IRQ_WRAP_0 |
| 9 | PWM_IRQ_WRAP_1 |
| 10 | DMA_IRQ_0 |
| 11 | DMA_IRQ_1 |
| 12 | DMA_IRQ_2 |
| 13 | DMA_IRQ_3 |
| 14 | USBCTRL_IRQ |
| 15 | PIO0_IRQ_0 |
| 16 | PIO0_IRQ_1 |
| 17 | PIO1_IRQ_0 |
| 18 | PIO1_IRQ_1 |
| 19 | PIO2_IRQ_0 |
| 20 | PIO2_IRQ_1 |
| 21 | IO_IRQ_BANK0 |
| 22 | IO_IRQ_BANK0_NS |
| 23 | IO_IRQ_QSPI |
| 24 | IO_IRQ_QSPI_NS |
| 25 | SIO_IRQ_FIFO |
| 26 | SIO_IRQ_BELL |
| 27 | SIO_IRQ_FIFO_NS |
| 28 | SIO_IRQ_BELL_NS |
| 29 | SIO_IRQ_MTIMECMP |
| 30 | CLOCKS_IRQ |
| 31 | SPI0_IRQ |
| 32 | SPI1_IRQ |
| 33 | UART0_IRQ |
| 34 | UART1_IRQ |
| 35 | ADC_IRQ_FIFO |
| 36 | I2C0_IRQ |
| 37 | I2C1_IRQ |
| 38 | OTP_IRQ |
| 39 | TRNG_IRQ |
| 40 | PROC0_IRQ_CTI |
| 41 | PROC1_IRQ_CTI |
| 42 | PLL_SYS_IRQ |
| 43 | PLL_USB_IRQ |
| 44 | POWMAN_IRQ_POW |
| 45 | POWMAN_IRQ_TIMER |
| 46 | SPARE_IRQ_0 |
| 47 | SPARE_IRQ_1 |
| 48 | SPARE_IRQ_2 |
| 49 | SPARE_IRQ_3 |
| 50 | SPARE_IRQ_4 |
| 51 | SPARE_IRQ_5 |
类型定义
typedef enum irq_num_rp2350 irq_num_t RP2350
RP2350 上的中断编号(用作 typedef irq_num_t)
typedef enum irq_num_rp2040 irq_num_t RP2040
RP2040 上的中断编号(用作 typedef irq_num_t)
typedef void(* irq_handler_t)(void)
中断处理程序函数类型。
枚举
enum irq_num_rp2350 { [TIMER0_IRQ_0] = 0, [TIMER0_IRQ_1] = 1, [TIMER0_IRQ_2] = 2, [TIMER0_IRQ_3] = 3, [TIMER1_IRQ_0] = 4, [TIMER1_IRQ_1] = 5, [TIMER1_IRQ_2] = 6, [TIMER1_IRQ_3] = 7, [PWM_IRQ_WRAP_0] = 8, [PWM_IRQ_WRAP_1] = 9, [DMA_IRQ_0] = 10, [DMA_IRQ_1] = 11, [DMA_IRQ_2] = 12, [DMA_IRQ_3] = 13, [USBCTRL_IRQ] = 14, [PIO0_IRQ_0] = 15, [PIO0_IRQ_1] = 16, [PIO1_IRQ_0] = 17, [PIO1_IRQ_1] = 18, [PIO2_IRQ_0] = 19, [PIO2_IRQ_1] = 20, [IO_IRQ_BANK0] = 21, [IO_IRQ_BANK0_NS] = 22, [IO_IRQ_QSPI] = 23, [IO_IRQ_QSPI_NS] = 24, [SIO_IRQ_FIFO] = 25, [SIO_IRQ_BELL] = 26, [SIO_IRQ_FIFO_NS] = 27, [SIO_IRQ_BELL_NS] = 28, [SIO_IRQ_MTIMECMP] = 29, [CLOCKS_IRQ] = 30, [SPI0_IRQ] = 31, [SPI1_IRQ] = 32, [UART0_IRQ] = 33, [UART1_IRQ] = 34, [ADC_IRQ_FIFO] = 35, [I2C0_IRQ] = 36, [I2C1_IRQ] = 37, [OTP_IRQ] = 38, [TRNG_IRQ] = 39, [PROC0_IRQ_CTI] = 40, [PROC1_IRQ_CTI] = 41, [PLL_SYS_IRQ] = 42, [PLL_USB_IRQ] = 43, [POWMAN_IRQ_POW] = 44, [POWMAN_IRQ_TIMER] = 45, [SPARE_IRQ_0] = 46, [SPARE_IRQ_1] = 47, [SPARE_IRQ_2] = 48, [SPARE_IRQ_3] = 49, [SPARE_IRQ_4] = 50, [SPARE_IRQ_5] = 51, IRQ_COUNT } RP2350
RP2350 上的中断编号(用作 typedef irq_num_t)
enum irq_num_rp2040 { [TIMER_IRQ_0] = 0, [TIMER_IRQ_1] = 1, [TIMER_IRQ_2] = 2, [TIMER_IRQ_3] = 3, [PWM_IRQ_WRAP] = 4, [USBCTRL_IRQ] = 5, [XIP_IRQ] = 6, [PIO0_IRQ_0] = 7, [PIO0_IRQ_1] = 8, [PIO1_IRQ_0] = 9, [PIO1_IRQ_1] = 10, [DMA_IRQ_0] = 11, [DMA_IRQ_1] = 12, [IO_IRQ_BANK0] = 13, [IO_IRQ_QSPI] = 14, [SIO_IRQ_PROC0] = 15, [SIO_IRQ_PROC1] = 16, [CLOCKS_IRQ] = 17, [SPI0_IRQ] = 18, [SPI1_IRQ] = 19, [UART0_IRQ] = 20, [UART1_IRQ] = 21, [ADC_IRQ_FIFO] = 22, [I2C0_IRQ] = 23, [I2C1_IRQ] = 24, [RTC_IRQ] = 25, [SPARE_IRQ_0] = 26, [SPARE_IRQ_1] = 27, [SPARE_IRQ_2] = 28, [SPARE_IRQ_3] = 29, [SPARE_IRQ_4] = 30, [SPARE_IRQ_5] = 31, IRQ_COUNT } RP2040
RP2040 上的中断编号(用作 typedef irq_num_t)
函数
void irq_set_priority (uint num, uint8_t hardware_priority): 设置指定中断的优先级。uint irq_get_priority (uint num): 获取指定中断的优先级。void irq_set_enabled (uint num, bool enabled): 在执行核心上启用或禁用特定中断。bool irq_is_enabled (uint num): 判断特定中断是否在执行核心上已启用。uint32_t irq_get_mask (void): 获取执行核心上当前启用的掩码。uint32_t irq_get_mask_n (uint n): 获取执行核心上当前启用的掩码。void irq_set_mask_enabled (uint32_t mask, bool enabled): 在执行核心上启用/禁用多个中断。void irq_set_mask_n_enabled (uint n, uint32_t mask, bool enabled): 在执行核心上启用/禁用多个中断。void irq_set_exclusive_handler (uint num, irq_handler_t handler): 为执行核心上的中断设置独占中断处理程序。- irq_handler_t irq_get_exclusive_handler (uint num): 获取执行核心上中断的独占中断处理程序。
void irq_add_shared_handler (uint num, irq_handler_t handler, uint8_t order_priority): 为执行核心上的中断添加共享中断处理程序。void irq_remove_handler (uint num, irq_handler_t handler): 移除执行核心上给定 irq 编号的特定中断处理程序。bool irq_has_handler (uint num): 判断给定中断编号是否安装了 IRQ 处理程序。bool irq_has_shared_handler (uint num): 判断给定中断编号的当前 IRQ 处理程序是否为共享处理程序。- irq_handler_t irq_get_vtable_handler (uint num): 从执行核心当前安装的硬件向量表(VTOR)中获取指定 IRQ 的当前 IRQ 处理程序。
static void irq_clear (uint int_num): 清除执行核心上的特定中断。void irq_set_pending (uint num): 强制在执行核心上挂起一个中断。void user_irq_claim (uint irq_num): 在调用核心上声明用户 IRQ 的所有权。void user_irq_unclaim (uint irq_num): 将调用核心上的用户 IRQ 标记为不再使用。int user_irq_claim_unused (bool required): 在调用核心上声明一个空闲用户 IRQ 的所有权。
类型定义文档
irq_num_t RP2350
typedef enum irq_num_rp2350 irq_num_t
RP2350 上的中断编号(用作 typedef irq_num_t)
irq_num_t RP2040
typedef enum irq_num_rp2040 irq_num_t
RP2040 上的中断编号(用作 typedef irq_num_t)
irq_handler_t
typedef void(* irq_handler_t) (void)
中断处理程序函数类型。
所有中断处理程序应为此类型,并遵循正常的 ARM EABI 寄存器保存约定。
枚举类型文档
irq_num_rp2350 RP2350
enum irq_num_rp2350
RP2350 上的中断编号(用作 typedef irq_num_t)
| 枚举值 | 说明 |
|---|---|
| TIMER0_IRQ_0 | 选择 TIMER0 的 IRQ 0 输出。 |
| TIMER0_IRQ_1 | 选择 TIMER0 的 IRQ 1 输出。 |
| TIMER0_IRQ_2 | 选择 TIMER0 的 IRQ 2 输出。 |
| TIMER0_IRQ_3 | 选择 TIMER0 的 IRQ 3 输出。 |
| TIMER1_IRQ_0 | 选择 TIMER1 的 IRQ 0 输出。 |
| TIMER1_IRQ_1 | 选择 TIMER1 的 IRQ 1 输出。 |
| TIMER1_IRQ_2 | 选择 TIMER1 的 IRQ 2 输出。 |
| TIMER1_IRQ_3 | 选择 TIMER1 的 IRQ 3 输出。 |
| PWM_IRQ_WRAP_0 | 选择 PWM 的 WRAP_0 IRQ 输出。 |
| PWM_IRQ_WRAP_1 | 选择 PWM 的 WRAP_1 IRQ 输出。 |
| DMA_IRQ_0 | 选择 DMA 的 IRQ 0 输出。 |
| DMA_IRQ_1 | 选择 DMA 的 IRQ 1 输出。 |
| DMA_IRQ_2 | 选择 DMA 的 IRQ 2 输出。 |
| DMA_IRQ_3 | 选择 DMA 的 IRQ 3 输出。 |
| USBCTRL_IRQ | 选择 USBCTRL 的 IRQ 输出。 |
| PIO0_IRQ_0 | 选择 PIO0 的 IRQ 0 输出。 |
| PIO0_IRQ_1 | 选择 PIO0 的 IRQ 1 输出。 |
| PIO1_IRQ_0 | 选择 PIO1 的 IRQ 0 输出。 |
| PIO1_IRQ_1 | 选择 PIO1 的 IRQ 1 输出。 |
| PIO2_IRQ_0 | 选择 PIO2 的 IRQ 0 输出。 |
| PIO2_IRQ_1 | 选择 PIO2 的 IRQ 1 输出。 |
| IO_IRQ_BANK0 | 选择 IO_BANK0 的 IRQ 输出。 |
| IO_IRQ_BANK0_NS | 选择 IO_BANK0_NS 的 IRQ 输出。 |
| IO_IRQ_QSPI | 选择 IO_QSPI 的 IRQ 输出。 |
| IO_IRQ_QSPI_NS | 选择 IO_QSPI_NS 的 IRQ 输出。 |
| SIO_IRQ_FIFO | 选择 SIO 的 FIFO IRQ 输出。 |
| SIO_IRQ_BELL | 选择 SIO 的 BELL IRQ 输出。 |
| SIO_IRQ_FIFO_NS | 选择 SIO_NS 的 FIFO IRQ 输出。 |
| SIO_IRQ_BELL_NS | 选择 SIO_NS 的 BELL IRQ 输出。 |
| SIO_IRQ_MTIMECMP | 选择 SIO 的 MTIMECMP IRQ 输出。 |
| CLOCKS_IRQ | 选择 CLOCKS 的 IRQ 输出。 |
| SPI0_IRQ |