# STM32H7 600MHz 下 FDCAN 与以太网并发传输的 DMA 仲裁优先级陷阱与规避 ## 一、问题背景 STM32H7 系列采用双核或单核 Cortex-M7,主频高达 600MHz,内部总线架构为 AXI 总线矩阵(AXI-M7)与 AHB/APB 桥接。FDCAN 和以太网 MAC(Ethernet)均通过 DMA 控制器访问内存,但它们的 DMA 请求路径不同:FDCAN 使用 DMA1/DMA2(挂载于 AHB1),以太网使用独立的 DMA(挂载于 AXI 总线)。当两者并发传输时,AXI 总线矩阵的仲裁策略可能产生优先级反转,导致 FDCAN 帧丢失或以太网帧超时。 ## 二、DMA 仲裁机制原理 ### 2.1 AXI 总线矩阵仲裁 STM32H7 的 AXI 总线矩阵采用基于 ID 的仲裁算法,每个主设备(如 Cortex-M7、DMA1、DMA2、Ethernet DMA)拥有固定的 ID 和优先级。默认情况下,仲裁优先级由硬件固定,但可通过 `AXI_CR` 寄存器调整。关键点: - **DMA1/DMA2** 的优先级低于 Ethernet DMA(因为 Ethernet DMA 直接连接 AXI 总线,而 DMA1/2 通过 AHB 桥接)。 - 当 Ethernet DMA 持续占用总线(如大包传输),FDCAN 的 DMA 请求会被阻塞,造成 FIFO 溢出。 ### 2.2 FDCAN 的 DMA 请求特性 FDCAN 使用 DMA 进行消息收发,每个消息帧需要多次 DMA 传输(如从 SRAM 读取消息 RAM)。若 DMA 请求延迟超过 FDCAN 的硬件超时(如 1ms),则触发错误中断。在 600MHz 下,总线时钟快,但仲裁延迟可能成为瓶颈。 ## 三、陷阱场景复现 假设系统配置: - FDCAN1 波特率 5Mbps,每个消息 64 字节数据,发送频率 10kHz。 - Ethernet 使用 DMA 环形缓冲区,接收 1500 字节帧,中断频率 1kHz。 默认配置下,运行 10 分钟后,FDCAN 出现 `FDCAN_IRQ` 错误(如 `DATA LOST`),而 Ethernet 正常。通过逻辑分析仪发现,FDCAN 的 DMA 请求在 Ethernet 突发传输期间被延迟约 200μs,超过 FDCAN 的容忍阈值。 ## 四、规避方案 ### 4.1 调整 AXI 总线优先级 通过修改 `AXI_CR` 寄存器,提高 DMA1/DMA2 的优先级。但需注意,过高优先级可能影响 Cortex-M7 的实时性。推荐设置: ```c // 设置 DMA1 和 DMA2 为高优先级(高于 Ethernet DMA) AXI->CR &= ~(AXI_CR_DMA1_PRI_MASK | AXI_CR_DMA2_PRI_MASK); AXI->CR |= (0x3 << AXI_CR_DMA1_PRI_Pos) | (0x3 << AXI_CR_DMA2_PRI_Pos); // 优先级 3(最高) ``` 但此方法可能影响其他 AXI 主设备,需评估。 ### 4.2 使用 FDCAN 的 RAM 直接访问(DMA 旁路) FDCAN 支持通过 AHB 直接访问消息 RAM(如使用 `FDCAN_WriteToRAM` 函数),绕过 DMA。但会占用 CPU 时间,不适合高负载。 ### 4.3 优化 DMA 传输粒度 将 FDCAN 的 DMA 传输配置为单次突发(Burst=1),减少总线占用时间,降低冲突概率。在 CubeMX 中设置: ```c hdma_fdcan1.Init.Burst = DMA_BURST_SINGLE; hdma_fdcan1.Init.TransferMode = DMA_NORMAL; ``` ### 4.4 使用中断而非 DMA(低负载场景) 若 FDCAN 流量不大(<1Mbps),可改用中断方式,避免 DMA 仲裁问题。但注意中断延迟。 ### 4.5 综合方案(推荐) 结合优先级调整与突发限制,并启用 FDCAN 的自动重传功能: ```c // 1. 调整 AXI 优先级(仅提升 DMA1,用于 FDCAN) AXI->CR = (AXI->CR & ~AXI_CR_DMA1_PRI_MASK) | (0x2 << AXI_CR_DMA1_PRI_Pos); // 2. 配置 FDCAN 自动重传(避免瞬时丢失) FDCAN_InitTypeDef init = {0}; init.AutoRetransmission = ENABLE; HAL_FDCAN_Init(&hfdcan1, &init); // 3. 以太网 DMA 设置循环模式,并降低中断频率(使用 coalescing) HAL_ETH_ConfigRxCoalesce(&heth, ETH_RX_COALESCE_TIMER_100US); ``` ## 五、完整代码示例 以下为基于 STM32H743 的初始化代码片段(使用 HAL 库): ```c // 全局变量 FDCAN_HandleTypeDef hfdcan1; ETH_HandleTypeDef heth; void SystemClock_Config(void); static void MX_FDCAN1_Init(void) { hfdcan1.Instance = FDCAN1; hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1; hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; hfdcan1.Init.Mode = FDCAN_MODE_NORMAL; hfdcan1.Init.AutoRetransmission = ENABLE; hfdcan1.Init.TransmitPause = DISABLE; hfdcan1.Init.ProtocolException = DISABLE; hfdcan1.Init.NominalPrescaler = 10; hfdcan1.Init.NominalSyncJumpWidth = 1; hfdcan1.Init.NominalTimeSeg1 = 13; hfdcan1.Init.NominalTimeSeg2 = 2; hfdcan1.Init.DataPrescaler = 5; hfdcan1.Init.DataSyncJumpWidth = 1; hfdcan1.Init.DataTimeSeg1 = 13; hfdcan1.Init.DataTimeSeg2 = 2; hfdcan1.Init.StdFiltersNbr = 1; hfdcan1.Init.ExtFiltersNbr = 0; hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK) { Error_Handler(); } // 配置 DMA 为单次突发 hdma_fdcan1.Init.Burst = DMA_BURST_SINGLE; hdma_fdcan1.Init.TransferMode = DMA_NORMAL; HAL_DMA_Init(&hdma_fdcan1); } static void MX_ETH_Init(void) { heth.Instance = ETH; heth.Init.MACAddr[0] = 0x00; // ... 其他 MAC 配置 heth.Init.RxMode = ETH_RX_INTERRUPT_MODE; heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; if (HAL_ETH_Init(&heth) != HAL_OK) { Error_Handler(); } // 启用接收合并(coalescing) HAL_ETH_ConfigRxCoalesce(&heth, ETH_RX_COALESCE_TIMER_100US); } void main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_FDCAN1_Init(); MX_ETH_Init(); // 调整 AXI 优先级:提升 DMA1(FDCAN 使用) AXI->CR = (AXI->CR & ~AXI_CR_DMA1_PRI_MASK) | (0x2 << AXI_CR_DMA1_PRI_Pos); // 启动 FDCAN HAL_FDCAN_Start(&hfdcan1); HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); // 启动以太网 HAL_ETH_Start(&heth); while (1) { // 主循环 } } ``` ## 六、注意事项 - **优先级调整的副作用**:提高 DMA1 优先级可能增加 Cortex-M7 访问 AXI 总线的延迟,影响实时任务。建议在系统初始化时设置,并通过压力测试验证。 - **FDCAN 自动重传**:启用后,若发送失败会自动重传,但会增加总线负载,需确保波特率余量。 - **以太网合并中断**:降低中断频率可减少 CPU 负载,但会增加延迟,适合非实时应用。 - **调试建议**:使用逻辑分析仪监测 DMA 请求信号(如 `DMA_REQ`)和总线占用,确认冲突点。 - **不同型号差异**:H7 系列中,H743 与 H750 的 AXI 优先级寄存器可能略有不同,请参考对应参考手册。 ## 七、总结 STM32H7 的 DMA 仲裁优先级陷阱是并发传输中的隐性杀手。通过理解 AXI 总线矩阵的仲裁机制,合理调整优先级、优化 DMA 突发模式,并利用 FDCAN 的自动重传和以太网的合并中断,可以有效规避数据丢失和超时问题。建议在实际项目中结合具体流量模型进行调优,并充分测试。