Interrupt Management Overview

[中文]

Overview

bk_avdk_smp currently targets BK7258 (Cortex-M33). Each core owns its own NVIC (interrupt controller), and every external interrupt (for example, peripheral interrupts) can be routed to any core, as shown below.

Interrupt Overview

Interrupt Overview

The interrupt handling framework can be divided into three levels:

  • Peripheral module level – Each peripheral manages its own interrupt enable/disable states.

  • System-control level – System control registers determine which core receives a given peripheral interrupt.

  • Core level – The core’s NVIC determines how the interrupt is handled. For portability, software provides the ICU (Interrupt Control Unit) abstraction.

1. Peripheral Level

In Armino, any peripheral capable of generating an interrupt is called an interrupt source. An interrupt source maps to one INT_SRC_DEV macro, where DEV denotes the peripheral name. For example, the GPIO interrupt source is INT_SRC_GPIO while the SDIO interrupt source is INT_SRC_SDIO. Refer to icu_int_src_t in int_types.h for the list of supported interrupt sources. Specific APIs are provided in each peripheral driver.

Note

Interrupt sources correspond to peripherals rather than individual peripheral channels.

2. System-Control Level

The system-control layer can enable interrupts and decide which CPU receives them. The relevant interfaces live in middleware/driver/sys_ctrl/sys_driver.c.

For the CP subsystem, configure system-level interrupts using:

int32 sys_drv_int_disable(uint32 param);
int32 sys_drv_int_enable(uint32 param);
int32 sys_drv_int_group2_disable(uint32 param);
int32 sys_drv_int_group2_enable(uint32 param);

For the AP subsystem, use the following interfaces:

int32 sys_drv_core_intr_group1_disable(uint32 core_id, uint32 param);
int32 sys_drv_core_intr_group1_enable(uint32 core_id, uint32 param);
int32 sys_drv_core_intr_group2_disable(uint32 core_id, uint32 param);
int32 sys_drv_core_intr_group2_enable(uint32 core_id, uint32 param);

// Example: route the USB interrupt to CPU2
sys_drv_core_intr_group1_enable(CPU2_CORE_ID, USB_INTERRUPT_CTRL_BIT);

Important

BK7258 provides 64 external interrupts in total. Interrupt IDs 0–31 belong to group 1, and IDs 32–63 belong to group 2.

3. Core Level Interfaces

Core-level interrupt controller configuration depends on the CPU architecture. To unify behavior, the software offers the ICU (Interrupt Control Unit) module located in middleware/driver/icu. ICU maintains a mapping table that records information such as interrupt number and default priority.

The ICU exposes the following APIs for application use:

bk_err_t bk_int_isr_register(icu_int_src_t src, int_group_isr_t isr_callback, void *arg); // enable and register
bk_err_t bk_int_set_priority(icu_int_src_t int_src, uint32_t int_priority);               // set priority
bk_err_t bk_int_isr_unregister(icu_int_src_t src);                                        // disable and unregister

Important

When configuring a peripheral interrupt, first call bk_int_isr_register to register the handler, then enable the peripheral interrupt. To remove an interrupt, disable it at the peripheral first, then call bk_int_isr_unregister.

OS Adapters

The OS abstraction layer also offers APIs to mask and unmask interrupts (on Cortex-M33, only NMI and HardFault are serviced while interrupts are masked):

uint32_t rtos_disable_int(void);           // mask interrupts and return previous state
void rtos_enable_int(uint32_t int_level);  // restore interrupt state

Default Initialization

Interrupt initialization occurs in driver_early_init() through a call to interrupt_init().