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/AM3359:AM335x Linux UART DMA 不工作

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/772225/linux-am3359-am335x-linux-uart-dma-not-working

器件型号:AM3359

工具/软件:Linux

您好!

 我有一个 Beagle boneback Devkit、它配备了 am3359。 它使用从最新 SDK "ti-processor-sdk-linux-am335x-evm-05.02.00.10"编译的 uboot 和内核运行。 因此、内核版本号为'4.14.79'。  

 我将 Devkit 的 UART4连接到我的主机 PC (通过 USB2RS232转换器)。 通过将连续字节从 PC 发送到 Devkit 的 UART4,我发现 uart4的 RX DMA 永远不起作用,这意味着它接收到的每个字节都是通过轮询(serial8250_Rx_chars )而不是 DMA 来实现的。

以下是我的 DTS 配置的一部分:

uart4_pins:pinmux_uart4_pins{
 pinctrl-single、pins =<
 0x70 (PIN_INPUT_PULLUP | MUX_MODE6)/* GPMC_wait0.uart4_RxD *
 0x74 (PIN_OUTPUT 下拉| MUX_MODE6)/* GPMC_WPN.uart4_TXD *
 >;
};

uart4{(&U)
 pinctrl-names ="default";
 pinctrl-0 =<uart4_PINs>;
 状态="正常";
};

uart4:串行@481a8000{
 兼容="ti、OMAP3-UART";
 ti、hwmods ="uart5";
 时钟频率=<48000000>;
 reg =<0x481a8000 0x2000>;
 reg-shift =<2>;
 中断=<45>;
 STATUS ="禁用";
 DMA =<&EDMA 34>、<&EDMA 35>;
 dma-names ="TX"、"Rx";
};

通过搜索整个 DTS 文件(DTS 和 dtsi)、我确认了信道34和35从未被其他功能引用。

我在8250_omap.c 中添加了一些 printk、并有一些发现:

每次通信 Rx char 时、都会按顺序调用以下堆栈:

  OMAP-8250_Handle_Rx_DMA >> Handle_Rx_DMA >> OMAP-8250_Rx_DMA_FLUSH >> serial8250_Rx_CHARs >> OMAP-8250_Rx_DMA

 看起来、DMA 从站已经准备好并始终等待传入字节、但当中断到达时、DMA 从站将被清空、清空时不会将任何内容插入 TTY 缓冲区。

 然后、FIFO 中剩余的所有字符都由'serial8250_Rx_chars'读取。

 同样、为下一个 DMA 准备了一个新的从器件、它仍在下一个中断时被清空、该 DMA 也不会传输任何字节。

在整个测试中、DMA 不会传输 PC 到 Devkit 的任何字节、它们都在'serial8250_rx_chars '中逐一读取。

随附的'end.c'和'resc.c'是我的测试程序。 'end.c'在 PC (Ubuntu)上运行、而'rescv.c'在 Devkit (AM335x)上运行。

我们将感谢您的任何帮助。

e2e.ti.com/.../recv.ce2e.ti.com/.../2783.send.c

此致、

XJ

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

    首先、Processor SDK Linux v5.1.0.11引入了一个驱动程序错误、当多个 UART 同时打开时、该错误会导致 DMA 失败、因此 Processor SDK Linux v5.2.0.10也会受到该错误的影响。

    要检查您遇到的问题是否是由该驱动程序错误引起的、您能否使用 Processor SDK Linux v5.0.0.15进行测试以查看问题是否发生?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    ,从哪里下载 SDK 5.0.0.15? 顺便说一下,在测试期间、只有调试控制台(uart0)和 uart4同时使用、只有 uart4正在尝试使用 DMA。 我不知道这是不是问题。 从何处获取错误详细信息?

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

    很抱歉、我读邮件速度太快、认为您使用的是4个 UART 端口。
    不、您的用例不受我提到的错误的影响。 控制台 UART (uart0)不使用 DMA、因此测试中仅使用 uart4。 仅当多个 UART 端口同时使用 DMA 时、上述错误才会影响。

    我将查看此测试用例、并让您返回。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    单字节、在 UART 接收端(AM335x Linux UART 驱动程序)、永远不会调用 DMA 回调__DMA_Rx_COMPLETE。 在每个 FIFO 中断处理程序中、DMA 被清空(没有任何字节被传输)、所有字节通过原始 func serial8250_Rx_chars 进行传输。 DMA 似乎准备就绪、但无法正常工作。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    [引用 user="user4248043"]uart4:serial@481a8000{
    (笑声)
     DMA =<&EDMA 34>、<&EDMA 35>;
     dma-names ="TX"、"Rx";
    };[/报价]

    您是否添加了这些 DMA 通道? 我在 Processor SDK Linux v5.2.0.10的内核源代码中看不到它们。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我从 uboot 的 DTS 文件模板中添加它们。 内核将解析 DTS 文件并请求 DMA 通道。 如何确认内核将驱动指定的 DMA 通道?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    对 UART3使用通道34和35不正确。 请查看 TRM 表11-23以了解 EDMA 事件、34和35未连接到 UART3。 您应该参阅表11-24并使用 EDMA 交叉开关通道7和8。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你是对的。 Uart4 DMA 事件固定为纵横制的9和10、我需要挑选两个可用的 DMA 通道并将其映射到纵横制事件9和10。 这是通过正确的 DTS 设置来完成的。 我将发布我的已验证 DTS 设置、然后关闭此问题。 谢谢!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    据我了解、对于表11-23 "直接映射事件"、DMA 通道是事件、无需重定向或映射(或多路复用器)。 这就是为什么在您的示例 DTS 文件中、信道28和29分配给 uart1、信道30和31分配给 uart2。 这些分配是固定的。

    //////////////////////////////////////////////////////////////////////////////////////////////
    uart1:串行@48022000{
    兼容="ti、am3352-uart"、"ti、omap3-uart";
    ti、hwmods ="uart2";
    时钟频率=<48000000>;
    REG =<0x48022000 0x2000>;
    中断=<73>;
    STATUS ="禁用";
    DMA =<&EDMA 28 0>、<&EDMA 29 0>;
    dma-names ="TX"、"Rx";
    };

    uart2:串行@48024000{
    兼容="ti、am3352-uart"、"ti、omap3-uart";
    ti、hwmods ="uart3";
    时钟频率=<48000000>;
    REG =<0x48024000 0x2000>;
    中断=<74>;
    STATUS ="禁用";
    DMA =<&EDMA 30 0>、<&EDMA 31 0>;
    dma-names ="TX"、"Rx";
    };
    //////////////////////////////////////////////////////////////////////////////////////////////

    对于表11-24 "crossbar 映射事件"、集成了一个新的控制器"crossbar"来扩展更多 DMA 事件、从而实现更多外设。
    UART4已与固定事件编号9&10交叉开关、您应该为这两个事件选择映射的两个 DMA 通道。
    下面是我的 DTS 设置的一部分:

    //////////////////////////////////////////////////////////////////////////////////////////////
    /*这是 Xbar 控制器*/
    EDMA_Xbar:dma-router@f90{
    兼容="ti、am335x-edma-crossbar";
    reg =<0xf90 0x40>;
    dma-cells =<3>;
    DMA 请求=<32>;
    dma-masters =<&edma>;
    };

    /*这些是 uart4设置*/
    uart4:串行@481a8000{
    兼容="ti、am3352-uart"、"ti、omap3-uart";
    ti、hwmods ="uart5";
    时钟频率=<48000000>;
    reg =<0x481a8000 0x2000>;
    中断=<45>;
    STATUS ="禁用";
    DMA =<&EDMA_Xbar 34 0 9.
    EDMA_Xbar 35 0 10>;
    dma-names ="TX"、"Rx";
    };
    //////////////////////////////////////////////////////////////////////////////////////////////

    "dmas"设置直接指向"edma_xbar"而不是"edma"、34和35是 DMA 通道(您可以选择其他可用通道)、9和10是 Xbar 事件、这些事件是表11-24中的固定值。

    请注意、如何识别 DMA 是否正常工作。
    我在内核 menuconfig 中启用了"DMA 引擎调试和 DMA 引擎详细调试"。
    DMA 传输完成后、键入指令'dmesg | grep dma'以检查是否存在以下类似情况:

    //////////////////////////////////////////////////////////////////////////////////////////////
    [153.695592] EDMA 49000000.EDMA:vchan dc272908:TXD db0ef240[1ade]:已提交
    [153.695610] EDMA 49000000.EDMA:
    [153.695619] EDMA 49000000.EDMA:从通道38开始的第一次传输
    [153.695627] EDMA 49000000.EDMA:ER1 00000000
    [153.695635] EDMA 49000000.EDMA:EER1 00000040
    [153.695719] EDMA 49000000.EDMA:DMA_IRQ_handler
    [153.695728] EDMA 49000000.EDMA:EER1 00000000
    [153.695736] EDMA 49000000.EDMA:TXD db0ef240[1ade]:标记为完成
    [153.695744] EDMA 49000000.EDMA:通道38上的传输完成
    //////////////////////////////////////////////////////////////////////////////////////////////

    我认为这可以用来标识通道38的成功 DMA 传输(使用以下关键字:Submit、IRQ_handler、complete)。
    如果您正在使用 DMA 尝试 UART、则发现 dmesg 仅包含"提交"但"完成"、尽管您仍然可以通过 UART 接收或发送字符、但应注意 DMA 不起作用、传输或接收的字符将以原始轮询方式处理。

    我的验证案例是使用 GitHub 上的最新内核 Kernel 4.14.94。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="user4248043"]我在内核 menuconfig 中启用了"DMA 引擎调试和 DMA 引擎详细调试"。[/quot]

    这不是检查 DMA 的最佳方法、它会在日志中启用批次消息。 我将以一种简单的方式在内核中添加一条调试消息作为下面的补丁。

    diff -git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
    index 2bb0b092bff2..873121c728tty 100644
    -- a/drivers/tty/serial/8250/8250_omap.c index
    +
    @@@@ 8b_tid_t_tid_port/8250 tid_r_r_port_tids/static t_t_port_port_r_en_tid_644/tid_t_t_r_r_tid_t_t_t_r_r_port_r_tids/
    if (计数< dma->rx_size)
    dmaengine_terminate_async (dma->rxchan);
    
    + dev_info (p->port.dev、"DMA Rx %d 字节\n"、count);
    RET = tty_insert_flip_string (tty_port、dma->rx_buf、count);
    
    p->port.icount.rx +=转台
    

    然后使用一根导线回看 UART4 RX 和 TX 引脚、在串行控制台上运行以下命令、将50个字节传输到 UART4。

    root@AM335x-EVM:~# echo "12345678901234567890123456789012345678901234567890123456789012345678901234567890">/dev/ttyS4

    然后、您应该会看到以下显示 DMA 接收48字节的内核日志。

    [411.074237] omap8250 481a8000.serial: DMA Rx 48字节
    [411.079405] omap8250 481a8000.serial: DMA Rx 0字节
    [411.094727] omap8250 481a8000.serial: DMA Rx 0字节

    请注意、UART 的 DMA 一次只移动48字节数据、DMA 不会完成任何传输提醒。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、我尝试在_dma_rx_do_complete 中添加 printk、我得到的结果与您打印的结果相同。
    在吞吐量测试期间、所有 printk 和 log 都将被禁用。

    RX_TRIGGER 为48、我是否可以更改它以获得更高的性能?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    您可以增加 RX_TRIGGER 以减少中断数量、但它不能确保更高的性能。 您必须在您的系统上测试它。