主题中讨论的其他器件: CC2640
我们的问题是、在187K 中的大约128K 需要通过 persistent 应用程序遍历到主应用后、固件映像块的 OAD 传输失败。 无论出于何种原因、 我们都 对堆栈和周围细节进行了深入研究、并对我们的应用程序进行了许多测试/诊断构建(该应用程序与 CC2640姊妹产品兼容、 而不是 CC2340R5 [SDK 7_40],进程在 OAD_SetParameter ()内停止和 GATT_Notification ()返回0x16 (blePending )使传输进程结束。
创建时钟并设置事件以重试通知调用不会纠正问题,因为每次后续调用 GATT_Notification ()都会返回0x16 ,直到启动新的调试会话。
这是非常意外的情况、因为通过持久应用程序从应用程序传输到设备的每个块都处于锁定步骤。 Essential SDK 示例(无一个加密/步骤)中存储的模型使用通知应用程序通过 WriteCharacteristic 请求发送下一个块,而 WriteCharacteristic 又生成调用 BLEAppUtil_invokeFunction() ,将块发送到应用程序级别以编程到闪存。 这种锁定步骤方法意味着,在没有其他 BLE 操作同时运行到 OAD 下载的情况下,内部队列应该从根本上被耗尽,并且没有可能导致来自 GATT_Notification ()的 blePending 返回状态的未决指示或步骤。
如果我们看到从 Gatt_Notification ()返回0x16 ,我们会设置一个计时器,以重新发送所需块的通知,但向 GATT_Notification()发出的后续调用(稍后为250mSec )也会返回0x16的状态,此后每次重试也会返回。
该问题通常发生在 主片上应用的 FW 映像(~187K)中的802个块中的400-600个块(每个块236字节)之后。 但有趣的是、我们每次测试过程时都不会在同一点发生失速。
检查 ROV 中的细节显示了每个线程的健康堆栈、并且堆的分配率略高于50%、在12K 个运算中、分配的不足大约为99 malloc/释放、因此这些似乎与正常使用一致。
我们另一个基于 CC2640的器件在其 OAD 更新中仅包含约44KB 并使用相同的应用;CC2340R5始终使其超过44K 点、在传输大约100-130K 后卡住。 我们可以看到在其退出点之前闪存到 mainapp 区域的正确代码。
因此, 在 API 级别中,许多人关注内存泄漏的降低。 除了在 OAD_service.c 和 OAD_profile.c 中进行一些微调以添加一些诊断计数器(这些计数器尚未揭示明显的资源问题)之外、这些是 SLP SDK 7_40中提供的示例源代码版本。
尚未弄清楚如何使用 ROV 来检查队列的运行状况(有些说明需要在那里的人)、但我们以缓慢的动作(在通知后在应用程序端增加延迟)操作了传输过程、这没有产生影响。
我的想法是那里的团队没有尝试过一个大的固件映像过 OAD,但保持迅速较小的映像(如< 80KB),并且没有看到这个问题。
您怎么看?
P.S.在 OAD_service 中发现了另一个可疑的 malloc/free 泄漏路径。 C 在过程 OadWriteAttrCB()的两个地方(我不认为它们对我的问题有贡献(我将在单独的线程中发布) ,但如果 iCall_malloc()的正文至 BLEAppUtil_invokeFunction()失败,为 pOADSrvWriteReq 对象分配的内存未释放, 同样,如果对 BLEAppUtil_invokeFunction()的调用失败(例如如果队列已满),则这两个对象不会按其应有的方式释放。 在测试期间、我们将错误计数器放置在正确的位置、虽然我们获得0x16返回代码、但我们不会获得 malloc 错误的任何命中点。