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.

[参考译文] CC2652R:当在 iCall_createRemoteTasks 之前进行内存分配时、蓝牙堆栈不工作

Guru**** 2587365 points
Other Parts Discussed in Thread: LAUNCHXL-CC26X2R1

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1387403/cc2652r-bluetooth-stack-does-not-work-when-memory-allocations-are-made-before-icall_createremotetasks

器件型号:CC2652R
主题中讨论的其他器件:LAUNCHXL-CC26X2R1

工具与软件:

您好、TI!

我在使用 名为"DMM 15.4 Collector + BLE 远程显示"的 DMM 示例时遇到了一个奇怪的问题。  我正在使用中   LaunchXL-CC26X2R1 和  Simple Link SDK 7.40.0.77

在蓝牙堆栈初始化之前、我需要分配并使用一些动态分配的内存。 这会导致一个问题-示例代码停止工作、并且可能会进入一些有效的处理程序(不显示日志、蓝牙不再广播、UART 控制台不响应输入)。 此处、您可以看到一个简单的示例、该示例演示了如何触发问题:

  /* Update User Configuration of the stack */
  user0Cfg.appServiceInfo->timerTickPeriod = Clock_tickPeriod;
  user0Cfg.appServiceInfo->timerMaxMillisecond  = ICall_getMaxMSecs();

#ifdef BLE_START
  /* Initialize ICall module */
  ICall_init();

  uint8_t *data = ICall_malloc(8196);
  if(NULL != data) {
      memset(data, 0xAB, 8096);

      ICall_free(data);
  }

  /* Start tasks of external images */
  ICall_createRemoteTasks();
  pBleTaskHndl = ICall_getRemoteTaskHandle(0);

  RemoteDisplay_createTask();

如上所示、我正在分配相当大的存储器块并将其设置为0xAB 的值(这非常重要!)。 该存储器立即被取消分配、但存储器值仍为0xAB -这会导致无线电 MCU 停止正常运行。

但是、如果我修改 memset 以将此内存区域设置为0x00、则一切都将正常运行、就像什么都没有发生一样。 这最终导致在蓝牙初始化之前无法分配和使用任何存储器。

问题:

  1. 我还没有看到过任何提到在蓝牙初始化前不能使用 iCall_malloc 的文档-是正确的吗? 在调用 iCall_createRemoteTasks 之前使用 iCall_malloc 吗  
  2. 为什么蓝牙堆栈不能抗扰动态分配块中的初始存储器值? 这似乎是 一个错误
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Michal、

    感谢您的咨询。 请帮助我以下帮助您进一步帮助您:

    1. 您能否说明您从对讲机收到了什么错误或哪些功能停止工作?
    2. 您能否使用 运行时对象 查看器来查看是否存在堆损坏问题?
    3. 您在使用 SDK 中的什么示例?

    BR、

    David。

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

    感谢您的答复。 以下是您其他问题的答案:

    1. 更加精确-当在初始化栈之前(但在 iCall_init 之后-请参阅简介帖子中的代码)完成内存分配后、将使用该分配的内存(因此它不再具有值0x00)并释放、因此 TI BLE5堆栈随后使用相同的内存区域时、它会导致无线电 MCU 在尝试建立蓝牙连接时立即停止所有操作 (尝试使用手机连接到开发套件)
    2. 当然有! 这是 ROV 捕获-请告诉我您想看到什么。 在这里您可以看到、我们现在位于 HWI 错误处理中-无线电 MCU 不再工作


      这看起来不像是存储器损坏-在分配的存储器之外不会进行访问。 我不确定是否可以在不对 SYSCFG 进行任何进一步修改的情况下轻松检查存储器损坏、这可能会改变测试环境
    3. 我正在使用  名为"DMM 15.4收集器+ BLE 远程显示"的 DMM 示例- dmm_154collector_remote_display_app_2_4g_CC26X2R1_LAUNCHXL_tirtos7_ticlang

    只是为了确保我的消息被传递:

    • 如果将内存区域设置为任何非零值、则无线电 MCU 完全停止工作并进入 HWI 处理程序
    • 如果将内存区域设置为零值、则无线电 MCU 可以正常工作

    这让我怀疑 BLE5堆栈内部为自身分配了一些内存、而没有将其初始化为预期值、但假定 iCall_malloc 返回的整个内存区域使用0x00值进行初始化(可能为真、也可能不为真)。 在本例中、蓝牙堆栈会返回一个指针、指向值为0xAB 而不是0x00的存储器区域。 原始帖子中的6行代码是我为触发该问题而对样本进行的唯一修改  

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

    您好、Michal、

    感谢您提供额外的信息。 我想问一下、为什么需要分配这么大的内存量? 您能告诉我您返回的数据指针的地址是什么吗? 使用本指南来 调试内存问题可能会很有用。 此外、使用自动堆大小功能时、您有大约8839字节、因此可能会覆盖栈使用的一些参数(为什么我要问指针地址)。

    BR、

    David。

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

    在此示例代码中分配8k 内存仅用于模拟我的实际项目-在初始化蓝牙堆栈之前进行了大量内存分配。 因此、在上面的代码中、这共同模拟了一个以前使用但现在可用且可由(可能)蓝牙堆栈使用的 RAM 区域。

    返回指针的地址为: 0x200072C8

    我对  您提到的8839字节限制感到非常困惑。 限制从何而来? 出于对同一个样本的好奇、我决定尝试分配更多内存(10k 字节)、这完全没有问题-没有返回 NULL 指针。 甚至更多,我决定打印堆统计,它看起来"有点更多"比8k 可用. 在下面的屏幕中、您可以看到从调试中捕获的内容-堆统计信息和分配的地址都是可见的:

    此外、我还查看了生成的.map 文件、此处是我的 heapStart 和 heapEnd symobls:

    20013600 HeapEnd
    200071d8 HeapStart

    当为堆计算内存区域时(按照你提供的链接中的计算方法)、我获得了与 Get heap stats 功能返回的值相同的值: 50216

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

    您好、Michal、

    您能否分享一下与堆消耗相关的 ROV 结果? 调试常见的堆问题

    您能尝试将分配拆分成多个分配吗?

    BR、

    David。

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

    我很抱歉,但我觉得我们什么都没有。 为了解决这个问题、让我重申一下如何重现它–触发它非常简单、因此我希望您可以在结束时进行、并根据需要收集尽可能多的信息和分析数据。

    如何导致 TI BLE5栈行为异常:

    1. 将支持 DMM 的样片从 TI SDK 导入工作区。 使用以下示例工程:dmm_154collector_remote_display_app_2_4g_CC26X2R1_LAUNCHXL_tirtos7_ticlang
    2. 打开位于"application"目录中的"main.c"文件
    3. 导航至第334行或找到"iCall_init ();"函数调用
    4. 插入以下5行代码、使示例 main.c 文件如下所示:
      uint8_t *data = ICall_malloc(8192);
      if(NULL != data) {
          memset(data, 0xAB, 8192);
          ICall_free(data);
      }
    5. 在支持的开发板上构建和启动示例项目
    6. 使用您喜爱的蓝牙调试应用程序连接到开发板
    7. 观察电路板进入 HWI 错误处理程序并停止任何操作

    我已经尽力将问题分到您的示例项目中、并找到它导致 TI BLE5堆栈行为错误的确切时刻。 请尝试重新创建它并亲自查看。

    存储器损坏理论:

    如果将自动堆大小功能限制为仅8839字节的堆、这是完全错误的。 我不知道你从哪里得到这些信息(因为你没有回答我的问题)、但它可能会误导阅读此线程的任何人。 如果是这样、TI BLE5堆栈启动后就不会留下任何存储器、但显然情况并非如此、因为 TI15.4堆栈可在 BLE 堆栈之后启动、并且无需出现任何问题即可获取所有必需的存储器、而且仍有足够的存储器留给用户应用。

    再次说明一下-请向我提供8kB 限制信息的来源

    我的理论关于蓝牙内存损坏:

    但是、在您提出的问题中、我们找出了在启动 ICall 远程任务之前8kB 内存分配为何会导致 TI BLE5堆栈出现故障的原因。 如果用户决定在调用"iCall_createRemoteTasks"之前和之后分析内存消耗、他们将看到 TI BLE5堆栈分配大约8kB 的堆。

    因为 I:

    • 分配了8kB
    • 修改了该区域的内存
    • 释放了该区域

    这意味着 TI BLE5栈会返回一个不再用0x00值填充、而是之前设置到该存储器的任何值的存储器区域。 如果在创建 ICall 远程任务之前未进行分配、则 TI BLE5堆栈会在重新启动后获取包含0x00值的内存区域。 这看起来像是 TI BLE5堆栈实现中的一个错误–它分配一个内存并假定(错误地)返回的区域中填充了0x00值。 不是。 当然、在 TI 示例项目中、在创建 ICall 远程任务之前没有进行分配、但 TI 文档中没有任何内容(至少我找不到这样的内容)、其中指出在创建 ICall 远程任务之前禁止分配和释放内存。

    如果用户尝试分配一个小于8kB 的区域并使用随机数据填充该区域、则不会发生蓝牙损坏、因为该区域的某些部分仍被填充为0x00、这正是 TI BLE5 Stack 的预期。

    如何进行:

    • 请尝试重新创建该问题。 我确保它易于重现并与您的示例项目分离。
    • 我可以尝试将分配分成8个1KB 的块、结果仍然相同。 如果 TI BLE5 Stack 返回动态分配的存储器区域、该区域未填充0x00值、则将中断。
    • 我确信同样的行为可以通过更改链接器脚本来触发、从而使用随机数据(而不是0x00值)初始化 RAM 中的堆区域-我不是连接器专家、我不会再尝试它

     

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

    您好、Michal、

    感谢您提供详细的步骤和信息、并对困惑感到抱歉、我的价值观完全错误、我将确保根据您使用的示例澄清这一点。 感谢您指出这一点。

    我正在研究这个问题。 到目前为止、我无法在仅使用 BLE 的工程(例如 simple_peripheral)上重现该问题、因此我认为可能涉及 DMM 或其他协议存在问题。 如果我遗漏了一些东西、我也会与团队一起回顾。 我将在今天报告我的调查结果。

    BR、

    David。

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

    您好、Michal、

    经进一步检查、我们发现问题来自以下事实:先前分配的存储器空间(例如、通过应用您的 iCall_malloc (8196 )和 memset (data、0xAB、8096)情况)不会设置回0 (这 是某些堆栈函数正常工作的预期结果-例如0x00021504 (llReplaceRxBuffers + 0xC)、它基于不同的异常值(存在不同的异常和0xAB)。

    作为一项变通措施、我建议如下:

    在"iCall.c"内:分配后将数据设置为0x00。                                                                                                

    void *ICall_malloc(uint_least16_t size)
    {
      void* data = ICall_heapMalloc(size);
      memset(data, 0x00, size);
      return (data);
    }
    

    我将与堆栈团队一起回顾这一点、以便更好地了解这种修改会导致什么潜在后果。

    BR、

    David。

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

    完美! 感谢您确认我的观察结果。 由于以下两个原因(可能更多)、此修复(尽管可以正常工作)是不可接受的:

    • 在每个 malloc 上设置内存将非常繁重
    • 这需要修改 SDK 文件、这是完全不需要的-这会使我在将来无法轻松升级到最新的 SDK

    我期待 在即将推出的 SDK 版本中修复该问题。  这似乎是一个严重的错误、我非常乐意将我的项目升级到最新版本

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

    您好、Michal、

    我理解。 我认为对于只应在 ICall 注册任务内部使用的 ICall 函数的使用、我们应该在 BIOS_start ()之后使用 iCall_malloc ()、并在 TI-RTOS 中启动 RTOS 调度程序。 我正在与团队一起对此进行审查、认为这是100%肯定的、并在这里给出了适当的理由、但根据我进行的测试、这可以正常工作、而无需每次都将值设置为零。

    BR、

    David。

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

    在 BIOS_start ()之前调用 iCall_malloc 应该没有问题、因为在 iCall_malloc (内部 HEAPMGR_malloc)的执行中没有任何需要 BIOS 来执行。 这是一个非常简单的堆实现并且检查很容易–那些函数中的任何内容都不需要 BIOS 运行。 关于从 ICall 已注册任务中调用 ICall 函数–这同样适用于 iCall_malloc 吗? 考虑到下面堆管理器的实现并且没有调用中止函数、我不这么认为。 并非所有希望分配内存的任务都必须是 ICall 注册的任务。

    实际问题是 TI BLE5堆栈执行、假定 iCall_malloc 返回初始化为0x00的存储器区域的指针。 作为嵌入式开发人员、我绝不会假设动态分配的存储器将使用任何值进行初始化。 如果我希望我的存储器具有特定的值、我显式设置了该值。

    感谢您对如何解决此问题的所有建议、但我会传递这些建议–我为企业项目提供了更好的解决方案。 正如您确认的、TI BLE5 Stack 的实现存在问题、 我对 TI 的期望是确保在即将推出的 SDK 版本中修复该错误。

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

    您好、Michal、

    我已将此问题提交给研发团队、他们将在此对最佳方法进行评估。 我会在有答案后立即向您提供最新信息。

    感谢您的耐心。

    BR、

    David。

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

    附加信息。

    在编译期间启用以下选项也可以触发同样的问题:HEAPMGR_Profiler。

    它会在 rtos_heaposal.h 文件中的 void HEAPMGR_init (void)函数中启用这段代码:

    #ifdef HEAPMGR_PROFILER
      (void)HEAPMGR_MEMSET(HEAPMGR_HEAP, HEAPMGR_INIT_X, (HEAPMGR_SIZE/HDRSZ)*HDRSZ);
    #endif // HEAPMGR_PROFILER

    使用预定义数据填充 RAM。 当然、这也会导致同样的问题。

    鉴于可以通过两种不同的方式触发错误、因此解决根本原因(TI BLE5栈错误)很有意义、而不必尝试避免触发它。

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

    您好、Michal、

    感谢您提供更多信息。 我也与团队分享了这一点、我将尽快报告。

    BR、

    David。

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

    你好,大卫,任何关于这个主题的结论?

    此致、
    Andrzej

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

    您好、Andrzej:

    这是一个很好的问题。 团队仍在调查此问题、我将要求提供最新信息。

    BR、

    David。

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

    我可以在何时修复?

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

    您好、Andrzej:

    目前正在对该问题的优先次序进行内部评估、我们正在尽最大努力尽快解决该问题。 我们正在就预期时间与您的 TI 参考联系人沟通。 对此可能造成的延迟和不便、我深表歉意。

    BR、

    David。