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.

[参考译文] CC2640R2F:无论 MAX_PDU_SIZE 如何、连接到支持 DLE 的 BLE 4.2器件都会导致使用最大接收 PDU 大小

Guru**** 2553260 points
Other Parts Discussed in Thread: CC2640

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/579877/cc2640r2f-connecting-to-ble-4-2-device-with-dle-support-causes-max-receive-pdu-size-to-be-used-regardless-of-max_pdu_size

器件型号:CC2640R2F
主题中讨论的其他器件:CC2640

概述

当 iPhone 7连接到我们的设备时、我们的应用程序似乎会自动通过 LL_LENGTH_REQ 控制数据包作为其第一个业务订单发送。  数据包显示我们的传输数据包大小和间隔是 L2CAP 标准、但接收数据包大小是数据长度扩展的最大值。  iPhone 7以 LL_LENGTH_RSP 响应、表示它可以支持针对 DLE 的最高 Tx 和 Rx 数据长度(数据长度扩展)。  这会导致我们的接收缓冲区大小调整为不必要的大、从而消耗大量堆。  LL_LENGTH_REQ 数据包仍会发送到连接到 iPhone 6s (支持 BLE 4.2、但不支持数据长度扩展)的情况下、但被带有"未知操作码"控制数据包的6s 拒绝、这不会导致我们的应用调整缓冲区大小。  似乎问题不在于 iPhone 7本身、而在于它支持 DLE。  最终、我们要做的是防止发送长度控制数据包、在发送之前"拦截"该数据包并修改其值、或者(如果可能)找出某种方法来设置我们自己的最大 Rx 速率和数据包大小。

详细信息:

在过去几个月中、我们一直在处理与 iPhone 7连接相关的问题。  通过使用 HEAPMGR_metrics 和 HEAPMGR_Profiler、我们确定了导致此问题的原因是堆故障、这就是为什么仅仅添加更多代码就会减少堆的可用存储器。  当 heapmgr.h 堆用完时、分配函数返回 false、并且无法分配指定的对象。  这可能导致连接中断或无响应。  我们调整了一些堆栈大小以避免此问题、从而为我们提供足够的内存来连接到 iPhone 7。  当连接到 iPhone 7时、我们发现 HEAPMGR_MEMMAX 指示堆分配的最高点、它将比 iPhone 6连接后的值大大约1000。

进一步研究、事实证明堆上占用空间最多的对象是通过调用 osal_bufmgr.c 中的 osal_BM_alloc 创建的缓冲区  缓冲区的大小为265 (当它们进入堆时更大一点)、如果堆具有足够的空间、则其中四个缓冲区在 iPhone 7连接期间始终处于活动状态。  如果没有足够的空间供它们使用、应用程序会不断尝试创建它们、如果没有足够的堆、则会导致恒定的堆故障。  当连接终止时、任何现有的缓冲区都会被释放。

当我连接 iPhone 6而不是 iPhone 7时、这些缓冲区会被创建、但大小为41、而不是265。  41 - 27 (最小 LCAP 数据包大小)=大小为14的缓冲器标头、265 - 14 = 251、这是最大数据长度扩展数据包大小。  因此、这些缓冲区似乎是数据包接收缓冲区。  但是、当连接 iPhone 7时、将 MAX_PDU_SIZE 设置为27似乎对接收缓冲区大小没有任何影响。  同样、将 MAX_NUM_PDU 设置为其他值似乎不会影响产生的缓冲区数量。  我不确定是否已禁用数据长度扩展。  在我的 build_config.opt 中、我现在已经注释掉了所有-dv42_features 定义、这是肯定的、但似乎没有帮助。  在 build_config.opt 的注释中、显示"EXT_DATA_LEN_CFG-在控制器中启用扩展数据长度功能(始终启用)"。  这是否意味着无法将其关闭?  或者、如果定义了它、是否意味着无法在运行时禁用它?

我还在由编译运行的 factory_config.opt 中看到行"-dble_V42_feature=V42_features + privacy_1_2_CFG+EXT_DATA_LEN_CFG"。  (此文件有警告、请勿更改它。)  这种定义是否会使 DLE 始终启用?  

如果使用 DLE、文档指出连接应以数据包 MTU 23 (包括 L2CAP 头时、数据包大小为27)和连接间隔328us 开始、并且必须在主设备和从设备之间协商对这些连接参数的更改。

当我们的应用程序收到 GAP_LINK_established 事件时、我们执行的操作之一是调用 GATT_ExchangeMTU。  我们发送的 clientRxMTU 为23、最大 L2CAP MTU 大小。  我们收到一个 ATT_EXCHANGE_MTU_RSP、其中服务器 RxMTU 为23、如果我正确理解 CC2640开发人员指南(http://www.ti.com/lit/ug/swru393d/swru393d.pdf、5.5.2.1)、则表明该连接的 MTU 大小应为23。  我们不会收到 ATT_MTU_Update_event、我假设这是因为 MTU 未从默认值更改、因此连接 MTU 未更新。  无论在 iPhone 7或6上、这种行为都是相同的。

但是、在接收 ATT_EXCHANGE_MTU_RSP 之前、我们还会收到 HCI_BLE_DATA_LENGTH_CHANGE_EVENT。  此事件发生在创建任何265大小的缓冲区之前,并且无论是否启动交换 MTU 过程都将发生。  当我们连接到 iPhone 6s 时、不会生成此事件。  从事件中读取值、我们得到:

maxTxOctets:27.

maxTxReceiveTime:328

maxRxOctets:251

maxRxReceiveTime:2120

查看监听器日志、我在连接开始后立即找到了 LL_LENGTH_REQ 和 LL_LENGTH_RSP 数据包。 (我之前忽略过这一点、因为 SmartRF 数据包监听器2.18.1.0显然不会自动标记 LL_LENGTH_REQ 和 LL_LENGTH_RSP 数据包;这些数据包只是显示为"控制"数据包、我必须双击数据包并选择"数据包详细信息"以查看数据、以防其他人进入此数据包)。  我们发送的 LL_LENGTH_REQ 具有与 HCI_BLE_DATA_LENGTH_CHANGE_EVENT 中相同的值、而 iPhone 7以可能的最大 Tx 和 Rx 数据包大小进行响应。  这会导致上面列出的值、因为使用了 Tx 和 Rx 的最小互值。  当连接到 iPhone 6s 时、此数据包仍会发送。  6s 支持 BLE 4.2、但不支持数据长度扩展、并使用"未知操作码"对控制数据包进行响应。  在连接期间、接收缓冲器保持 L2CAP 数据包大小。

使用 CCS 中的 Modules 视图并在函数 lSetupLenCtrlPacket()上设置断点,我发现在设置初始 Rx 缓冲区(使用 lCreateRxBuffer 进行跟踪)之后(很快就会在 GAP_LINK_established _event 之后)调用该断点。

因此、这里的问题似乎在于 LL_LENGTH_REQ 数据包的传出值、我们似乎找不到任何方法来使用定义或常量来控制这些值。

很抱歉、这里的帖子很长;这是我们一直在尝试破解的内容、因为 iPhone 7的额外堆使用限制了我们添加新功能。  我们非常感谢您的任何帮助或想法!

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

    您能不能查看我们的客户在 iPhone7上针对 CC2640R2遇到的以下问题。

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

    谢谢、Omid!

    我们通过跟踪用于填充 LL_LENGTH_REQ 数据包的值的原点、设法使其正常工作。  在存储器中、L2CAP 值后跟 DLE 值的两个副本:

    1B 00 48 01 FB 00 48 08 FB 00 48 08 (23、328、251、2120、251、 2120)

    因此、我们扫描这些显示在中的存储器范围、并在应用程序任务初始化时替换它们、从而:

    1B 00 48 01 1B 00 48 01 1B 00 48 01 (23、328、 23、328、 23、 328)

    这是代码。  当然、在运行时修改栈使用的内部变量由您自行承担风险。  我认为在这种情况下、将 DLE 值替换为 L2CAP 值应该是可以的、因为 L2CAP 值对于使用数据长度扩展的连接有效、并且该连接最初配置为使用这些值。  您应该确保使用的存储器范围与您的配置相对应、并且这些值实际上以正确的格式出现在该存储器范围中。

    //要扫描的内存中的字节范围

    #define MIN_DLE_bytes_ADDR 0x20000000

    #define MAX_DLE_bytes_ADDR 0x2000FFFF

    #define DLE_Bytes 0x084800FB

    #define L2CAP_Bytes 0x0148001B

    内联 bool fixDleBytes( void ){

      //扫描存储器范围、找到字节

      对于(int* i =(int*) min_DLE_bytes_ADDR;i <=(int*) MAX_DLE_bytes_ADDR;i++){

        //确保我们具有准确的字节序列

        if (* i =L2CAP_Bytes &&*(i+1)=DLE_Bytes&&*(i+2)== DLE_Bytes){

          //将最大 DLE 值替换为 L2CAP 值

          *(i+1)= L2CAP_Bytes;

          *(i+2)= L2CAP_Bytes;

          返回 true;

        }

      }

      返回 false;

    当然、这并不理想、最好有一种更易于访问的方法来限制数据包数据长度。

     

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

    您可以使用 HCI_EXT_SetMaxLenDataCmd 供应商扩展命令覆盖用于响应 LL_length_Req / LL_length_RSP 中最小/最大八位字节/时间的控制器(LL)默认值。 有关 DLE、请参阅软件开发指南部分中的用法:
    software-dl.ti.com/.../index.html

    还请注意、ATT_MTU 大小(源自 MAX_PDU_SIZE)不直接与 LL PDU 大小绑定、但为了高效传输数据、ATT_MTU 应设置为与 LL PDU 相同的大小。

    如果您正在发送通知和/或指示、则无需分配 ATT_MTU 的全部大小、但是、发送数据时不能超过 MTU 的最大大小。

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

    JXS、

    非常感谢您花时间帮助我的客户!

    尊敬的、

    Omid

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

    您好 JXS、在查看所有这些 API 头文件时、我们忽略了此函数。 (我还没有在我的所有 Google 搜索中找到您链接的文档、它将非常有用、可供将来参考。) 由于某些问题阻止我们连接调试器、我目前还无法验证这一点、但我接受这一点、因为它可以正常工作!

    感谢您的帮助!