您好,
我在 i.MX8MM 上的 ECSPI 驱动程序 (fsl_ecspi.c) 中发现了一个潜在问题,特别是在 ECSPI_SendTransfer() 中。
以下代码将计算可用的 FIFO 空间:
dataCounts =
((uint32_t)FSL_FEATURE_ECSPI_TX_FIFO_SIZEn(base) - (uint32_t)ECSPI_GetTxFifoCount(base))< txRemainingBytes ?
((uint32_t)FSL_FEATURE_ECSPI_TX_FIFO_SIZEn(base) - (uint32_t)ECSPI_GetTxFifoCount(base)) :
txRemainingBytes;
但是,ECSPI_GetTxFifoCount(base) 读取的是一个硬件寄存器,而且 FIFO 级别是动态更新的。
由于在同一个表达式中会多次调用该函数,因此在不同的评估中返回的值可能会不同。
因此,在某些定时条件下,计算出的可用 FIFO 空间可能会变得不一致,
和 dataCounts 可能会超出预期值。
这可能会导致不正确的传输行为,在我的情况下,ECSPI 中断不会停止(中断持续触发)。
我认为根本原因是 FIFO 计数寄存器被多次读取,
,而驱动程序认为该值在表达式中保持一致。
建议的解决方案:
- 只读取一次 FIFO 计数寄存器
- 将其存储在本地变量中
- 在后续计算中使用缓存值
修复示例:
uint32_t fifoAvailableCount = ((uint32_t)FSL_FEATURE_ECSPI_TX_FIFO_SIZEn(base) - (uint32_t)ECSPI_GetTxFifoCount(base));
dataCounts = (fifoAvailableCount< txRemainingBytes) ?fifoAvailableCount : txRemainingBytes;
您能确认这是已知问题还是意外行为吗?
您好,@pengyong_zhang
感谢您的回复。
我没有使用 Linux。
我正在 i.MX8MM 的 A53 内核上运行裸机/RTOS 环境。
我使用的 ECSPI 驱动程序基于 MCUXpresso SDK 驱动程序。
例如,实施情况如下:
https://github.com/nxp-mcuxpresso/mcuxsdk-core/blob/main/drivers/ecspi/fsl_ecspi.c#L180
在该实现中,FIFO 状态在中断处理程序中被多次读取。
由于 FIFO 计数在两次读取之间会发生变化,我认为这可能会在极少数情况下导致 dataCounts 超过 txRemainingBytes。
您能否确认这种行为是否在预料之中,或者这是否是 ECSPI 驱动程序中的一个已知问题?
顺祝商祺!
我们的 imx8mm ECSPI 驱动程序代码文件如下:
您使用的是哪个版本的内核?
B.R
我也遇到了这个问题,并且已经提交了一个 PR 来修复它: https://github.com/nxp-mcuxpresso/mcuxsdk-core/pull/33
另外需要注意的是,即使经过此修复,如果在 IRQ 期间有字节从 TXFIFO 发送出去,而 RXFIFO 正在被清空,则代码会触发信号 RXFIFO 溢出。例如,如果在调用 ECSPI_GetRxFifoCount 时,RXFIFO 中有 60 个字节,TXFIFO 中有 4 个字节,那么到调用 ECSPI_GetTxFifoCount 时,这 4 个字节已被发送,则 TXFIFO 将被填满(在 i.MX8MP 的情况下最多可达 64 个字节)。如果 ISR 没有足够快地再次得到服务,这将导致溢出,因为在读取任何项目之前,就会传输 64 + 4 个项目。可以通过在补丁中使用handle->rxRemainingBytes - handle->txRemainingBytes而不是fifoCounts字节来解决这个问题,但这只有在 ISR 无法足够快地清空 RXFIFO 时才有必要(我的情况就是这样,但可能并非处处如此,而且这可能会导致事务处理速度变慢/中断次数增多,所以我选择不在 PR 中包含此更改)。