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:硬件置位错误

Guru**** 2609895 points
Other Parts Discussed in Thread: CC2640R2F, BLE-STACK

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1257659/cc2640r2f-hardware-assert-error

器件型号:CC2640R2F
Thread 中讨论的其他器件: BLE-STACK

你好!

  在 CC2640R2F 上调试修改后的"simple_peripheral"工程时、我遇到了`hci_BLE_hardware_error_event_code`(使用  simplelink_cc2640r2_sdk_5_30_00_03的 blestack)。  它对应于某些(但不是所有)连接事件。

我相当确定它与堆分配相关。   当我的断点在应用程序` processStackMsg ()`函数内被命中时,使用`HEAPMGR_Metrics `和 MONITORING` heapmgrMemFail`显示了两个分配失败,尽管`heapmgrMemMax `仍然低于堆大小。

按照此页面(链接)上的说明、我将错误代码识别为129、我认为它对应于`hw_fail_out_of_memory`(来自"ll_common.h")

TI 是否能够就该错误的潜在原因/解决方案提供任何指导?  我认为这是一个 blestack 堆问题(因此一种解决方案是降低应用程序的静态 RAM 使用量)、但我想知道为什么不会在每个 连接事件中都发生这种问题?

谢谢!

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

    您好、Kenton:  

    感谢您的答复。 我们将尽快与您联系。  

    谢谢。  

    艾萨克

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

    尊敬的 Kenton:

    如前所述、hw_fail_out_of_memory 意味着堆栈即将耗尽堆内存。

    我建议确保使用最大堆大小(默认情况下应使用自动调整堆大小)。 之后、您可以考虑保存 RAM 的大小(参见 此处 了解一些导联)、增加 RAM 大小分配高速缓存和/或 AUX RAM 的大小(参见 此处 此处)。

    要回答您的问题"我很想知道为什么不会在每个 连接事件上发生"-处理连接事件所需的堆数量实际上可能会因发送和接收的数据包内容而异。 此外、应用程序其余部分消耗的堆可能也会随时间的推移而变化。

    我希望这将有所帮助、

    此致、

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

    感谢您的回复、Clement!

    提出一些后续问题:

    (1)什么决定发送/接收的数据包的大小?  限制因素有哪些?

    作为背景、虽然我有时会将不同的`len`参数传递到SimpleProfile_SetParameter() 函数中、但我始终使用相同的特性进行数据传输。  保证长度<= MAX_PDU_SIZE、并存储在一个全局变量中(我们将其称为"global_length_variable")。

    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, global_length_variable, dataBuffer);

    SimpleProfile_SetParameter()函数内、我清除特征数据、memcpy 将指定的(`len`)字节数转换为`值`:

    memset(simpleProfileChar1, 0, SIMPLEPROFILE_CHAR1_LEN);
    memcpy(simpleProfileChar1, value, len);

    当主机读取此特性(即中的SimpleProfile_readAttrCB())时,我们 运行--

    memcpy( pValue, pAttr->pValue, global_length_variable)

    这些代码部分是否与发送的数据包的大小有关?  我的印象是主机总是只会读取特征的全部值(即、无论`SIMPLEPROFILE_CHAR1_LEN`设置为什么值)。

    (2)我的应用程序代码中没有动态内存分配、因此堆会由 TI-RTOS 和/或 BLE-STACK 代码专门分配。  这些代码库的哪些部分可能会随着时间的推移导致堆使用量变化?  

    再次感谢、

    -Kenton

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

    增加(1)以上内容... 我刚刚发现、如果`global_length_variable`大于(MAX_PDU_SIZE - 6)、我的传输将不会成功。  不过、硬件断言或分配失败、因此这可能是不相关的问题。

    根据 MAX_PDU_SIZE 的值、特征大小是否存在限制?

    谢谢!

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

    您好!

    (1)什么决定发送/接收的数据包的大小?  限制因素是什么?

    通过无线发送的 PDU 的大小将会产生影响。 但图片中也可能包含其他元素、例如每次连接事件中发送/接收的数据包数量。 由于需要更多的本地存储、因此数据包丢失(通过降低可用吞吐量)也会产生影响。

    (2)我的应用程序代码中没有动态内存分配,因此堆将由 TI-RTOS 和/或 BLE-stack 代码专门分配。  这些代码库的哪些部分可能会随着时间的推移导致堆使用量变化?  [/报价]

    一般而言、BLE-STACK 代码应负责这些分配。 但是、这取决于这些元素的使用方式。

    我希望这将有所帮助、

    此致、

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

    谢谢、Clement、

    要确认以下几点:

    1. 假设在特征读取操作期间、外设将始终返回一个  SIMPLEPROFILE_CHAR1_LEN 字节的数据、我的想法是否正确?
      1. 或者`len`参数是否被传递给 SimpleProfile_readAttrCB()并 SimpleProfile_SetParameter()影响发送的数据包的大小?
    2. 您提到了丢包... 这如何提高本地存储的使用率?  是因为需要分配更多缓冲区吗?
    3. 我觉得主机(在我的特定应用程序中) 一次只能读取一次。  是否有办法查看每个连接事件实际发送/接收了多少个数据包? (例如、通过观察 simple_peripheral 项目中的变量或断点?)
    4. MAX_PDU_SIZE 是否对可通过 SimpleProfile_readAttrCB() 和 SimpleProfile_SetParameter() 函数的`len`参数成功设置的最大特征长度施加了限制?
      1. 如果是、为什么限制看起来是(MAX_PDU_SIZE - 6)?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    假设在特征读取操作期间,外围设备将始终返回一个  SIMPLEPROFILE_CHAR1_LEN 字节的数据传输,我是正确的吗?

    恐怕你不是完全正确的。
    首先,即使用特定长度定义特征,两台主机也可以发送不同于预期长度的数据(大于或小于)。 然后设备有可能拒绝该消息(甚至只考虑数据的一个子集)。

    或者`len`参数是否传递给 SimpleProfile_readAttrCB()并 SimpleProfile_SetParameter()影响发送的数据包大小?

    这里,我们同意:)发送的数据包的大小受这些功能的影响。

    您提到数据包丢失... 这如何提高本地存储的使用率?  是因为需要分配更多缓冲区吗?

    低功耗蓝牙连接可在链路层实现数据包丢失检测和重新传输机制(第二种机制可以在 GATT 级别实现)。 这意味着、LL 将在存储器中保留(并重试其传输)一个数据包、直到它被确认。 如果新数据包在前一个数据包传输完成之前排队、则存储器消耗可能会增加。 如果连接间隔大于生成新数据之间的间隔、则也是如此。

    我觉得主机(在我的特定应用程序中) 一次只能读取一次。  是否有办法查看每个连接事件实际发送/接收了多少个数据包? (例如、通过观察 simple_peripheral 项目中的变量或断点?)

    我确认可以链接连接 PDU。 我不知道有一个可在应用级别访问的变量会显示这一点。 但是、您可以使用蓝牙监听器观察此情况。 或者、您可以启用可观察的射频设备(请参阅 此处)、以便您可以查看所有无线电活动、以及查看链接的数据包的接收/传输。

    MAX_PDU_SIZE 是否会对可通过 SimpleProfile_readAttrCB() AND SimpleProfile_SetParameter() 函数的`len`参数成功设置的最大特征长度施加限制?

    MAX_PDU_SIZE 对单个 PDU 中传输的最大数据大小提供了限制。 如果要传输大小大于 ATT_MTU 的 GATT 特性(请参见后面)、则必须在多个 PDU 之间拆分该特性。 如果使用 GATT_WriteLongCharValue 函数、此机制应由任务处理。

    为什么限制似乎是(MAX_PDU_SIZE - 6)?

    答案在下图中或多或少是:)

    您应该考虑到每层添加的标头。

    我希望这将有所帮助、

    此致、

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

    感谢您发送编修。  在我开始了解协议的底层机制时、这非常有用。

    我确实有几个简短的跟进问题...  

    1. 您说过 " LL 将在存储器中保留一个数据包(并重试其传输)、直到它被确认。"  堆栈是否有一种机制可在某一时刻释放此内存? (例如、如果连接已终止、或在特定时间过后?)
    2. 关于"GATT_WriteLongCharValue"函数... 我假设这是主机器件应该使用的东西?  主机是否应该类似地使用"GATT_ReadLongCharValue"函数读取比 ATT_MTU 最大大小更长的特征?  如果是这样、"simple_peripheral"工程是否会将传输自动拆分为多个 PDU?
    3. blestack 文档似乎表明 最大 ATT_MTU 为 MAX_PDU_SIZE - 4"(即 L2CAP 标头大小)。  这似乎与上图不同、该图还包含 LL 接头。  我想知道我在这里遗漏了什么?
    4. 我假设 ATT 标头是1个字节还是3个字节、具体取决于操作是读取还是写入、或者是那不正确?

    再次感谢、

    -Kenton

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

    您好!

    很高兴看到我在帮助你:)

    您说 :"LL 将在内存中保留(并重试其传输)数据包,直到它被确认为止。"  堆栈是否有一种机制可在某一时刻释放此内存? (例如,如果连接已终止,或在经过特定时间后?)

    每当连接终止时,我提到的内存都会被释放。 否则不会释放它(这是蓝牙要求)。

    有关"GATT_WriteLongCharValue"函数... 我假设这是主机器件应该使用的东西?  主机是否应该类似地使用"GATT_ReadLongCharValue"函数读取比 ATT_MTU 最大大小更长的特征?  如果是这样、"simple_peripheral"工程是否会将传输自动拆分为多个 PDU?

    和正确。 GATT 客户端应调用 GATT_ReadLongCharValue"函数、从而读取比 ATT_MTU 最大大小更长的特征。 然后 GATT 服务器的堆栈将处理数据的拆分。

    blestack 文档似乎表明 最大 ATT_MTU 为 MAX_PDU_SIZE - 4"(即 L2CAP 标头大小)。  这似乎与上图不同、该图还包含 LL 接头。  我想知道我在这里遗漏了什么?

    ATT_MTU 提供 ATT 数据的大小(即 PDU 大小- LL 标头- L2CAP 标头)。 为了获得 ATT 有效载荷的可用大小、您必须考虑 ATT 标头的大小(3字节-请见下文)。

    我假设 ATT 标头是1字节还是3字节,具体取决于操作是读取还是写入,还是不正确?

    ATT 标头实际上具有固定的大小(3个字节)。

    此致、