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.

[参考译文] CCS/TM4C1294NCPDT:有关 DMA 的小帮助

Guru**** 2482225 points
Other Parts Discussed in Thread: TM4C1294NCPDT

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/718361/ccs-tm4c1294ncpdt-a-little-help-with-dma

器件型号:TM4C1294NCPDT

工具/软件:Code Composer Studio

我正在努力使用 DMA 方法从阵列传输数据并将其发送到 UART 端口。 我可以将其放在 UART 1的数据寄存器中、但无法通过 COM 端口显示相同的内容。

我怎么能做到这一点… 如果我不想再使用任何数组!!!

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

    您可以查看 Tivaware 中的 UDMA_DEMO 示例程序。

    -kel
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、我已经看到了这个示例、我希望根据上述要求对这个示例进行一些更改。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Rohan、

    我真的不明白根据您的描述您缺少了哪些信息、您能否概述您已经采取了哪些步骤、到目前为止、哪些结果以及当前为您服务的内容缺少哪些内容? 此时、UDMA_DEMO 又不能满足您的需求呢?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Ralph、
    我要做的是使用 DMA 通过 PC 的 COM 端口从存储器位置发送数据。
    到目前为止、我还没有得到任何结果、只能更新指定 UART 端口的存储寄存器、但无法通过 UART COM 端口显示。

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

    您需要做的是缓冲数据、然后使用 UART 打印 API 将其发送到 PC。 如果您希望直接从 DMA 馈送 UART 打印 API、则尚未实施(据我所知)、也没有太大意义、因为 UART 打印速度比 DMA 传输慢、因此您不会获得任何实际好处。 使用 DMA 的想法是允许 CPU 在空闲 CPU 时钟周期内传输数据以提高效率。 这不适合通过 CPU 时钟周期驱动的 UART 控制台输出数据。 更有意义的是、在 UART 打印输出当前缓冲区的同时使用 DMA 填充下一个缓冲区、以加快接收数据与将其传回所需的总时间。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    void
    InitUART1传输(void)
    {
    uint_fast16_t ui16Idx;
    
    //
    //用简单的数据模式填充 TX 缓冲区。
    //
    对于(ui16Idx = 0;ui16Idx < UART_TXBUF_SIZE;ui16Idx++)
    {
    g_ui8TxBuf[ui16Idx]= ui16Idx;
    }
    
    //
    //启用 UART 外设,并将其配置为即使 CPU 也能正常工作
    //处于睡眠状态。
    //
    ROM_SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
    ROM_SysCtlPeripheralSlepEnable (SYSCTL_Periph_UART0);
    
    //
    //配置 UART 通信参数。
    //
    ROM_UARTConfigSetExpClk (UART0_BASE、g_ui32SysClock、115200、
    UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    UART_CONFIG_PAR_NONE);
    
    //
    //将 TX 和 RX 触发阈值设置为4。 这将由使用
    // uDMA 控制器发出信号,指示何时应传输更多数据。 。
    //将配置 uDMA TX 和 RX 通道,以便可以传输4个通道
    当 UART 准备传输更多数据时、//以突发方式传输字节。
    //
    ROM_UARTFIFOLevelSet (UART0_BASE、UART_FIFO_TX4_8、UART_FIFO_RX4_8);
    
    //
    //启用 UART 以进行操作,并为两个 TX 启用 UDMA 接口
    //和 RX 通道。
    //
    ROM_UARTEnable (UART0_BASE);
    ROM_UARTDMAEnable (UART0_BASE、UART_DMA_RX | UART_DMA_TX);
    
    //
    //该寄存器写入将 UART 设置为在环回模式下运行。 任何
    //在 TX 输出上发送的数据将在 RX 输入上接收。
    //
    HWREG (UART0_BASE + UART_O_CTL)|= UART_CTL_TXE|UART_CTL_RXE;
    
    
    //
    //将 UDMA UART0RX 通道的属性置于已知状态。 这些
    默认情况下、//应已禁用。
    //
    ROM_uDMAChannelAttributeDisable (UDMA_CHANGE_UART0RX、
    UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
    UDMA_ATTR_HIGH_PRIOR|
    UDMA_ATTR_REQMASK);
    
    //
    //为配置主控制结构体的控制参数
    // UART RX 通道。 主控制结构用于"A"
    //部分乒乓接收。 传输数据大小为8位
    //源地址不会递增,因为它将从读取
    //寄存器。 目的地址增量是字节8位字节。 。
    //仲裁大小设置为4以匹配 RX FIFO 触发阈值。
    //如果可能,UDMA 控制器将使用4字节突发传输。 这种情况
    //这种单字节传输会更有效一些。
    //
    ROM_uDMAChannelControlSet (UDMA_CHANGE_UART0RX | UDMA_PRI_SELECT、
    UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
    UDMA_ARB_4);
    
    
    ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART0RX | UDMA_PRI_SELECT、
    UDMA_MODE_BASIC、
    (void *)(UART0_BASE + UART_O_DR)、
    g_ui8RxBufA、sizeof (g_ui8RxBufA);
    
    //
    //设置 UART RX 交替控制的传输参数
    //结构。 模式设置为乒乓模式、传输源为
    // UART 数据寄存器,目的是接收"B"缓冲区。 。
    //传输大小设置为与缓冲区大小匹配。
    //
    /* ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART0RX | UDMA_ALT_SELECT、
    UDMA_MODE_PINGONG、
    (void *)(UART0_BASE + UART_O_DR)、
    g_ui8RxBufB、sizeof (g_ui8RxBufB);*
    
    //
    //将 UDMA UART0TX 通道的属性置于已知状态。 这些
    默认情况下、//应已禁用。
    //
    ROM_uDMAChannelAttributeDisable (UDMA_CHANGE_UART0TX、
    UDMA_ATTR_ALTSELECT |
    UDMA_ATTR_HIGH_PRIOR|
    UDMA_ATTR_REQMASK);
    
    //
    //设置 UDMA UART TX 通道的 USEBURST 属性。 这将会
    //强制控制器在传输数据时始终使用突发
    //将 TX 缓冲器连接到 UART。 这是比较有效的总线使用
    //不是允许单次或突发传输的默认值。
    //
    ROM_uDMAChannelAttributeEnable (UDMA_CHANGE_UART0TX、UDMA_ATTR_USEBURST);
    
    //
    //配置 UART TX 的控制参数。 UDMA UART TX
    //通道用于将数据块从缓冲区传输到 UART。
    //数据大小为8位。 源地址增量为8位字节
    //因为数据来自缓冲区。 目的增量为
    //由于数据将被写入 UART 数据寄存器,因此不存在。 。
    //仲裁大小设置为4,与 UART TX FIFO 触发器匹配
    //阈值。
    //
    ROM_uDMAChannelControlSet (UDMA_CHANGE_UART0TX | UDMA_PRI_SELECT、
    UDMA_SIZE_8 | UDMA_SRC_INC_8 |
    UDMA_DST_INC_NONE |
    UDMA_ARB_4);
    
    //
    //设置 uDMA UART TX 通道的传输参数。 这将会
    //配置传输源和目的以及传输大小。
    //使用基本模式是因为外设正在进行 UDMA 传输
    //请求。 源是 TX 缓冲区、目的是 UART
    //数据寄存器。
    //
    ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART0TX | UDMA_PRI_SELECT、
    UDMA_MODE_BASIC、g_ui8TxBuf、
    (void *)(UART0_BASE + UART_O_DR)、
    sizeof (g_ui8TxBuf));
    
    printf ("data %X \n"、(void *)(UART0_BASE + UART_O_DR);
    //
    //现在,UDMA UART TX 和 RX 通道都被引脚以启动 A
    //传输。 一旦启用通道、外设将会启动
    //发出传输请求,数据传输将开始。
    //
    ROM_uDMAChannelEnable (UDMA_CHANGE_UART0RX);
    ROM_uDMAChannelEnable (UDMA_CHANGE_UART0TX);
    
    //
    //启用 UART DMA TX/RX 中断。
    //
    ROM_UARTIntEnable (UART0_BASE、UART_INT_DMATX | UART_INT_DMATX);
    
    //
    //启用 UART 外设中断。
    //
    ROM_IntEnable (INT_UART0);
    } 

    您好 Ralph、

    其基本理念不是仅打印数据、而是仅打印项目的一部分。

    我正在尝试设置0-256的数组、并通过使用 DMA 而不使用打印功能将其传输到 UART0 COM 端口。

    谢谢!  

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

    您正在使用的示例是回送模式、由于回送是如何完成的、该模式包含 TX 和 RX 设置。 对于您描述的示例、您希望将 TX 发送到终端。 不过、我看到了许多设置 RX 的代码。 我建议现在移除与 RX 相关的任何内容、并首先关注 TX 的工作。 如果您还需要处理 RX、那么我们在后面添加该部分、但如果您可以通过删除与 RX 相关的所有内容来清理代码、然后查看您是否获得任何不同的行为、则这将只是调试过程。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Ralph、

    我尝试从该示例中删除所有 RX 组件、仅启用 TX 以通过 COM 端口发送数据、但需要注意的是、它会出现。

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

    如果不注意(UART0发生故障)已(仅限)"部分初始化!"

    // Enable the UART peripheral, and configure it to operate even if the CPU is in sleep.

        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

        ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);

    不是对基本函数的(附加)调用:

    • SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);

    • GPIOPinConfigure (GPIO_PA0_U0RX);
    • GPIOPinConfigure (GPIO_PA1_U0TX);
    • GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);

    还需要?   只要"愿意" - 这些呼叫要么是"默认行为" 、要么  是在其他地方发出(可能)?

    如海报所述: "仅启用 TX 以通过 COM 端口发送数据... 但却注意到了这一点。"   ('IT' 为- (未完全初始化) 'UART0!')

    (始终) "优步问题解决" "kiss" 指示 、"所有多余的" (不仅仅是(已经)励行的 RX 代码)应(暂时删除)、  而是安装最基本的"UART 代码示例" 、 然后是测试/验证。   

    如果并且仅在-这种情况下、'OST basic - yet most vital of operations is confirmed (最重要的操作已确认)' 应添加"多余"的(单个部分)-并 单独 和 顺序 测试    一次测量/确认一个步骤(或一个部分)...

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 CB1
    UART0已使用上述所有函数完全初始化、但我没有将其包含在所示的代码中
    如果您看一下该示例、则该函数具有 UART 配置 tat 的函数。 我已从该函数中删除 Rx 部分、并尝试在该函数中也启用 Rx。

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

    问候-感谢您(非常快速)的回答。

    现在很少有人知道您(有选择地)提供(和删除)函数调用- 并且包括了"不那么重要"的'sleep Enable()'-这 会使您感到困惑!   (生命是隐藏的-包括"多余" -这是不一致的-不是吗?)   和... 浪费时间和制造工作...

    如建议-代码(显示... 未知是其他的东西... "看不见")增加了复杂性-并严重违反了""。   错误和冲突被"邀请"-这证明是如此不明智!

    如前所述、最小、最简单的代码实现方式成功地从 UART 获取正确的输出、即我的"最佳、优先和唯一"建议!   (您是否真的希望、"放下您的 UART 龙!"   (代码过量引入的额外复杂性和"缺陷"不能证明您的朋友!    没有朋友帮助你 crüe -或者...)

    作为一名前美国军官,我们被教导说,“限制我们的战斗规模/范围”——与 “ 所有方面/方向”的战斗 ——最常——并不是“结束得好”。   (此处如此... )

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

    很抱歉、我没有提到项目的名称、它是 Code Composer Studio 中电路板 TM4C1294NCPDT 的 UDMA_DEMO。 我希望现在您可以轻松地参考该示例并为我提供一些良好的解决方案、以便我可以实现所需的输出集。

    谢谢!!
    罗汉
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    请再次阅读-我的帖子-在您之前的"8分钟"到达! 调试和解析'en masse'-早已证明-是一种"最有效"的解决方案解析方法... “婴儿台阶”——即使是(第一个)月球爱好者所说的——创造伟大(最好)的感觉!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Ralph、

    我们的基本要求是使用 DMA 将数据传输到 UART 外设、而无需 CPU 干预、不会从 DMA 中取出 RX 缓冲区、然后将其传输到 UART、这需要额外的 CPU 周期。
    我们只希望处理后的缓冲区可以传输到 UART 外设、这样代码就不会卡在 ISR 上以处理数据并发送到 UART。 请建议我们如何使用此演示代码来满足我们的要求。

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

    是否可以在删除 RX 函数的情况下发布代码、以便我可以在不包含所有以 RX 为中心的调用的情况下再次查看该代码?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    void
    ConfigureUART (void)
    {
    //
    //启用 UART 使用的 GPIO 外设。
    //
    ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
    
    //
    //启用 UART0
    //
    ROM_SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
    ROM_SysCtlPeripheralSlepEnable (SYSCTL_Periph_UART0);
    
    //
    //为 UART 模式配置 GPIO 引脚。
    //
    //ROM_GPIOPinConfigure (GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure (GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_1);
    
    //
    //初始化控制台 I/O 的 UART
    //
    UARTStdioConfig (0、115200、g_ui32SysClock);
    }
    
    void
    UART0IntHandler (void)
    {
    uint32_t ui32Status;
    uint32_t ui32模式;
    
    //
    //读取 UART 的中断状态。
    //
    ui32Status = ROM_UARTIntStatus (UART0_BASE、1);
    
    //
    //清除任何挂起状态,即使由于没有 UART,应该没有任何挂起状态
    //中断已启用。 如果启用了 UART 错误中断
    //这些中断可能在这里发生,应该被处理。 UDMA 的影响
    //用于 RX 和 TX、那么这两个中断都不应该
    //已启用。
    //
    ROM_UARTIntClear (UART0_BASE、ui32Status);
    
    //
    //检查 DMA 控制表以查看乒乓"A"传输是否为
    //完成。 "A"传输使用接收缓冲器"A"和主缓冲器
    //控制结构。
    //
    ui32Mode = ROM_uDMAChannelModeGet (UDMA_CHANGE_UART0TX | UDMA_PRI_SELECT);
    
    //
    //如果主控制结构体指示停止,则表示"A"
    //接收缓冲完成。 UDMA 控制器仍应接收
    //将数据输入"B"缓冲区。
    //
    if (ui32Mode = uDMA_MODE_STOP)
    {
    //
    //递增计数器以指示数据已接收到缓冲区 A 中
    //一个实际应用,此应用将用于向主线程发出信号
    //数据已接收,因此主线程可以处理数据。
    //
    G_ui32RxBufACount++;
    
    //
    //使用主缓冲区为"A"缓冲区设置下一个传输
    //控制结构。 进入"B"缓冲器的持续接收为时
    //完成,UDMA 控制器将切换回这个。 这种情况
    //示例重复使用缓冲区 A,但更复杂的应用可能
    //使用一组旋转的缓冲区来增加该时间
    //主线程必须先处理缓冲区中的数据,然后再处理
    //重复使用。
    //
    ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART0TX | UDMA_PRI_SELECT、
    UDMA_MODE_BASIC、
    (void *)(UART0_BASE + UART_O_DR)、
    g_ui8RxBufA、sizeof (g_ui8RxBufA));
    }
    
    
    //
    //如果 UART1 DMA TX 通道被禁用,则表示 TX DMA 传输
    //完成。
    //
    if (!ROM_uDMAChannelIsEnabled (UDMA_CHANGE_UART0TX))
    {
    //
    //开始到 UART1 TX 的另一个 DMA 传输。
    //
    ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART0TX | UDMA_PRI_SELECT、
    UDMA_MODE_BASIC、g_ui8TxBuf、
    (void *)(UART0_BASE + UART_O_DR)、
    sizeof (g_ui8TxBuf));
    
    //
    //必须重新启用 uDMA TX 通道。
    //
    ROM_uDMAChannelEnable (UDMA_CHANGE_UART0TX);
    } 

    我提到了我的两个函数、这两个函数已配置为支持 UART0、且仅启用 TX。

    谢谢你  

    罗汉

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

    您好、Rohan、

    很抱歉耽误您的时间、但我决定自己从 UDMA_DEMO 制作 CCS 项目示例更容易、以便与您尝试的操作类似。 虽然这并不完整、但它肯定会将 UDMA 数据直接传输到终端。 这将为您提供 UDMA 设置代码。

    请比较您的项目与此项目的设置代码、并查看任何差异。 我知道我从您的示例中更改了一个内容、即在 uDMA_MODE_STOP IF 语句中、我调整了 ROM_uDMAChannelTransferSet 以使用 g_ui8TxBuf 而不是 g_ui8RxBufA。

    e2e.ti.com/.../udma_5F00_demo_5F00_tx_5F00_only.zip

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Ralph、
    非常感谢你们的帮助 然而、我已经通过 UDMA 传输到 COM 端口、但从基础知识中发现了一些愚蠢的错误。

    此致
    罗汉