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.

[参考译文] TMS320F28P650DK:DMA + UART:发送时跳过字节、接收时增加一个字节

Guru**** 2874030 points

Other Parts Discussed in Thread: C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1576434/tms320f28p650dk-dma-uart-skipping-byte-when-transmitting-extra-byte-when-receiving

器件型号: TMS320F28P650DK
主题: C2000WARE 中讨论的其他器件

工具/软件:

您好!
我们的 TMS320F28P650DK6 通过 UART 与另一个 MCU 交换消息(~512 字节)。 大约 10%的时间、TMS 在发送时缺失一个字节、或在接收时发现额外的 0 字节。

TMS 上的 CPU1 在时钟控制下为 200MHz、而 UART 在 1MHz(8 位/字、1 个停止位)下运行。 逻辑分析仪跟踪显示没有异常。 传入的消息看起来非常好、传出的消息看起来很完美、只是中间缺少一个随机字节。 丢失的字节同时出现在从数据包开始的偶数偏移和奇数偏移处。

TX 由 DMA 驱动 — 突发大小 2、在 TX FIFO 中由 14 个或更少字节触发。 DMA 设置为在一次操作中发送整个传输。
RX 也由 DMA 驱动、突发大小为 4、由 RX FIFO 中 4 个或更多字节触发。 DMA 连续运行、缓冲区足够大、适合整个消息。 我可以通过使用调试器观察缓冲器来看到我们收到了杂散零。

我可以使用一些帮助找出导致此行为的原因。 因为 TX DMA 的突发大小是 2、所以不应该发送奇数个字节--但逻辑分析仪清楚地表明、我们偶尔会发送 519、而不是 520。 请提供任何见解。

谢谢!

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

    尊敬的 Anton:

    几件事:

    1. 您能否检查 UART RIS 寄存器并查看传输/接收期间是否出现任何错误标志?
    2. UART 模块的注意事项之一: 接收时无法在调试器中打开 UART 数据寄存器 (UARTDR)、否则 UART 会将其视为对数据寄存器的“读取“、并丢弃 RX FIFO 中的数据。 确保接收数据时在 CCS Register 视图或 Memory 浏览器中打开 UARTDR 寄存器。
    3. 您是否首先尝试在您的设置上从 C2000ware 运行 uart_ex4_loopback_dma 示例作为起点?

    此致、

    Delaney

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

    感谢您的关注!

    1、我重现了 UARTRIS 寄存器报告没有错误的问题。 当我通过启动和停止调试器堆来滥用设备时、我确实设置了一次溢出位、因此看起来一切都已正确设置、中断位也没有意外地被清除。
    我还检查了 UARTRSR 和 DMA 通道的 OVRFLG 位、看起来正常。
    2.谢谢。 我还没有使用调试器查看 UARTDR。
    3.我们从例子开始。 直到最近、我们开始执行更大的(即 520 字节)传输时、一切都运行得比较可靠。
    我还注意到了第二个 UART 上的类似功能、我们也用于器件间通信。 8.33MHz 正在传输 UART、我偶尔会注意到 46 字节传输过程中缺少四个字节。 我不确定这是不是新的,还是我们直到现在才注意到;我可以在下周来看看。

    我发现这些症状非常奇怪。 如果 DMA 太 (与其他 DMA 通道/CPU 争夺资源,触发器丢失等)、我希望能看到传输中的间隙、但没有丢失数据。 相反、它传输时没有间隙、但仍然未命中一个字节。 DMA 是否可能对一个触发器执行两个突发?
    在 RX 方面、我目前的理论是、UART FIFO 流动不足----即 DMA 试图从空 FIFO 中检索一个字节、这会导致 DMA 缓冲区中出现额外的零。 下溢是否会设置任何错误位? 我很难弄清楚这个零点可能来自哪里。

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

    尊敬的 Anton:

    由于问题的性质(丢弃了完整字节)、我预计这会导致 UART FIFO 溢出。 您的突发大小配置和 FIFO 级别相匹配、因此触发和数据传输的时序应正确同步。  

    您能否尝试启用所有错误中断并在 ISR 中放入断点或 ESTOP0、而不是在 CCS 窗口中查找? 这是排除任何错误的更明确的方法。 您可以使用 DMA 通道执行相同的操作 — 启用错误中断标志并在 ISR 内使用 NOP 指令添加 if 语句检查、然后在 if 语句中添加一个断点、看看 CPU 是否停止。  

    此致、

    Delaney

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

    感谢您的建议。 这正是我第一次做的——但我再次尝试了、这次使用了计数器(参见下面的代码片段)。

    DMA 传输结束中断会按我预期触发任意多次。 我 认为 rxmis 不会触发、因为 DMA 始终在 ISR 运行之前清除中断标志。 出于类似的考虑、我想 txmis 中断通常会被 TX DMA 抢占?

    从不设置 DMA 溢出和 UART FIFO 溢出标志、但我在发送时仍经常看到丢失的字节、在接收时看到额外的字节。

    重要的是、我发现只有在启用并运行 USB 外设时才会出现问题。
    据我所知、USB 不应在任何方面与 UART 相冲突:
     - USB 和 UART 不共享外设总线(参见数据表 ,第 295 页),
     -我们没有将 DMA 用于 USB(或除两个 UART 之外的其他任何东西),
     - UART DMA 缓冲器都在 GSRAM0 中,而所有 USB 相关的都在主存储器中,
     -所有的 UART 传输都是在一次 DMA 传输中完成的 — 所以我不希望在传输过程中出现问题,即使中断被禁用并且 CPU 完全与 USB 连接。 RX 更加复杂、因为我们在循环缓冲器配置中以连续模式运行 DMA、但我仍然预计问题会以 DMA 突发大小的倍数(而不是一个字节)出现。

    总之、UART 是自主和完全不受阻碍地运行的、仍然没有一个字节、然后就像没有出现任何问题一样运行。 我不知道该做些什么;任何指导都是值得赞赏的。
    谢谢!

    typedef struct {
        uint32_t tx_dma_transfer_count;
        uint32_t tx_dma_ovrflg;
        uint32_t rx_dma_transfer_count;
        uint32_t rx_dma_ovrflg;
        uint32_t txmis;
        uint32_t rxmis;
        uint32_t femis;
        uint32_t pemis;
        uint32_t bemis;
        uint32_t oemis;
    } uart_err_t;
    volatile uart_err_t g_uart_err = {0};
    
    __interrupt void INT_UARTA_IPC_RX_DMA_ISR(void)
    {
        if(HWREG(UARTA_IPC_RX_DMA_BASE + DMA_O_CONTROL) & DMA_CONTROL_OVRFLG){
            g_uart_err.rx_dma_ovrflg++;
            HWREG(UARTA_IPC_RX_DMA_BASE + DMA_O_CONTROL) = DMA_CONTROL_ERRCLR;
        } else {
            g_uart_err.rx_dma_transfer_count++;
        }
    
        // Record keeping for circular buffer
        g_dbg_ipc_uart.rx_w_wrap_total += 1;
        if(ipc_rx_wrap_cnt < INT16_MAX) ipc_rx_wrap_cnt += 1;
        ipc_rx_wrap_guard = false;
        Interrupt_clearACKGroup(INT_UARTA_IPC_RX_DMA_INTERRUPT_ACK_GROUP);
    }
    
    __interrupt void INT_UARTA_IPC_TX_DMA_ISR(void)
    {
        if(HWREG(UARTA_IPC_TX_DMA_BASE + DMA_O_CONTROL) & DMA_CONTROL_OVRFLG){
            g_uart_err.tx_dma_ovrflg++;
            HWREG(UARTA_IPC_TX_DMA_BASE + DMA_O_CONTROL) = DMA_CONTROL_ERRCLR;
        } else {
            g_uart_err.tx_dma_transfer_count++;
        }
        Interrupt_clearACKGroup(INT_UARTA_IPC_TX_DMA_INTERRUPT_ACK_GROUP);
    }
    
    __interrupt void INT_UARTA_IPC_ISR(void)
    {
        volatile const uint32_t MIS = HWREG(UARTA_IPC_BASE + UART_O_MIS);
    
        if(MIS & UART_MIS_TXMIS) g_uart_err.txmis++;
        if(MIS & UART_MIS_RXMIS) g_uart_err.rxmis++;
        if(MIS & UART_MIS_FEMIS) g_uart_err.femis++;
        if(MIS & UART_MIS_PEMIS) g_uart_err.pemis++;
        if(MIS & UART_MIS_BEMIS) g_uart_err.bemis++;
        if(MIS & UART_MIS_OEMIS) g_uart_err.oemis++;
    
        HWREG(UARTA_IPC_BASE + UART_O_ICR) = 0xFFFFFFFF;
        UART_clearGlobalInterruptFlag(UARTA_IPC_BASE);
        Interrupt_clearACKGroup(INT_UARTA_IPC_INTERRUPT_ACK_GROUP);
    }

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

    尊敬的 Anton:

    有趣的是、让我深入了解一下、然后回到您的身边。

    此致、

    Delaney

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

    尊敬的 Anton:

    对延迟深表歉意。 您是否尝试过将 RX 和 TX 线路作为范围来验证数据看起来是否正确/预期?

    您是正确的;在这种情况下、USB 外设不应直接影响 UART 外设。

    我建议尝试禁用 RX DMA 连续模式、有时这可能会导致时序问题。 您是否能测试某些内容 — 禁用连续模式并保持 USB 启用/运行。

    此致、

    Delaney