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.

[参考译文] MSPM33C321A:当配置为可变长度接收时、UART DMA 接口错过了最后一个字节

Guru**** 2966500 points

Other Parts Discussed in Thread: SYSCONFIG

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1660821/mspm33c321a-uart-dma-interface-misses-last-bytes-when-configured-for-variable-length-reception

器件型号: MSPM33C321A
主题: SysConfig 中讨论的其他器件

尊敬的团队:  
我对使用 MSPM33C321x 上的 RX 超时触发器进行 UART DMA 接收有疑问。
 
我正在实现可变长度 UART 接收、并按如下方式配置了 DMA:
  • DMA 触发源:UART RX 超时
  • DMA 传输大小:最大接收缓冲区大小
  • 数据包长度:可变
  • 我的超时计数设置为 15。
在测试期间、我观察到当接收到一个数据包时、RX 超时事件发生在 DMA 传输最后一个字节之前。 因此、DMA 缓冲区中的最后一个字节似乎缺失。
 
我还检查了当发生 RX 超时中断时、UART RX FIFO 中是否有任何数据剩余、但 FIFO 为空。  
此外、还尝试将 RX FIFO 阈值电平设置为>=1/4 满和 1/2 满、未成功。
 
您能否澄清 RX 超时 DMA 触发的预期行为?
 
具体来说:
  • RX 超时事件是否预计会在 DMA 将最后一个字节传输到存储器之前发生?
  • 当 RX TIMEOUT 用作 DMA 触发源时、是否应该在超时事件生成之前已经传输最后一个字节?
  • 是否有建议的方法通过 DMA 接收来处理可变长度的 UART 数据包?
  • 是否有任何已知限制或示例工程使用 DMA 和 RX TIMEOUT 演示可变长度 UART 接收?
在我的当前设置中、我始终观察到 DMA 缓冲区中的字节比发送的字节数少一个、这表明当发生超时事件时、最终字节可能仍在 UART 接收路径中。
 
请提供任何指导。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    嗨、Rajeshwary、

    RX 超时事件应视为在配置的超时内未接收到额外的 UART 字符。 不应将其视为对接收缓冲区的所有待处理 DMA 写入均已完成的保证。 如果选择 RX 超时作为 DMA 触发、则超时事件本身可能是针对 UART 接收路径中剩余字节/数据启动 DMA 请求的事件。 因此、软件可以在存储器中看到最终 DMA 写入之前观察到超时情况。

    对于可变长度 UART 接收、我们建议使用正常的 UART RX DMA 触发器将传入字节移动到 DMA 缓冲区中、并使用 RX 超时作为数据包结束指示。 超时时时时、应用程序应停止/同步 DMA 通道、读取剩余 DMA 传输计数、计算接收到的长度、然后处理缓冲区。

    换句话说、RX 超时可用于检测可变长度帧的结束、但不应将其单独用作 DMA 缓冲区已完成的证据。 此外、仅靠 FIFO-EMPTY 状态不足以确认数据已提交到 SRAM、因为在存储器写入/计数更新仍处于挂起状态时、DMA 可能已从 FIFO 中删除了该字节。

    还请确保在超时触发的 DMA 请求完成之前、应用程序没有禁用 DMA 通道或清除超时/DMA 事件。 如果 ISR 在 RX 超时时立即禁用 DMA、则可能与最终的 DMA 传输争用。

    我们建议使用启用 UART RX DMA 触发器进行测试、以实现正常接收、并使用 RX 超时中断来分隔数据包。 MSPM33 SDK 还包括 UART RX 多字节 FIFO DMA 中断示例、它们可用作基于 DMA 接收的 UART 的起点。

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

    您好 Jojo、

    我尝试了使用 UART RX DMA 触发器将传入字节移动到 DMA 缓冲区中并使用 RX 超时作为数据包结束指示的建议方法。
    我将 DMA 传输大小配置为 64 个字节、而实际的 RX 数据包大小当前为 5 个字节。 但是、当我使用 DL_DMA_getTransferSize (DMA0、DMA0_CH1_CHAN_ID) API 读取 DL_UART_INTERRUPT_RX_TIMEOUT_ERROR 中断中的剩余 DMA 传输计数时、返回值为 0 而 不是 5。 我还检查了 DL_UART_IIDX_DMA_DONE_RX 中断中的传输计数、并观察到相同的结果、计数仍报告为 0。
    我将连接我的 UART 和 DMA 配置以供您参考。
    请注意、我能够使用 DMA 接收固定数量的字节。 但是、我的应用程序接收多个具有可变长度的命令、我需要一种可靠的方法来确定接收到的实际字节数。 我希望能迅速得到解决、因为这是一个紧迫的问题。

    以下是用于 在 DL_UART_INTERRUPT_RX_TIMEOUT_ERROR 中断中读取 DMA 传输大小的代码补丁

    define MPESTI_T_DMA_RX_WINDOW 64U
    //用于读取 DMA 传输大小的补丁
         DL_DMA_disableChannel(DMA0、DMA0_CH1_CHAN_ID);
      
           剩余易失性 uint32_t;
          易失性 uint8_t dmaReceived;
          
          /* RX 超时表示 DMA 模式下的帧边界。 */
           Remaining = DL_DMA_getTransferSize (DMA0、DMA0_CH1_CHAN_ID); =>将大小返回为零
          dmaReceived = MPESTI_T_DMA_RX_Window - remaining;
          target->Nwk.rxLen = dmaReceived;

    此致、

    Rajeshwary

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

    嗨、Rajeshwary、

    感谢您的更新和 SysConfig 屏幕截图。 使用 UART RX 中断作为 DMA RX 触发器并将 RX 超时作为帧边界的新方法是正确的方向。

    需要检查的几个事项:

    在单次传输 DMA 模式下、DMA 传输大小为 64 表示在 DMA 块完成之前需要 64 个 UART RX 触发事件。 如果实际接收到的数据包为 5 个字节、则预期剩余计数将为 59、而不是 5。 然后、接收到的长度将为 64 - 59 = 5 个字节。

    2.在禁用 DMA 通道之前,请先读取 DMA 传输大小。 在代码补丁中,在调用 DL_DMA_getTransferSize () 之前禁用 DMA 通道。 禁用 DMA 通道可能会影响实时通道状态、因此应首先捕获计数。

    3.屏幕截图显示“配置传输大小“未选中。 如果 SysConfig 未设置传输大小、请确保应用程序每次在启用 DMA 通道之前调用 DL_DMA_setTransferSize (DMA0、DMA0_CH1_CHAN_ID、64)。

    4.另请确认 RX DMA 目标地址在每次传输后递增。 对于 UART RX DMA、源地址应在 UART RXDATA 中保持不变、但目标地址必须递增、这样每个接收到的字节都会存储到下一个缓冲区位置。

    作为使用 DL_DMA_getTransferSize () 的替代方法,我们建议在 RX 超时读取当前的 DMA 目标地址并计算接收的长度,如下所示:

    rxLen =当前 DMA 目标地址 — RX 缓冲区的起始地址

    这样可以避免在 DMA 通道禁用后或 DMA 完成后读取传输大小寄存器的模糊性。

    建议的超时处理顺序:

    -禁用 UART RX DMA 事件以防止新的 DMA 请求
    -读取 DMA 目标地址或传输计数
    -计算 rxLen
    -为下一个数据包禁用/重新布设 DMA 通道
    -启用 Re RX DMA 事件

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

    您好 Jojo、

    我尝试了使用建议的超时处理顺序、将 DMA RX 触发源作为 UART RX 中断。 不过,我总是收到 DL_DMA_getTransferSize () 输出为 0。 我在 RX 超时中检查了 DMA 目标地址 、如下所示

    当前 DMA 目标地址= 0x3000800D

    RX 缓冲区的起始地址= 0x30007FCD

    rxLen = 64。

    一旦我将 DMA 触发源移至 UART RX 超时中断 、我总是收到 DL_DMA_getTransferSize () 输出 4 和  

    当前 DMA 目标地址= 0x30007FD1

    RX 缓冲区的起始地址= 0x30007FCD

    rxLen = 4。

    您是否尝试过建议的解决方案? 您能为我提供测试代码吗?

     需要快速解决该问题。

    此致、

    Rajeshwary

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

    嗨、Rajeshwary、

    感谢您提供更多数据。 目标地址值非常有用。

    选择 UART RX DMA 触发器后、目标地址从移动 0x30007FCD 到 0x3000800D、这是一个 64 字节的差异。 这表明 DMA 通道完成了完整的 64 字节接收窗口、而不是 5 字节数据包。 因此、在该设置中、未在 5 字节帧边界捕获超时。

    TRM 中的一个要点是、仅当接收 FIFO 不为空且在超时期间没有收到更多数据时、RX 超时才会被置为有效。 如果 RX FIFO 阈值配置为 RX FIFO contains >= 1 entry、则 DMA 可以在到达时立即耗尽每个字节。 在这种情况下、FIFO 在帧结束时可能为空、因此 RX 超时不是可靠的帧边界指示器。

    例如、请尝试将 RX FIFO 阈值设置 RX FIFO contains >= 1/2 full得更高、并将 DMA RX 触发器保持为 UART RX 中断。 通过此设置、DMA 处理批量数据、RX 超时用于处理 FIFO 中剩余的字节。 在 RX TIMEOUT ISR 中、禁用 UART RX DMA 触发、读取当前 DMA 目标地址以确定 DMA 已移动了多少个字节、然后手动将剩余的字节从 UART RX FIFO 排入缓冲区中。 数据包长度为:

    rxLen = (current DMA destination address - RX buffer start address) + residual FIFO bytes drained by CPU

    当 DMA 触发更改为 UART RX 超时时时、观察到的 4 个字节长度与超时事件一致、仅耗尽当前 FIFO 的内容。 不建议使用该模式来接收大于 UART FIFO 深度的任意可变长度数据包。

    此外、我建议改用 DMA 目标地址加上剩余的 FIFO 漏极数。