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.

[参考译文] CC2340R5:启用 BLE 时 UART Rx 缺少字节

Guru**** 2419530 points
Other Parts Discussed in Thread: CC2340R5, SYSCONFIG

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1537394/cc2340r5-uart-rx-missing-bytes-when-ble-is-enabled

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

工具/软件:

我的客户正在尝试在 CC2340R5 上开发高性能 UART 转 BLE 桥接器应用。 设计目标是在 460800 波特率下稳定工作。 为了提高环形缓冲器用于存储接收到的 UART 数据的性能、BLE 应用将从该环形缓冲区重试数据并通过 BLE 通知发送到对等设备。

应用程序在 115200 波特率下运行正常、但当波特率增加到 460800 时、UART Rx 端会显示缺少的字节。

  • 这些字节直接从 UART Rx 缓冲区丢失。 CC2340 UART 从不接收这些字节。 这是通过 UART 回调中接收的字节计数进行验证的。
  • 如果未使用 BLE 和环形缓冲器(仅接收 UART 数据但未将其放入环形缓冲区)、则不会发生问题。
  • 如果使用环形缓冲器但未使用 BLE(将接收到的数据放入环形缓冲器,但不通过 BLE 通知发送)、则问题仍然发生。

客户有一个项目要重现此问题(请离线联系我以处理该项目)。 要重现此问题、请按照以下步骤操作:

  1. 在 CC2340R5 LaunchPad 上运行工程。
  2. 连接到手机。
  3. 从电话请求 247 字节的 MTU。
  4. 启用电话通知。
  5. 使用 460800 波特率打开 UART 终端 (hTerm)。
  6. 通过 UART 向 CC2340 发送文件(我创建了一个 100KB 示例文件,如下所示)。
  7.  在 CCS 监视窗口中观察 uart_received_bytes。

重复步骤 6 和 7 并观察  uart_received_bytes 变量、每次 UART 终端向 CC2340 发送 100,000 个  字节、每次 UART_received_bytes 都比发送的字节少一个或两个字节。

e2e.ti.com/.../test_5F00_100kb.bin

这个问题看起来与中断优先级或 DMA 传输有关、但我在找到问题的确切位置时遇到了问题。 我已经尝试调整 UART HWI 优先级和 UART 振铃缓冲区大小、但两者都没有区别。 请帮助找出根本原因吗? 谢谢。

此致、

Shuyang

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

    尊敬的 Shuyang:

    使用的是哪个 SimpleLink F3 SDK 版本?  您是否能够在未初始化 BLE 的 TI 驱动程序工程中复制此行为、或者是否存在 BLE 堆栈/连接是复制问题所必需的?  您尝试过哪些 UART 环形缓冲区大小?

    此致、
    Ryan

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

    您好、Ryan、

    SDK 版本为 simplelink_lowpower_f3_SDK_9_10_00_83。

    我执行了两项测试来验证 BLE 栈是否必不可少:

    1. BLE 正在广播、但无连接、UART 回调将接收到的数据放入振铃缓冲区、但 BLE 任务不发送 — 问题仍然可以重现。  

    2. BLE 未广播或未连接、 UART 回调将接收到的数据放入 环缓冲区、BLE 任务从环缓冲区重试数据,但对此不做任何处理 — 问题不会发生。

    BLE 活动对于问题的发生似乎至关重要。

    UART 振铃缓冲区大小为 256 (Rx) 和 32 (Tx)。

    下一步调试是什么? 由于 BLE HWI 始终具有最高优先级、是否有办法避免 UART 在 Rx 端丢失任何字节?

    此致、

    Shuyang

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

    尊敬的 Shuyang:

    这并不是用户第一次注意到使用 UART2 TI 驱动程序时缺少字节。

    https://e2e.ti.com/f/1/t/1430261 
    https://e2e.ti.com/f/1/t/1363778 

    以下是我目前的想法:

    • UART 外设接收 FIFO 的长度为 8 个条目
    • UART2 TI 驱动程序 实现了 DMA 为基本模式(即不是乒乓模式或任何其他模式)
    • 当 整个 DMA 传输完成 (UART2LPF3_hwiIntRead) 时 、有一段时间可以停止 DMA RX 事务 (UART2Support_dmaStopRx)、以便在重新启动 DMA RX 事务 (UART2Support_dmaStartRx) 之前进一步处理传入的数据状态
    • 在此期间、当 DMA RX 事务暂停时、涉及一个竞态条件以确保 RX FIFO 不被填充
    • 鉴于 BLE 栈广播的波特率增加和优先级更高、FIFO 在此期间可能会在  UART2LPF3_hwiIntRead 内溢出、从而导致丢失的字节。

    如果该理论正确、那么您将能够使用 UART2LPF3_hwiIntRead 中的关键部分来避免在此时间敏感期内发生 BLE 栈活动:

    /*
     *  ======== UART2LPF3_hwiIntRead ========
     *  Function called by Hwi to handle read-related interrupt
     */
    static void UART2LPF3_hwiIntRead(uintptr_t arg, uint32_t status)
    {
        UART2_Handle handle              = (UART2_Handle)arg;
        UART2LPF3_HWAttrs const *hwAttrs = handle->hwAttrs;
        UART2LPF3_Object *object         = handle->object;
        void *readBufCopy;
        unsigned int key;
    
        // Enter critical section.
        key = Hwi_disable();
    
        /* Temporarily stop RX transaction */
        UART2Support_dmaStopRx(handle);
    
    //...
    
        /* Start another RX transaction */
        UART2Support_dmaStartRx(handle);
        
        // Exit critical section.
        Hwi_restore(key);
    }

    我无法确定这将对 BLE 栈产生的影响、因为这会主动阻止它发送调度的广播。  请尝试我的建议(使用尽可能大的环形缓冲器,以尽可能减少临界区中断)、但请记住这可能对进一步的 BLE 活动产生的影响(例如有效连接期间的数据包发送/接收)。

    此致、
    Ryan

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

    您好、Ryan、

    添加临界部分后、问题仍然出现。 我做了几次测试、行为和以前完全一样。 还有其他事项需要考虑吗? 如果你能帮助你重现它会更好。

    此致、

    Shuyang

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

    您好、Shuyang、

    请帮助我解决以下问题。

    1. 您使用的 UART RX 缓冲区最大大小是多少? 我认为、如果问题是某种类型的溢出、增加缓冲区大小有助于缓解这种情况。 您是否尝试过分析 params.eventCallback = NPITLUART_eventCallBack;以包含 params.EventMask |= UART2_event_overlulation;并检查是否满足此条件?
    2. 什么是 Adv/conn 间隔、您是否尝试过更长的间隔并看到影响?
    3. 您能否分享工程中如何使用 UART 驱动程序的代码片段? 您使用的是 Display UART、还是定义了另一个?

    谢谢。

    David。

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

    尊敬的 Shuyang:

    您能否将 SysConfig 电源策略设置为“doWFI",“,以便、以便我们可以确认电源约束/依赖项没有发挥作用?  是否有办法确定 缺少 100 KB 文件中的哪些字节(即开始,中间,结束)?

    此致、
    Ryan

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

    您好、David:

    1. UART Rx 振铃缓冲区大小为 256 字节、应用程序振铃缓冲区大小为 2048 字节。 我没有注册回调、但在 CCS 调试模式下检查了溢出位、没有观察到溢出。 稍后我将添加回调。

    2.高级间隔为 100ms,连接间隔为 30ms。 会尝试更大的值。

    3、项目离线发送。 我使用的是 UART2 驱动程序、而不是显示驱动程序。

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

    您好、Ryan、

    我将尝试 WFI。

    我没有找到一种很好的方法来定位丢失的字节、我在 Rx 回调中添加了一些代码、以通过 UART 发回最后一个字节。 添加代码后、我发现问题可能发生在 2048 字节附近、即应用程序振铃缓冲区已满时。

    但我发现此 Tx 代码实际上增加了问题发生的机会、因此我不确定它是否本身引入了问题。

    如果没有 Tx 代码、100,000 字节中将会漏掉 1 到 3 个字节、因此很难确切地判断位置。

    此致、

    Shuyang

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

    如上所述、我发现  OE 位设置为 1 后 RSR_ECR 寄存器不会被清除。 我想就这一发现提供更多的细节、因为我不确定这是一个问题、还是只是我的执行情况。

    与 TRM 一样、一旦 FIFO 中有空空间、RSR_ECR 中的 OE 位就应清除为 0:

    但是、我发现一旦设置为 1、它就不会被清除、即使 RXFE 为 1、这意味着 FIFO 为空:

    这使得超限计数保持为 1、因为当 RSR_ECR.OE 为 1 时、不会再次调用超限中断。

    若要清除 OE 位、我在  UART2LPF3_hwiIntFxn 中添加了一些代码来清除此位:

    手动清除 OE 中断后、OE 中断能够再次被触发。

    我不确定这是硬件问题、还是只是对 TRM 的误解、您能帮忙确认吗?

    此致、

    Shuyang

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

    1.使用 doWFI — 问题仍然发生。

    2.将 UART Rx 振铃缓冲区大小增加到 20480 — 问题仍然发生。

    [/报价]

    好的、因此不会出现低功耗进入问题(符合预期)、 MAX_DMA_SIZE = UDMA_XFER_SIZE_MAX = 1024、因此 UART RX 振铃缓冲器将受到该值的限制。

    我对溢出位不太了解、但根据您的分析、似乎需要手动清除、这与 TRM 相矛盾。

    此致、
    Ryan

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

    您好、Ryan、David、

    我想我已经找到了此问题的根本原因。 这是由 UART 溢出导致的。

    首先、向 UART2LPF3_hwiIntRead 添加关键部分有助于消除  UART2LPF3_hwiIntRead 被更高优先级 HWI 抢占的情况(尽管由于我将在下面详细说明的原因,它没有完全消除它)、从而提高性能。

    但添加临界段后仍然可能发生 UART 溢出、因为可能会在 发生 UART2LPF3_hwiIntFxn 之前立即调用 RF_commandHwi。 为了验证这一点、我在 UART2LPF3_hwiIntFxn 和 RF_commandHwi 内添加了 GPIO 切换。 从逻辑布线中、我们可以看到 UART2LPF3_hwiIntFxn 由于被 RF_commandHwi 抢占而延迟:

    为了进行比较、调用 UART2LPF3_hwiIntFxn 的 UART2_READ 的常规间隔为 5.21ms、当问题发生时、间隔会延迟至 5.34ms。 这与 RF_commandHwi 执行的周期 (150us) 相匹配。

    波特率为 460800 时、该周期 150us 等于 7 个字节的传输时间、在此期间 UART Rx 无法启用。 因此、当下一个 UART_READ 被调用时、UART Rx FIFO 已满、导致发生溢出。 这也解释了较低波特率下不会出现该问题的原因。

    由于 RF_commandHwi 必须保持最高优先级、因此我想没有办法使用当前 UART DMA 实现完全消除该问题。 使用 DMA 乒乓模式似乎很普及、因为它可以实现连续数据传输、您认为这是一个好主意吗?

    PS: 如果临界区未完全消除抢占、这是因为我在当前实施中发现了一个小问题。 UART 回调调用 BLEAppUtil_invokeFunctionNoData、后者调用 pvPortMalloc 以从堆中分配内存、而 pvPortMalloc 调用 xTaskResumeAll、后者  对关键部分使用 taskEnter_Critical 和 taskEXIT_critical。 这些 API 并不用于 ISR 上下文、因此它们会意外启用全局中断。 虽然稍后的 HwiP_disable 调用将很快关闭全局中断、但此调用确实增加了 HWI 被更高优先级 HWI 抢占的可能性。

    此致、

    Shuyang

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

    尊敬的 Shuyang:

    感谢您对该问题的深入分析。  更高的 UART 波特率、射频操作和 DMA 基本模式的组合会创建一个临界情况、在当前条件下这是不可避免的。  通过进一步了解所涉及的限制、主机可以在每  1024 个 字节发送之间插入一个短暂的暂停、这样仍然允许更高的波特率、同时 只短暂延迟整体传输。  否则、肯定需要进一步开发 DMA 乒乓模式选项、您可以将 ADCBuf TI 驱动程序作为已使用的解决方案。

    此致、
    Ryan

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

    Ryan Brown1 是否有关于此问题的任何更新?

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

    嗨、Linjie、

    我不知道需要我采取哪些行动来提供最新信息。

    此致、
    Ryan