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/AM3358:SPI DMA 问题

Guru**** 1956055 points
Other Parts Discussed in Thread: AM3358
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/709789/linux-am3358-spi-dma-issue

器件型号:AM3358

工具/软件: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 中启用调试时、我没有看到任何错误

谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是否可以添加调试以查看是否滞留在 WAIT_for_Completion 调用中?

    Steve K.
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    看起来我被困在等待_等待_完成的调用中...

    作为一个实验、我将 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

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢。 我将对此进行分析。

    我编写了一个小型测试程序、该程序使用 spidev 发送和接收数据。 我使用的是 BeagleBone Black、并在 spi0_d0和 spi0_D1之间有一根跳线。 我修改了 mcspi 驱动程序、使 DMA 阈值为32字节、并且在程序中、我将发送和接收200字节的数据。 4小时后仍然没有错误。

    Steve K.
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    如果发送/接收64字节的数据而不是200字节、会怎么样?  它可能与我要发送的小数据包有关?  我可以尝试将数据包大小调整为200、看看问题是否消失。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我用200字节的数据包运行了一个周末。  此问题必须与使用带有较小数据包的 DMA 有关。  请告诉我您是否能够使用64字节的数据包进行复制。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我无法使用包含64字节数据包的 spidev 和 spidev_test (修改后、使其在循环中运行)进行重新配置。 我的最佳猜测是它不会重新调整、因为计时不同于我们的自定义驱动程序...

    我们在 SPI 上有一个自定义驱动程序:它在前一个驱动程序完成后立即提交 SPI 传输。

    我已检测代码、因此我应该能够判断在一个仍在进行的传输过程中是否尝试了新的传输。 到目前为止、我找不到任何问题。

    问题似乎在于 DMA 传输已开始、但完成过程从未完成。 您是否有任何其他想法可以导致这种情况的发生? 或在 SPI/DMA 的存储器映射寄存器中查找什么?

    谢谢!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我将详细介绍导致完成的原因。 您能否在遇到错误之前转储寄存器? 我想对它们进行比较。

    Steve K.
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在 OMAP2_mcspi_Rx_DMA 中调用 WAIT_for_Completion 之前、这是典型 SPI 事务的寄存器转储。 如果您在查找错误发生之前的寄存器转储,我将看到我是否可以使其发生,或者让您知道它是否会影响重现错误的能力...

    [266.365716]在以下情况之前:
    [266.367941] OMAP2_MCSPI_REVISION = 0x0000002b
    [266.379863] OMAP2_MCSPI_SYSSTATUS = 0x00000001
    [266.387904] OMAP2_MCSPI_IRQSTATUS = 0x00020001
    [266.394725] OMAP2_MCSPI_IRQENABLE = 0x00000000
    [266.399477] OMAP2_MCSPI_WAKEUPENABLE = 0x00000001
    [266.407469] OMAP2_MCSPI_SYST = 0x00000000
    [266.414152] OMAP2_MCSPI_MODULCTRL = 0x00000001
    [266.418905] OMAP2_MCSPI_XFERLEVEL = 0x00001f1f
    [266.426557] OMAP2_MCSPI_CHCONF0 = 0x381103d4
    [266.433036] OMAP2_MCSPI_CHSTAT0 = 0x0000002E
    [266.437789] OMAP2_MCSPI_CHCCTRL0 = 0x00000001
    [266.445536] OMAP2_MCSPI_TX0 = 0x00000000
    [266.450286] OMAP2_MCSPI_RX0 = 0x00000000
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在尝试修改 OMAP2_mcspi_Rx_DMA ()中的任何寄存器之前、我会检查 OMAP2_MCSPI_CHSTAT_EOT (传输状态结束)是否被清除。 当我使用 spidev 时、我看不到任何问题:EOT 始终被清除。 但是、对于我们的自定义驱动程序、我看到 EOT 偶尔会被设置。 这似乎不正确、但我不确定为什么还在发生。 我进行了一些其他检查、以查看是否曾在上一个传输完成之前尝试过新的传输、并且迄今为止我没有遇到任何该调试代码。 有什么想法会导致这种情况?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    当故障发生时、我获得了一个 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 传输大小、看看会发生什么情况...

    您是否还能重现?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我认为、当传输大小是32字节的倍数时、它与使用 FIFO 有关。 我添加了一些代码来绕过启用 FIFO:我在 OMAP2_mcspi_set_fifo 中添加了一个无条件转至 disable_fifo、并且不再看到该问题。 理想情况下、我认为我们希望使用 FIFO、因为我们希望尽可能减少 CPU 使用率。

    您是否能够复制它? 我提到我能够使用 spidev 复制、因此我想您现在应该能够复制。 我是否可以向您提供任何其他信息? 到目前为止、这个问题在这里并没有占据很大的优先级、但由于日程安排的原因、它开始成为一个问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 James:
    今天稍后我将尝试使用 spidev 复制它。

    Steve K.
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我能够使用64字节的数据包重新生成它。 我将开始深入探讨这一点。

    Steve K.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的关注!

    我曾尝试尝试过 FIFO 深度和 XFERLEVEL AFL/AEL 设置、以查看我是否可以使数据正常工作、但无法找到任何有效的设置。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我在 OMAP2_mcspi_TX_callback 中添加了一个 GPIO 脉冲、它看起来就像完成在传输的第33个字节附近。  不确定是否与问题相关、但似乎可疑...

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我想我找到了一个解决方法。 诀窍是首先设置 TX DMA 传输而不设置 CHCONF_DM5W、然后设置 Rx DMA 传输、当两者都设置好时、同时设置 DMASW/DMAR。 我将让这种情况持续一夜以再次确认情况是否正常、然后我将向您发送一个补丁。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是一个补丁、我的 SPI 测试与它一起运行了一整晚。   不确定是否有更好的解决方法、您能看一下并告诉我吗?

    e2e.ti.com/.../start_2D00_dma_2D00_simultaneously.patch.zip

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    下面是我提出的一组补丁:

    1、将 WAIT_TO_Completion 更改为 WAIT_TO_ENULOCING_TIMEOUT

    2.通过同时启动 TX/Rx DMA 来修复竞态条件

    3、DMA 最小长度的器件树绑定

    4.设备树绑定以完成超时

    e2e.ti.com/.../dma_2D00_patches.tar.gz

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 James:

    请允许我设置测试条件、重新生成、然后我将跟进反馈。

    Marcus

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这可能会帮助您复制它。  我已附加一个在循环中运行的修改 spidev_test 程序。  我可以通过这种方式复制它。  您可以按如下方式调用它:

    sudo ./spidev_loop -D /dev/spidev2.0 -s 80000 -p "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"

    e2e.ti.com/.../spidev_5F00_loop.c.zip

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    好的、我可以使用您提供的最新测试应用重现此问题。 请允许我了解与您提供的解决方法相关的根本原因。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    变通办法似乎是对 TI 驱动程序进行永久更新的好选择。
    我将向我们的软件开发团队提交您的补丁。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我向 TI 软件团队报告了该问题、它们是导致该问题的根本原因。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢!
x 出现错误。请重试或与管理员联系。