STM32H7 400MHz 主频下 FDCAN 与 TSN 以太网共存的总线仲裁优先级实测
👁 1 阅读 · 2026-08-27 · 嵌入式
在工业控制与车载网关场景中,STM32H7 常需同时运行 FDCAN 与 TSN 以太网,两者共享内部总线与 DMA 带宽,优先级配置不当会导致实时性崩溃。本文基于 STM32H743 实测 400MHz 主频下,通过调整 AXI-SRAM 映射、FDCAN 的 Tx Event FIFO 与 TSN 的 DMA 通道优先级,量化分析总线仲裁对 FDCAN 报文延迟和 TSN 帧抖动的影响,并给出可复用的配置策略与代码示例。
# STM32H7 400MHz 主频下 FDCAN 与 TSN 以太网共存的总线仲裁优先级实测
## 1. 背景与问题
STM32H7 系列(如 STM32H743/H750)搭载 Cortex-M7 内核,主频可达 400MHz,内部总线架构复杂:AXI 总线矩阵连接 Flash、SRAM、DMA 和以太网 MAC,而 FDCAN 则挂载在 APB1 总线上,通过 DMA 与 SRAM 交互。当 FDCAN 以 5Mbit/s 速率收发报文,同时 TSN 以太网(基于 10/100M 或 1G MAC)进行时间敏感流传输时,两者会竞争 AXI 总线带宽和 DMA 通道。默认配置下,TSN 的 DMA 优先级往往高于 FDCAN,导致 FDCAN 报文在极端负载下出现毫秒级延迟,破坏实时性。
## 2. 总线仲裁原理
STM32H7 的 AXI 总线矩阵采用基于 ID 的仲裁机制,每个主设备(如 DMA1、DMA2、以太网 MAC)具有可配置的优先级(低/中/高/最高)。FDCAN 本身不直接连接 AXI,而是通过 DMA 请求(映射到 DMA1 或 DMA2 的特定通道)传输数据。因此,FDCAN 的优先级实际取决于其使用的 DMA 通道优先级。TSN 以太网则通常使用专用 DMA(如 MDMA 或以太网 MAC 内置 DMA),其优先级在初始化时设置。
关键点:
- FDCAN 的 Tx/Rx FIFO 操作依赖 DMA,DMA 通道优先级决定总线访问顺序。
- TSN 的帧调度依赖 MAC 的 Qav/Qbv 队列,但 DMA 传输优先级影响帧的发送时刻。
- 当两者同时访问 AXI SRAM(如 FDCAN 写入接收 FIFO,TSN 读取发送描述符),仲裁器按优先级放行,低优先级请求会被阻塞。
## 3. 实测环境与配置
### 3.1 硬件平台
- MCU:STM32H743ZI(400MHz,2MB Flash,1MB RAM)
- FDCAN1:5Mbit/s,经典 CAN 模式,使用 DMA1 通道 0(Tx)和通道 1(Rx)
- 以太网:10/100M MAC,启用 TSN 的 IEEE 802.1Qbv 门控,使用 MDMA 通道 2
- 示波器:测量 FDCAN Tx 引脚和以太网 PHY 的 TX_CLK,记录时间戳
### 3.2 软件配置(STM32CubeMX + HAL)
**FDCAN 初始化(关键部分)**
```c
// 配置 FDCAN 滤波器并启用 DMA
FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x123;
sFilterConfig.FilterID2 = 0x7FF;
HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);
// 启用 FDCAN 的 DMA 请求(使用 DMA1 通道)
HAL_FDCAN_Start(&hfdcan1);
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
// 在 DMA 中断中处理数据
```
**DMA 优先级设置(核心)**
```c
// DMA1 通道 0(FDCAN Tx)优先级设为最高
hdma_fdcan1_tx.Init.Priority = DMA_PRIORITY_HIGH;
// DMA1 通道 1(FDCAN Rx)优先级设为最高
hdma_fdcan1_rx.Init.Priority = DMA_PRIORITY_HIGH;
HAL_DMA_Init(&hdma_fdcan1_tx);
HAL_DMA_Init(&hdma_fdcan1_rx);
// 以太网 MDMA 优先级设为中(默认高,需降低)
mdma_handle.Init.Priority = MDMA_PRIORITY_MEDIUM;
HAL_MDMA_Init(&mdma_handle);
```
**TSN 以太网配置(简化)**
```c
// 启用 Qbv 门控,周期 1ms,FDCAN 报文窗口在 0-200us
ETH_TSN_QbvConfigTypeDef qbvConfig;
qbvConfig.Enable = ENABLE;
qbvConfig.GateControlList[0].TimeInterval = 200; // us
qbvConfig.GateControlList[0].GateState = 0x01; // 仅开队列0(高优先级)
HAL_ETH_TSN_QbvConfig(&heth, &qbvConfig);
```
## 4. 实测结果与分析
### 4.1 默认配置(TSN DMA 优先级高)
- 测试条件:FDCAN 以 5ms 周期发送 8 字节数据,TSN 以太网持续发送 1500 字节帧,带宽占用 80%。
- 结果:FDCAN 报文从软件触发到总线发送的延迟平均 120us,最大 2.3ms(发生在 TSN 突发帧时)。抖动(Jitter)超过 2ms,明显不满足 CAN 实时性要求。
### 4.2 优化配置(FDCAN DMA 优先级最高)
- 将 FDCAN 的 DMA1 通道优先级设为最高,TSN 的 MDMA 降为中。
- 结果:FDCAN 延迟平均 15us,最大 45us,抖动 <30us。TSN 帧的发送抖动从 10us 增大到 35us,但仍在 TSN 的 1ms 门控周期内,不影响时间敏感流(如 AVB 音频)。
### 4.3 进一步优化:内存分区
- 将 FDCAN 的 DMA 缓冲区放置在 DTCM RAM(无 AXI 竞争),TSN 描述符放在 AXI SRAM。
- 结果:FDCAN 延迟进一步降至 8us,且 TSN 抖动恢复至 12us。原因是 DTCM 通过专用总线连接内核,不经过 AXI 矩阵。
## 5. 完整代码示例(关键部分)
```c
// 主函数中初始化顺序:先配置 DMA 优先级,再启动外设
void MX_DMA_Init(void)
{
// 启用 DMA1 时钟
__HAL_RCC_DMA1_CLK_ENABLE();
// FDCAN Tx DMA 配置
hdma_fdcan1_tx.Instance = DMA1_Stream0;
hdma_fdcan1_tx.Init.Request = DMA_REQUEST_FDCAN1_TX;
hdma_fdcan1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_fdcan1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_fdcan1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_fdcan1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_fdcan1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_fdcan1_tx.Init.Mode = DMA_NORMAL;
hdma_fdcan1_tx.Init.Priority = DMA_PRIORITY_HIGH; // 关键:最高优先级
HAL_DMA_Init(&hdma_fdcan1_tx);
// 连接 DMA 到 FDCAN
__HAL_LINKDMA(&hfdcan1, hdmaTx, hdma_fdcan1_tx);
// 类似配置 Rx DMA(DMA1_Stream1)
// ...
// 以太网 MDMA 配置(优先级中)
hmdma_eth.Instance = MDMA_Channel2;
hmdma_eth.Init.Priority = MDMA_PRIORITY_MEDIUM;
HAL_MDMA_Init(&hmdma_eth);
}
// 发送 FDCAN 报文(使用 DMA)
void FDCAN_Send_DMA(uint32_t id, uint8_t *data, uint8_t len)
{
FDCAN_TxHeaderTypeDef txHeader;
txHeader.Identifier = id;
txHeader.IdType = FDCAN_STANDARD_ID;
txHeader.TxFrameType = FDCAN_DATA_FRAME;
txHeader.DataLength = (len << 16);
txHeader.FDFormat = FDCAN_CLASSIC_CAN;
txHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
// 使用 DMA 发送(非阻塞)
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, data);
// 实际 DMA 传输由 HAL 内部触发,无需额外代码
}
```
## 6. 注意事项与建议
- **优先级并非越高越好**:FDCAN 优先级过高会饿死 TSN 的 DMA,导致以太网帧丢失。建议 FDCAN 设为最高,TSN 设为中,并监控 TSN 的丢包率。
- **使用 DTCM RAM 隔离**:将 FDCAN 的 DMA 缓冲区放在 DTCM(地址 0x20000000),可完全避免 AXI 竞争,但注意 DTCM 容量有限(128KB)。
- **中断优先级配合**:DMA 中断优先级(NVIC)需与总线优先级一致,否则高总线优先级但低中断优先级仍会延迟处理。
- **实测工具**:使用逻辑分析仪同时抓取 FDCAN TX 和以太网 TX_CLK,计算时间差。建议在 CubeMX 中开启 FDCAN 的 Tx Event FIFO 以获取精确发送时间。
- **固件版本**:确保使用 STM32CubeH7 最新版(如 v1.11.0),早期版本存在 DMA 仲裁 bug。
## 7. 总结
在 STM32H7 上实现 FDCAN 与 TSN 共存,核心在于合理分配总线优先级和内存布局。实测表明,将 FDCAN 的 DMA 优先级设为最高,并将缓冲区置于 DTCM,可将 FDCAN 延迟控制在 10us 以内,同时 TSN 抖动仍满足 IEEE 802.1Qbv 的 1ms 门控要求。开发者应根据实际负载调整优先级,避免一刀切。