This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具/软件:Linux
我正在使用运行 Linux 内核4.9.69的 am3358。 我们的板上有一些北欧无线电、作为 SPI 从属设备连接到 am3358。 我们以8MHz 的频率运行 SPI 总线。 我们所有的 SPI 事务都非常小:小于或等于64字节、但它们有很多。
虽然我们看到 CPU 使用率相当高、但在不涉及 DMA 的情况下、一切都能完美运行。 该系统完美运行了一周以上。
最近、我开始研究使用 DMA 处理 SPI 事务以尝试降低 CPU 负载。 驱动程序 SPI-OMAP2-mcspi.c 使用以下命令来决定是否使用 DMA:
#define DMA_MIN_Bytes 160
我将此值更改为0、以便 DMA 用于每个事务、这样做可以显著减少 CPU 使用量。 但是、SPI 不再完美工作。 我看到 SPI 事务在大约1/2小时到1小时后停止。 如果我将 DMA_MIN_Bytes 设置为32或64、我还会看到这种情况。
您有什么想法吗? 您是否知道在较小的事务上启用 DMA 会导致 SPI 停止工作的任何原因? 似乎没有任何错误传播到我们使用 SPI 子系统的驱动程序。 在 SPI.c 和 SPI-OMAP2-mcspi.c 中启用调试时、我没有看到任何错误
谢谢!
看起来我被困在等待_等待_完成的调用中...
作为一个实验、我将 SPI-OMAP2-mcspi 中的 WAIT_TO_ENDINUTE()调用转换为 WAIT_TO_ENDUSE_TIMEOUT ()、并在 OMAP2_mcspi_Rx_DMA ()中单击超时
此外、当我进入错误状态后移除模块时、我会看到以下内容:
[58123.213768] OMAP-hwmod:SPI1:_WAIT_TARGET_DISABLE 失败
[58128.850390] SPI_MASTER SPI2:无法停止消息队列
[58128.855883] SPI_MASTER SPI2:销毁队列时出现问题
[58128.869961] SPI_MASTER SPI2:删除队列失败
当我遇到错误条件时、我转储了外设寄存器:
[515.038618] JZ OMAP2_mcspi_Rx_DMA ()超时
[515.043069] OMAP2_MCSPI_REVISION = 0x0000002b
[515.047805] OMAP2_MCSPI_SYSSTATUS = 0x00000001
[515.057359] OMAP2_MCSPI_IRQSTATUS = 0x00000001
[515.063953] OMAP2_MCSPI_IRQENABLE = 0x00000000
[515.070601] OMAP2_MCSPI_WAKEUPENABLE = 0x00000001
[515.075353] OMAP2_MCSPI_SYST = 0x00000000
[515.083063] OMAP2_MCSPI_MODULCTRL = 0x00000001
[515.087815] OMAP2_MCSPI_XFERLEVEL = 0x00401f1f
[515.095545] OMAP2_MCSPI_CHCONF0 = 0x3811c3d4
[515.102957] OMAP2_MCSPI_CHSTAT0 = 0x0000002E
[515.107711] OMAP2_MCSPI_CHCCTRL0 = 0x00000001
[515.115953] OMAP2_MCSPI_TX0 = 0x00000000
[515.123027] OMAP2_MCSPI_RX0 = 0x00000000
[540.640711] JZ OMAP2_mcspi_Rx_DMA ()超时
[540.645390] OMAP2_MCSPI_REVISION = 0x0000002b
[540.650129] OMAP2_MCSPI_SYSSTATUS = 0x00000001
[540.660151] OMAP2_MCSPI_IRQSTATUS = 0x00000001
[540.666923] OMAP2_MCSPI_IRQENABLE = 0x00000000
[540.674266] OMAP2_MCSPI_WAKEUPENABLE = 0x00000001
[540.679022] OMAP2_MCSPI_SYST = 0x00000000
[540.686883] OMAP2_MCSPI_MODULCTRL = 0x00000001
[540.694689] OMAP2_MCSPI_XFERLEVEL = 0x00401f1f
[540.699448] OMAP2_MCSPI_CHCONF0 = 0x3811c3d4
[540.707502] OMAP2_MCSPI_CHSTAT0 = 0x0000002E
[540.714205] OMAP2_MCSPI_CHCCTRL0 = 0x00000001
[540.718959] OMAP2_MCSPI_TX0 = 0x00000000
[540.727341] OMAP2_MCSPI_RX0 = 0x00000000
如果发送/接收64字节的数据而不是200字节、会怎么样? 它可能与我要发送的小数据包有关? 我可以尝试将数据包大小调整为200、看看问题是否消失。
我用200字节的数据包运行了一个周末。 此问题必须与使用带有较小数据包的 DMA 有关。 请告诉我您是否能够使用64字节的数据包进行复制。
当故障发生时、我获得了一个 salae 逻辑分析仪捕获。 附件。
在 OMAP2_mcspi_Rx_DMA 中的 WAIT_for_Complete_TIMEOUT 之后、DEBUG_1错误会变为高电平。 超时设置为140个 jiffies。
DEBUG_0 xfer 在 OMAP2_mcspi_transferone 的开头变为高电平、在结尾变为低电平
DRDY8由从器件驱动、并在从器件接收到 SPI 数据后变为高电平。 当从器件准备好让主器件发送另一个事务时、它会变为低电平
其余信号为标准 SPI 信号 MISO、MOSI、时钟、芯片选择。
如果您从 DEBUG_1错误变为高电平的位置后退约1.4秒、则会发生最后一次成功的 SPI 事务、然后启动失败的事务。 Debug_0 xfer 变为高电平、但其他行都不会切换。
最后一次成功的事务的唯一奇怪之处在于、SPI 时钟33字节中有一个短暂的断续进入事务、这似乎有点奇怪、因为正在使用 DMA。
事实证明、我可以使用 spidev 重现问题。 以前我使用的是12字节的数据包、无法重现。 但是、现在我使用的是64字节的数据包、我可以复制它。
在第33个字节后有一个短暂的暂停(在下面的屏幕截图中为61.96 μ s)、但随后 SPI 传输将恢复并完成。 但之后的下一个传输不起作用。
我还将连接 Salaea 逻辑分析仪迹线。
e2e.ti.com/.../spidev-_2D00_-repro.logicdata.zip
当 WAIT_for 完成超时时、DEBUG_1 ERR 变为高电平。
Debug_0 xfer 在 TRANSFER_ONE 入口有一个双脉冲、在 TRANSFER_ONE 出口有一个单脉冲
我在周末使用自定义 SPI 驱动程序和32字节数据包进行了尝试、但无法重现问题。
我可以使用 spidev 和我们的自定义驱动程序重新生成64字节的数据包。 我将尝试不同的 SPI 传输大小、看看会发生什么情况...
您是否还能重现?
我能够使用64字节的数据包重新生成它。 我将开始深入探讨这一点。
Steve K.
感谢您的关注!
我曾尝试尝试过 FIFO 深度和 XFERLEVEL AFL/AEL 设置、以查看我是否可以使数据正常工作、但无法找到任何有效的设置。
我在 OMAP2_mcspi_TX_callback 中添加了一个 GPIO 脉冲、它看起来就像完成在传输的第33个字节附近。 不确定是否与问题相关、但似乎可疑...
这是一个补丁、我的 SPI 测试与它一起运行了一整晚。 不确定是否有更好的解决方法、您能看一下并告诉我吗?
下面是我提出的一组补丁:
1、将 WAIT_TO_Completion 更改为 WAIT_TO_ENULOCING_TIMEOUT
2.通过同时启动 TX/Rx DMA 来修复竞态条件
3、DMA 最小长度的器件树绑定
4.设备树绑定以完成超时
尊敬的 James:
请允许我设置测试条件、重新生成、然后我将跟进反馈。
Marcus
这可能会帮助您复制它。 我已附加一个在循环中运行的修改 spidev_test 程序。 我可以通过这种方式复制它。 您可以按如下方式调用它:
sudo ./spidev_loop -D /dev/spidev2.0 -s 80000 -p "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"