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.

[参考译文] AM4378:启用 DMA 后 SPI 驱动器停止

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1181131/am4378-spi-driver-stalls-with-dma-enabled

器件型号:AM4378
主题中讨论的其他器件:TMDSEVM437X

您好!

我在 TMDSEVM437X 评估板上使用 SPI1接口。

在单个块中发送的字节少于160个时、它都按预期工作。  在这种情况下、驱动程序使用 PIO 模式。

对于160字节或更多字节、驱动程序使用 DMA 模式、至少这是目的。  然而、CS0变为低电平、SCLK 保持低电平、D1 (MOSI)保持高电平、并且驱动器在此状态下挂起。

经过大量的阅读和实验、仍然不清楚如何启用 DMA 的魔法。  希望有人能让我走上正确的轨道。

编辑:更新了后续帖子中的详细信息。

我可以看到、驱动程序在txrxdone以下标志上一直旋转:

static unsigned omap2_mcspi_rx_dma(struct spi_device *spi, struct
    spi_transfer *xfer, struct dma_slave_config cfg, unsigned es)
{
    /* ... */

    ret = mcspi_wait_for_completion(mcspi, &mcspi->txrxdone);

    /* ... */
}

以下是一些图、其中展示了该问题以及用于测试的命令:

root@am437x-evm:~# spi-pipe -d /dev/spidev1.0 -m 0 -s 100000 -n 1 -b 8 < /dev/urandom > /dev/null
root@am437x-evm:~# spi-pipe -d /dev/spidev1.0 -m 0 -s 100000 -n 1 -b 159 < /dev/urandom > /dev/null
root@am437x-evm:~# spi-pipe -d /dev/spidev1.0 -m 0 -s 100000 -n 1 -b 160 < /dev/urandom > /dev/null命令挂起

8 bytes

159 bytes

160 bytes

为避免疑义、在 DTS 中注释的两行即 DMA 被禁用的情况下、可以在一个块中传输多达4096个字节、而没有明显的问题。

4096 bytes

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

    我已经更新了 DTS 文件、找到了一些相关示例。  我使用am437x-gp-evm.dts的是针对正在使用的 TMDSEVM437X 板的,进行了以下更改。  遗憾的是、引脚行为与之前所述的完全相同、因此虽然更正确、但 DMA 仍然无法正常工作。

    --- arch/arm/boot/dts/am437x-gp-evm.dts.orig	2022-12-17 16:26:07.896847833 +0000
    +++ arch/arm/boot/dts/am437x-gp-evm.dts	2022-12-17 17:58:24.308768199 +0000
    @@ -526,10 +526,6 @@
     			AM4372_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)
     			AM4372_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)
     			AM4372_IOPAD(0x950, PIN_INPUT_PULLDOWN | MUX_MODE7)
    -			AM4372_IOPAD(0x990, PIN_INPUT_PULLDOWN | MUX_MODE7)
    -			AM4372_IOPAD(0x994, PIN_INPUT_PULLDOWN | MUX_MODE7)
    -			AM4372_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE7)
    -			AM4372_IOPAD(0x99c, PIN_INPUT_PULLDOWN | MUX_MODE7)
     			AM4372_IOPAD(0x9a0, PIN_INPUT_PULLDOWN | MUX_MODE7)
     			AM4372_IOPAD(0xa3c, PIN_INPUT | PULL_DISABLE | MUX_MODE7)
     			AM4372_IOPAD(0xa40, PIN_INPUT_PULLDOWN | MUX_MODE7)
    @@ -613,6 +609,24 @@
     			AM4372_IOPAD(0x954, PIN_INPUT_PULLDOWN | MUX_MODE0)
     		>;
     	};
    +
    +        spi1_pins_default: spi1_pins_default { /* pin configuration for SPI1-master */
    +                pinctrl-single,pins = <
    +                        AM4372_IOPAD(0x990, PIN_INPUT        | MUX_MODE3) /* (N24) SPI1_SCLK */
    +                        AM4372_IOPAD(0x994, PIN_INPUT_PULLUP | MUX_MODE3) /* (N22) SPI1_D0 */
    +                        AM4372_IOPAD(0x998, PIN_OUTPUT       | MUX_MODE3) /* (H23) SPI1_D1 */
    +                        AM4372_IOPAD(0x99c, PIN_OUTPUT       | MUX_MODE3) /* (M24) SPI1_CS0 */
    +                >;
    +        };
    +
    +        spi1_pins_sleep: spi1_pins_sleep {
    +                pinctrl-single,pins = <
    +                        AM4372_IOPAD(0x990, PIN_INPUT_PULLUP | MUX_MODE3) /* (N24) SPI1_SCLK */
    +                        AM4372_IOPAD(0x994, PIN_INPUT_PULLUP | MUX_MODE3) /* (N22) SPI1_D0 */
    +                        AM4372_IOPAD(0x998, PIN_INPUT_PULLUP | MUX_MODE3) /* (H23) SPI1_D1 */
    +                        AM4372_IOPAD(0x99c, PIN_INPUT_PULLUP | MUX_MODE3) /* (M24) SPI1_CS0 */
    +                >;
    +        };
     };
     
     &uart0 {
    @@ -1123,3 +1137,19 @@
     	ti,set-io-isolation;
     	ti,scale-data-fw = "am43x-evm-scale-data.bin";
     };
    +
    +&spi1 {
    +        status = "okay";
    +        pinctrl-names = "default", "sleep";
    +        pinctrl-0 = <&spi1_pins_default>;
    +        pinctrl-1 = <&spi1_pins_sleep>;
    +
    +        dmas = <&edma 16 0 &edma 17 0>;
    +        dma-names = "tx0", "rx0";
    +
    +        spidev@0 {        // using CONFIG_SPI_SPIDEV=y
    +                compatible="linux,spidev";
    +                spi-max-frequency = <12000000>;
    +                reg = <0>;
    +        };
    +};
    

    通过检测驱动程序代码spi-omap2-mcspi.c,我可以看到它写入了以下寄存器值...

    MODULCTRL = 0x00000001
    WAKEUPENABLE = 0x00000001
    CHCTRL0 = 0x00000000
    CHCONF0 = 0x200103cc
    CHCONF0 = 0x200103cc
    CHCTRL0 = 0x00000000
    CHCONF0 = 0x200103cc
    CHCONF0 = 0x200103cc
    CHCTRL0 = 0x00000000
    CHCONF0 = 0x200103cc
    CHCONF0 = 0x200103cc
    CHCTRL0 = 0x00001d00
    CHCONF0 = 0x200103fc
    CHCONF0 = 0x200103fc
    CHCONF0 = 0x201103fc
    CHCTRL0 = 0x00001d00
    CHCTRL0 = 0x00001d00
    CHCONF0 = 0x201103fc
    CHCONF0 = 0x201103fc
    XFERLEVEL = 0x00a00000
    CHCONF0 = 0x381103fc
    CHCTRL0 = 0x00001d01
    IRQENABLE = 0x00020000
    CHCONF0 = 0x381143fc
    CHCONF0 = 0x3811c3fc
    

    (笑声) txrxdone在该标志上永久旋转之前:

    static unsigned omap2_mcspi_rx_dma(struct spi_device *spi, struct
        spi_transfer *xfer, struct dma_slave_config cfg, unsigned es)
    {
        /* ... */
    
        ret = mcspi_wait_for_completion(mcspi, &mcspi->txrxdone);
    
        /* ... */
    }