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.

[参考译文] TM4C1294NCPDT:利用 DMA 和 UART RX

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/990998/tm4c1294ncpdt-leveraging-dma-with-uart-rx

器件型号:TM4C1294NCPDT

背景:
我的 TM4C129上有专用的 UART6 (RX PP0)、用于从另一个传感器读取串行数据。 就 TM4C 上接收的数据而言、传感器每7ms 发送(n)个帧、每个帧的宽度为32字节。 两侧的波特率均为115200。

目标:
在这种情况下、速度至关重要、因为 TM4C 负责执行其他任务、例如读取编码器和限位开关。

因此、我想采用我的中断驱动方法(见下文)、并尝试查看是否可以利用 DMA 从 UART RX 外设存储器创建一个管道、然后将其放入我自己在 SW 中本地创建的缓冲区。

进度:
我已经修改了基本 UART_echo 示例、但很明显地更改了周围的内容、以便接收到的数据来自传感器、而不是来自用户的手动输入。 然后、当数据在 UART6上传入时、我会在 UART0上打印出来、并可以在串行控制台(RealTerm)中查看数据。

问题:
在读取 DMA 并查看 UDMA_DEMO 示例后、我认为这可能是最佳方法。 但是、我正在努力调整现有代码以使用它。 例如、我看到有大量代码通过 UART TX 发送数据、这是由 DMA 促成的。 但是、我看不到许多让 DMA 简单地从 UART RX 接收数据的示例。

请注意 、UDMA_DEMO 的功能 与 我想要的类似、但我似乎无法连接点。 例如、该示例应用的一个理想特征是它已将 DMA 设置为使用某种乒乓方法。 我阅读了 TivaWare 中的文档、并认为这肯定适用于我的应用、也就是说、当我通过 UART 收集这32个字节的数据时、我可以解析之前收集的帧(32字节)、 并在下一个32字节块出现时执行相应的操作。

我想这是一个很长的提问时间、这是我关于 DMA 如何与 UART RX 有效交互的思考过程(上面提到的外设管道思想)。 如果是、下一步的最佳方法是什么。 在 TivaWare 中是否有任何其他示例可供您考虑、在这种情况下、这些示例可能会有所帮助?  

谢谢!

参考代码:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
uint32_t g_ui32SysClock;
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

    在这种情况下、将 UDMA 用于 UART RX 是很有意义的。 您看不到将 UDMA 用于 UART RX 的示例、因为接收的字符数通常是未知的。 在这种情况下、UDMA 不能正常工作。 在这种情况下、连续字符流以32个块的形式进行分组、在乒乓模式下使用 UDMA 是非常有意义的。 我看到的唯一问题是同步、这样您就不会在32字符串的中间开始接收。

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

    尊敬的 Bob:

    感谢您的反馈!

    在确保 UART 按预期工作后、我继续执行上述实现。 我基本上使用了 UDMA_DEMO、与 DriverLib 文档中的 DMA 部分结合使用。 具体侧重于第31.2.1节、其中列出了设置 DMA 的一般步骤。



    我已经附上了代码供参考、我认为我已经接近了、但我可能错过了一个步骤。

    我可以看到 UART ISR 被调用、但 DMA 缓冲区未被填满。





    为了使调试器的操作更加简单、我在中将 UART/DMA 配置进行了隔离 configDmaWithUart().

    乍一看、下面的函数中是否有任何看起来不合适的东西。 或者是否有任何可能导致我所看到问题的危险信号?

    谢谢!

    参考代码:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdint.h>
    #include <string.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_uart.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/udma.h"
    uint32_t g_ui32SysClock;
    #if defined(ewarm)
    #pragma data_alignment=1024
    uint8_t pui8ControlTable[1024];
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

    我将在星期一回到办公室时详细了解代码。 我附加了一个在乒乓模式下使用 UDMA 的 ADC 示例。 它可能会有所帮助。

    e2e.ti.com/.../1602.ADCwDMA.zip

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

    感谢 、您的示例无疑对您有所帮助。  

    我在这个周末做了一些工作、让它稍微工作。 我还借鉴了您所附的 ADC 示例中的一些想法、以帮助进行调试。

    到目前为止我发现、如果我使用 UART RX 0或1、它就可以工作、从我可以看到 DMA 缓冲区已满的意义上讲。 我需要验证数据、但它在某种程度上是有效的。

    我正在努力解决的另一个主题是 UART 与 DMA 的关系、特别是在中断方面。 我在浏览 TI 的文档时查看了是否有任何有关 DMA 的应用手册、但找不到任何应用手册。 基本上、在我的代码中、我正在注册几个不同的中断、但我是盲目地这样做的、因为我不一定知道需要哪些中断。 例如:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /* The DMA should now be configured for UART RX in ping-ping mode, with both primary
    and secondary buffers pointing to the UART data register */
    ROM_uDMAChannelEnable(UDMA_CHANNEL_UART1RX);
    /* Enable DMA for UART RX. Stop DMA if there's a UART error */
    ROM_UARTDMAEnable(UART1_BASE, UART_DMA_RX | UART_DMA_ERR_RXSTOP);
    /* Enable UART */
    ROM_IntEnable(INT_UART1);
    ROM_UARTIntEnable(UART1_BASE, UART_INT_RX | UART_INT_RT);
    ROM_UARTIntEnable(UART1_BASE, UART_INT_DMATX | UART_INT_DMARX);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX



    简而言之、我有一些 工作要做、但如果您有时间回答以下三个问题、这将有助于我联系点:

    1. 在工作流程方面、您能否给我指出、或者大致描述 DMA UART RX 数据缓冲区"收集"单个字符或字符流所发生的一系列事件? 没什么疯狂的、我更不想寻找这样的东西:
      "首先接收 UART RX 中断、然后让 DMA 执行 X、因此如果您希望 DMA 缓冲区填充(n)个字节、则需要注册 X ISR。"
    2. 也与#1有关、但由于这32个字节是通过 UART 接收的、因此如果我继续使用 UART FIFO、或者这样做会增加一定程度的复杂性。 我猜通过添加 FIFO 路由、ISR 将在给定的填充级别触发、而不是每个字符、但我不确定这将如何影响 DMA、以及它如何累加 UART RX 数据缓冲区中的数据?

    3. 如前所述、我最初尝试使用 launchpad 上的 UART RX 6。 从 UART 的角度来看、这似乎起作用了、我可以将数据从1个传感器推送到 Launchpad 上的指定引脚、并将其值打印到 UART 0。 但是、在这种情况下、我无法连接 DMA。 并注意到在中udma.h,它们有31个默认信道号,例如UDMA_CHANNEL_XXXX。 我用于 UART 6 RX 的 UART 没有映射到其中的任何一个。 因此我切换到了一个映射的(UDMA_CHANNEL_UART1RX),然后一切开始工作。
      在我使用之前 UDMA_CH10_UART6RX,但这可能不是 API 的使用方式,或者它们是通用定义,我的特定 LaunchPad 不支持该 DMA 通道? 总之、只是想知道您的想法。

    再次感谢您的帮助!

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

    要将 UART6与 UDMA 配合使用,您需要使用所有附加函数 uDMAChannelAssign()。 32个 uDMA 通道最多可以有9个不同的连接。 为了实现兼容性,如果通道映射到组0 (例如通道8上的 UART1RX),则不需要调用  uDMAChannelAssign()函数。

    Fullscreen
    1
    2
    3
    4
    uDMAChannelAssign(UDMA_CH10_UART6RX);
    uDMAChannelAssign(UDMA_CH11_UART6TX);
    uDMAChannelEnable(UDMA_CH10_UART6RX);
    uDMAChannelEnable(UDMA_CH11_UART6TX);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="327871" URL"~/support/microcontrollers/other/f/other-microcontrollers-forum/990998/tm4c1294ncpdt-leveraging-dma-with-uart-rx/3661075 #3661075">也与#1有关、但由于这32个字节是通过 UART 接收的、因此、如果我继续使用 UART FIFO、或者这会增加一定程度的复杂性、 我猜通过添加 FIFO 路由、ISR 将在给定的填充级别触发、而不是每个字符、但我不确定这将如何影响 DMA、以及它如何从 UART RX 数据缓冲区中累积数据?[/QUERT]

    在本例中、我认为这不会产生太大的影响。 如果您使用 FIFO、UART 将发出突发 UDMA 请求。 其它 DMA 请求将被忽略、直到突发完成。 (CPU 仍将获得所需的任何总线周期、如果需要、中断突发。) 从 DMA 的角度来看、猝发请求的效率略高。 它确实会增加其他 DMA 请求的延迟、但如果仅将 UART 用于 DMA、则使用 FIFO 会带来更多延迟。 如果您仅使用一个 UDMA 通道、则差异完全无关紧要。 这是数据表中的一些信息。