STM32H7 480MHz 下 FDCAN 与以太网并发中断优先级仲裁策略

一、为什么需要关注中断优先级仲裁?

在 STM32H7 系列(如 STM32H743/750)中,CPU 主频高达 480MHz,外设如 FDCAN(Flexible Data-rate CAN)和以太网 MAC 均支持高吞吐率。当两者同时产生中断时,若优先级配置不当,轻则导致数据帧丢失,重则引发系统死锁(例如中断嵌套死循环)。因此,合理的优先级仲裁策略是嵌入式系统稳定性的基石。

二、STM32H7 中断优先级机制基础

2.1 NVIC 优先级分组

STM32H7 使用 NVIC(嵌套向量中断控制器),支持 16 级可编程优先级(0-15)。优先级由抢占优先级(Preemption Priority)和子优先级(Subpriority)组成,通过 HAL_NVIC_SetPriorityGrouping() 设置分组方式。常见分组为:

  • NVIC_PRIORITYGROUP_4:全部 4 位用于抢占优先级,无子优先级(0-15 级抢占)。
  • NVIC_PRIORITYGROUP_2:2 位抢占(0-3),2 位子优先级(0-3)。

2.2 抢占优先级与子优先级的作用

  • 抢占优先级:决定中断能否打断当前正在执行的中断。数值越小,优先级越高。
  • 子优先级:当两个中断的抢占优先级相同时,子优先级决定响应顺序,但不会打断。

2.3 FDCAN 与以太网中断特性

  • FDCAN:支持多个中断源(如 RX FIFO 消息、TX 完成、错误警告),中断频率高,数据实时性要求严格。
  • 以太网:DMA 传输完成、接收帧到达等中断,数据量大,但可容忍微秒级延迟。

三、并发场景下的冲突分析

假设 FDCAN 接收中断(优先级设为 5)和以太网 DMA 接收中断(优先级设为 3)同时触发。若以太网抢占优先级更高,则 FDCAN 中断会被延迟,可能导致 FDCAN FIFO 溢出。反之,若 FDCAN 频繁抢占,以太网 DMA 描述符可能因未及时处理而丢失数据。

四、优先级仲裁策略设计

4.1 分组选择:推荐 NVIC_PRIORITYGROUP_2

  • 理由:提供 4 级抢占优先级(0-3),足够区分关键外设,同时保留子优先级用于同组内排序。
  • 配置代码:
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);

4.2 优先级分配建议

| 外设中断 | 抢占优先级 | 子优先级 | 说明 | |---------|-----------|---------|------| | FDCAN1_RX0 | 0 | 0 | 最高,保证实时性 | | FDCAN1_TX | 0 | 1 | 同抢占,子优先级次之 | | 以太网 DMA RX | 1 | 0 | 次高,避免丢包 | | 以太网 DMA TX | 1 | 1 | 同组,子优先级低 | | 其他(如定时器) | 2 | 0 | 低优先级 |

4.3 关键点:避免优先级反转

  • 确保 FDCAN 中断处理函数尽量短,只做数据拷贝和标志设置,耗时操作放主循环。
  • 以太网中断中,使用 DMA 描述符链表,减少 CPU 干预。

五、完整代码示例(基于 STM32CubeH7)

5.1 初始化配置

void MX_Interrupt_Config(void)
{
    // 设置优先级分组:2位抢占,2位子优先级
    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);

    // FDCAN1 接收中断(FDCAN1_IT0)
    HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);

    // FDCAN1 发送中断
    HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 0, 1);
    HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);

    // 以太网 DMA 接收中断(ETH_IRQn)
    HAL_NVIC_SetPriority(ETH_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(ETH_IRQn);

    // 以太网 DMA 发送中断(ETH_WKUP_IRQn)
    HAL_NVIC_SetPriority(ETH_WKUP_IRQn, 1, 1);
    HAL_NVIC_EnableIRQ(ETH_WKUP_IRQn);
}

5.2 中断服务函数示例

// FDCAN 接收中断处理
void FDCAN1_IT0_IRQHandler(void)
{
    HAL_FDCAN_IRQHandler(&hfdcan1);
    // 快速处理:读取 FIFO 数据到缓冲区,设置标志
}

// 以太网中断处理
void ETH_IRQHandler(void)
{
    HAL_ETH_IRQHandler(&heth);
    // 处理接收帧,更新描述符
}

5.3 主循环中的协作处理

while (1)
{
    if (fdcan_rx_flag)
    {
        // 解析 FDCAN 数据(耗时操作)
        fdcan_rx_flag = 0;
    }
    if (eth_rx_flag)
    {
        // 处理以太网数据包
        eth_rx_flag = 0;
    }
}

六、调试与验证技巧

  • 使用逻辑分析仪:观察 FDCAN TX/RX 引脚和以太网 TX/RX 引脚,测量中断响应时间。
  • 启用中断嵌套测试:在 FDCAN 中断中设置断点,模拟以太网中断触发,检查是否发生嵌套。
  • 监控 FIFO 状态:通过 HAL_FDCAN_GetRxFifoFillLevel() 检查 FDCAN 是否溢出。
  • 使用 RTOS 时:注意中断优先级与 RTOS 内核优先级的关系,确保中断不阻塞调度器。

七、注意事项

  • 避免在中断中调用 HAL_Delay():会导致系统挂起。
  • FDCAN 时钟配置:确保 FDCAN 内核时钟(如 20MHz)正确,否则影响中断时序。
  • 以太网 DMA 描述符:必须对齐到 4 字节边界,否则可能触发总线错误。
  • 优先级分组不可动态更改:必须在系统初始化时设置,且所有外设中断需遵循同一分组。

八、总结

通过合理配置 NVIC 优先级分组和中断优先级,STM32H7 在 480MHz 下可以完美处理 FDCAN 与以太网的并发中断。核心原则是:实时性要求高的中断(如 FDCAN)分配更高抢占优先级,而数据量大的中断(如以太网)分配稍低优先级,并通过子优先级细化同组排序。配合精简的中断处理函数,可确保系统稳定高效运行。