在 i.MXRT1176 上,我们使用 FLEXCAN 和 EDMA。(SDK 26.03)
我们定义了 DMA 传输完成的回调函数。
这是我们的流程:
1.调用 ` FLEXCAN_TransferReceiveFifoEDMA()` 开始传输。
2. DMA 传输完成后,调用用户定义的回调函数。
3. 从 DMA 缓冲区复制数据,并调用 `FLEXCAN_TransferReceiveFifoEDMA()` 继续接收消息。
4. 重复步骤 2-4
我们注意到,当我们从另一个节点以突发方式发送消息,且帧间间隔仅为最小值时,ACK 错误的数量会增加——iMX 无法确认消息。
从流程来看,每次 DMA 传输完成回调时,FLEXCAN 上的 DMA 都会被禁用。当调用 `FLEXCAN_TransferReceiveFifoEDMA()` 时,DMA 功能会重新启用。这可以通过调用 ` FLEXCAN_EnableRxFifoDMA()` 来实现。启用/禁用 DMA 会更新 FLEXCAN 的 MCR 寄存器中的 DMA 位,并且只能在冻结模式下进行。由于我们以突发方式接收消息,因此当 FLEXCAN 进入冻结模式时,可能正在进行传输,导致它无法确认接收到的消息。
嗨@r-uv ,
感谢您提供的详细分析。您的观察结果与SDK的实现一致。
FLEXCAN_TransferReceiveFifoEDMA() 是一个有限长度的事务 API。每次 DMA 操作完成后,驱动程序会禁用 Rx FIFO DMA 请求,下一次调用时会再次启用该请求。由于更改 MCR[DMA] 需要冻结模式,最小 IFS 流量中的下一帧可能在 FlexCAN 恢复正常模式之前到达,从而导致 ACK 丢失。
这也解释了为什么移除重复的 DMA 启用/禁用操作可以消除 ACK 错误,但仍然会导致丢帧:与冻结相关的 ACK 间隙被消除,但 eDMA 传输没有持续重新开始。
对于连续突发流量,我们建议保持 Rx FIFO DMA 请求启用,并使用硬件链式乒乓/分散聚集 TCD,以便自动激活下一个缓冲区。这需要连续的 DMA 接收路径,而不是反复重新启动 FLEXCAN_TransferReceiveFifoEDMA()。
此致,
加文
谢谢你的回复。SDK 是否有计划添加此功能的支持?是采用基于连续DMA的实现方式,还是仅仅采用当前的事务性API实现方式?