4. 中断控制器(ICU)与外部中断

在 RA 系列 MCU 中,中断系统由两个层次共同构成:Cortex-M 内核自带的 NVIC(Nested Vectored Interrupt Controller)负责内核异常与可屏蔽中断的优先级仲裁、嵌套与向量跳转;而 Renesas 的 ICU(Interrupt Controller Unit)位于外设与 NVIC 之间,负责把来自 GPIO、定时器、串口、ADC 等外设的中断请求进行汇聚、使能、优先级分配,并最终向 NVIC 提交。理解这两者的分工,是正确配置外部中断与按键唤醒的前提。

NVIC 与 ICU 的职责边界

可以把 ICU 看作“外设中断的集线器”,NVIC 看作“内核的调度器”。外设产生中断事件后,先进入 ICU 的 IRQn 通道,ICU 根据寄存器设置决定是否放行、映射到哪个 NVIC 中断线,并携带优先级信息;NVIC 再根据当前执行优先级决定立即响应、挂起还是嵌套。RA 的 FSP(Flexible Software Package)通过 R_ICU_ExternalIrqOpen()、R_ICU_ExternalIrqEnable() 等 API 封装了 ICU 侧配置,而 NVIC 侧的使能与优先级设置由 NVIC_EnableIRQ()、NVIC_SetPriority() 完成。两者必须同时正确,中断才会真正触发。

RA MCU 中断信号链:外设 → ICU → NVIC → CPU GPIO / 按键 IRQ 边沿/电平 定时器 / 串口 事件请求 ADC / 其他 转换完成 ICU 中断控制器 • 中断使能 / 屏蔽 • 触发方式选择 • 优先级分配 (IPR) • 中断状态标志 • 唤醒源配置 IRQn → NVIC 中断线映射 NVIC(Cortex-M 内核) • 优先级仲裁 • 嵌套与抢占 • 向量表跳转 • 挂起 / 激活状态 • PRIMASK/BASEPRI ISR 入口地址 CPU 执行 ISR 优先级与嵌套关系(数值越小优先级越高) 高优先级 IRQ (IPR=1) ──→ 可抢占低优先级 ISR (IPR=5) 同优先级 IRQ ──→ 不嵌套,按到达顺序依次执行 BASEPRI 屏蔽阈值 ──→ 低于阈值的 IRQ 被延迟响应

外部中断 IRQ 配置要点

以 RA6M5 的 P105 引脚接按键为例,配置外部中断需要完成以下关键步骤。首先在 FSP 的 Stacks 中添加 External IRQ 模块,选择 IRQ 通道(如 IRQ1),设置触发方式为“下降沿”或“双边沿”。按键按下时电平从高变低,下降沿触发最直观;若需要检测按下与释放两个动作,则选双边沿。随后在引脚配置中将 P105 设为 IRQ1 功能,并确认该引脚未被其他外设占用。

触发方式的选择直接影响中断行为:电平触发在按键持续按下时会反复进入 ISR,适合需要持续响应的场景;边沿触发只在跳变瞬间产生一次请求,更适合按键计数。FSP 生成的 g_external_irq1 结构体包含了通道号、触发类型和回调函数指针,调用 R_ICU_ExternalIrqOpen() 完成 ICU 侧初始化后,还需调用 R_ICU_ExternalIrqEnable() 使能该通道。此时 NVIC 侧的中断使能通常由 FSP 在 Open 中一并完成,但若手动管理,需确认 NVIC_EnableIRQ(ICU_IRQ1_IRQn) 已执行。

中断优先级与嵌套

Cortex-M 的优先级数值越小,优先级越高。RA 的 ICU 为每个 IRQ 通道提供独立的 IPR 寄存器,可设置 0~15 级(具体位数取决于芯片实现)。NVIC 侧通过 NVIC_SetPriority() 设置对应中断线的优先级,两者需要保持一致或由 FSP 统一管理。嵌套的前提是:新中断的优先级高于当前正在执行的 ISR 优先级,且当前 ISR 未被 BASEPRI 屏蔽。例如,IRQ1 设为优先级 2,IRQ2 设为优先级 5,当 IRQ2 的 ISR 正在执行时,IRQ1 到来可以抢占并嵌套执行;反之则需等待。

在按键中断中,若 ISR 内需要执行较耗时的去抖或业务逻辑,建议只做标志置位,把处理放到主循环或低优先级任务中,避免长时间占用高优先级中断导致其他中断延迟。

按键中断唤醒与去抖处理

RA 支持在低功耗模式下由外部中断唤醒。进入 Sleep 或 Software Standby 前,需确保 ICU 中对应 IRQ 通道保持使能,且该中断未被 BASEPRI 屏蔽。以 P105 下降沿触发为例,配置流程为:初始化 IRQ1 → 设置触发沿 → 使能 ICU 通道 → 配置 NVIC 优先级 → 调用 R_LPM_LowPowerModeEnter() 进入低功耗。按键按下产生下降沿,ICU 将请求提交 NVIC,NVIC 唤醒内核并跳转 ISR。

机械按键在按下和释放瞬间会产生 5~20 ms 的抖动,若不加处理,一次按键可能触发多次中断。常见的去抖策略有两种:一是在 ISR 中启动一个 10~20 ms 的定时器,定时到期后再读取引脚电平确认;二是在 ISR 中记录时间戳,若与上次中断间隔小于阈值则忽略。以下是一个基于 R_ICU_ExternalIrqCallback 的软件去抖示例:

volatile uint32_t g_key_tick = 0;
volatile bool g_key_pressed = false;

void irq1_callback(external_irq_callback_args_t *p_args)
{
    uint32_t now = R_BSP_GetTickCount();
    if ((now - g_key_tick) > 20) {   /* 20ms 去抖窗口 */
        g_key_tick = now;
        g_key_pressed = true;         /* 仅置标志,主循环处理 */
    }
}

/* 主循环中 */
if (g_key_pressed) {
    g_key_pressed = false;
    /* 执行按键业务逻辑 */
}

若使用双边沿触发,去抖窗口需要覆盖按下与释放两个阶段,通常建议窗口设为 20~30 ms。对于要求更高的场景,可以结合硬件 RC 滤波(如 10 kΩ 上拉 + 100 nF 电容,时间常数约 1 ms)与软件去抖共同使用。判断去抖是否有效,可以在 ISR 入口翻转一个 GPIO,用示波器观察:若一次按键只产生一个脉冲,说明去抖生效;若出现多个脉冲,则需增大去抖窗口或检查硬件滤波。

在低功耗唤醒场景中,若去抖逻辑依赖系统滴答定时器,而该定时器在低功耗模式下已停止,则时间戳比较会失效。此时应改用 RTC 或专用低功耗定时器提供时基,或在唤醒后先做一次引脚电平确认再决定是否响应。

配置检查清单

检查项确认内容常见问题
引脚复用P105 已设为 IRQ1 功能被其他外设占用导致无中断
触发方式下降沿 / 双边沿与硬件匹配电平触发导致重复进入 ISR
ICU 使能R_ICU_ExternalIrqEnable 已调用仅 Open 未 Enable,中断不触发
NVIC 优先级与 ICU IPR 一致且合理优先级冲突导致嵌套异常
去抖窗口20~30 ms 覆盖抖动时间窗口过短,一次按键多次触发
低功耗唤醒IRQ 通道在休眠前保持使能休眠时被屏蔽,无法唤醒

掌握 ICU 与 NVIC 的协作关系后,外部中断的配置就不再是“填参数碰运气”,而是可以按信号链逐段排查:先确认外设事件是否到达 ICU,再确认 ICU 是否放行并映射到正确的 NVIC 线,最后确认 NVIC 优先级与屏蔽状态是否允许响应。按键唤醒与去抖则是这一链路在低功耗与机械触点场景下的典型应用,去抖窗口、触发沿和时基选择需要根据实际硬件与功耗要求综合权衡。