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.

[参考译文] CC1352P:加载新广播数据时软件崩溃

Guru**** 2609955 points
Other Parts Discussed in Thread: SYSCONFIG

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1108768/cc1352p-software-crashes-when-loading-new-advertisement-data

器件型号:CC1352P
Thread 中讨论的其他器件:SysConfig

您好!

通过扩展广播广播广播数据后、我需要为下一个广播更改数据。 因此、我调用  GapAdv_prepareLoadByBuffer  函数来停止广播、更改我的数据(当前仅为虚拟数据、因此我在数据中增加一个字节)、然后我尝试使用  GapAdv_loadByBuffer 重新加载缓冲区、因此也会重新启用广播。 这是在 processAppMsg 函数中完成的、因此  应该不会因为回调上下文而出现问题。 遗憾的是、没有来自 GapAdv_loadByBuffer 的返回、并且软件在调用此函数后没有响应。 我调试了这个问题、当 iCall 尝试发布事件时、似乎会发生这种情况。 在下面、您将找到 来自 processAppMsg 的代码  

static void SimpleBroadcaster_processAppMsg(ttEvt_t *pMsg)
{
  bool safeToDealloc = TRUE;

  switch (pMsg->hdr.event)
  {
    case SC_EVT_ADV_REPORT:
    {
        GapScan_Evt_AdvRpt_t* pAdvRpt = (GapScan_Evt_AdvRpt_t*) (pMsg->pData);
        bStatus_t status = FAILURE;

        Display_print2(dispHandle, ++mrLine, 0, "Advertising Addr: %s RSSI: %d",
                        Util_convertBdAddr2Str(pAdvRpt->addr), pAdvRpt->rssi);
        Display_print1(dispHandle, ++mrLine, 0, "Advertising Data: %s",
                        Util_convertBytes2Str(pAdvRpt->pData, pAdvRpt->dataLen));

        /* Update some data */
        status = GapAdv_prepareLoadByBuffer(advData1, GAP_ADV_FREE_OPTION_DONT_FREE);
        SIMPLEBROADCASTER_ASSERT(status == SUCCESS);
        advData1[4] += 1;

        /* error: no return from this function....  */
        status = GapAdv_loadByBuffer(sizeof(advData1), advData1);
        SIMPLEBROADCASTER_ASSERT(status == SUCCESS);

        // Free report payload data
        if (pAdvRpt->pData != NULL)
        {
            ICall_free(pAdvRpt->pData);
        }
        break;
    }

代码在下面复制的 ICall 代码的第49行停止。 请注意、这一行代码会在我的错误发生之前多次执行、以解决问题。

ICall_Errno ICall_send(ICall_EntityID src,
                              ICall_EntityID dest,
                              ICall_MSGFormat format,
                              void *msg)
{
  ICall_CSState key;
  ICall_MsgHdr *hdr = (ICall_MsgHdr *) msg - 1;

  if (dest >= ICALL_MAX_NUM_ENTITIES ||
      src >= ICALL_MAX_NUM_ENTITIES)
  {
    return (ICALL_ERRNO_INVALID_PARAMETER);
  }
  key = ICall_enterCSImpl();
  if (!ICall_entities[dest].task)
  {
    ICall_leaveCSImpl(key);
    return (ICALL_ERRNO_INVALID_PARAMETER);
  }

  ICall_leaveCSImpl(key);
  /* Note that once the entry is valid,
   * the value does not change and hence it is OK
   * to leave the critical section.
   */

  hdr->srcentity = src;
  hdr->dstentity = dest;
  hdr->format = format;

#ifdef ICALL_NO_APP_EVENTS
  // for applications, call direct to callback without enqueue/event_pend/dequeue
  if (ICall_entities[dest].service == ICALL_SERVICE_CLASS_APPLICATION)
  {
    if (ICall_entities[dest].appCallback != NULL)
    {
      uint8_t safeToDealloc = ICall_entities[dest].appCallback(0 /*event*/, (uint8_t *)msg);
      if (msg && safeToDealloc)
      {
        ICall_freeMsg(msg);
      }
    }
    return (ICALL_ERRNO_SUCCESS);
  }
#endif // ICALL_NO_APP_EVENTS
  ICall_msgEnqueue(&ICall_entities[dest].task->queue, msg);
  
  /* Software stops working here */
  ICALL_SYNC_HANDLE_POST(ICall_entities[dest].task->syncHandle);

  return (ICALL_ERRNO_SUCCESS);
}

下面显示了完整的调用堆栈。

提前感谢您

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

    您好、Alexander、

    已指派某人查看此问题。 他们会向您提供反馈。  

    此致、

    SID

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

    您好、Alexander、

    您是否知道在失败之前执行它的次数?

    此外、您是否了解过 ICALL SysConfig 设置? 请告诉我、修改这些参数是否会对故障行为产生影响。

    此致、

    Arthur

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

    尊敬的 Arthur:

    线路  

    ICALL_SYNC_HANDLE_POST(ICall_entities[dest].task->syncHandle);

    在我在 应用程序中调用 GapAdv_loadByHandle 函数之后的第17次失败之前、执行了16次而没有任何问题。 我将使用 iCall 的实体的最大数量从6个增加到8个、将启用 iCall 的任务的最大数量增加到4个、这很遗憾没有帮助。 此外 、将两个值过度增加到16也不会产生影响。

    此致、

    Alex

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

    您好、Alexander、

    它看起来像是堆问题、不知怎么说。 您可以尝试在您的项目上使用 ROV (training.ti.com/how-use-runtime-object-view)吗? 使用它、我们可能会在某个位置看到一些内存泄漏、我希望这样做。

    此致、

    Arthur

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

    尊敬的 Arthur:

    感谢你的答复。 不幸的是、我在 ROV 中看不到任何堆存储器。 无堆空间仪表板和 HeapMem 模块都未显示任何内容(请参阅下面的屏幕截图)。 不过、堆栈空间看起来不错。 此外,BIOS ->扫描错误模块未检测到错误。

    最接近此问题的论坛主题帖是 这个问题、但它并不完全涵盖我的案例、除此之外 、主题帖创建者没有回复他是否(以及如何)修复了此问题。

    猜我们需要先解决这个问题、然后才能发现任何内存泄漏...  

    此致、

    Alex

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

    您好、Alexander、

    实际上、您必须首先在项目中启用某些功能。

    在.cfg 文件(TI-RTOS 配置)中、找到名为 HEAPMGR_CONFIG 的变量。 上面的注释块解释了该变量的用途。 要使用 ROV、必须将其设置为0x81或0x82。

    此外、您使用的 SDK 版本是什么、以及 RTOS 是什么?

    此致、

    Arthur

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

    尊敬的 Arthur:

    谢谢、幸运的是、这是一个简单的"修复"。 认为这是错误。 我已将 HEAPMGR_CONFIG 设置为0x82。

    下面是在我执行有问题 的 ICALL_SYNC_Handle_post 函数调用(我的初始帖子中代码的第49行)之前看到的 ROV。 如果你问我、堆存储器似乎是可以的。  但我注意到 simpleBroadcaster 任务在  执行此行后处于就绪状态。  我不知道这是从哪里来的。

     在 ICALL_SYNC_Handle_post 行之前:

     在 ICALL_SYNC_Handle_post 行之后:

    因此、从 TI-RTOS 基础知识来看 、我的任务要么被抢先、要么被读取。 恐怕我不知道这两种情况的含义、也不知道为什么我的任务不能继续运行。

    此致、

    Alex

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

    您好、Alexander、

    在这种情况下、您可以尝试更改 simple_broadcaster 任务优先级、以查看它是否可以解决您的问题。

    应在示例代码中将其定义为 SB_TASK_PRIORITY。

    此外、您能否尝试移动该块:

    // Free report payload data
            if (pAdvRpt->pData != NULL)
            {
                ICall_free(pAdvRpt->pData);
            }

    外壳体中? 我问的是、因为在当前 SDK 中、它的表现如下:

    static void SimpleBroadcaster_processAppMsg(sbEvt_t *pMsg)
    {
      bool safeToDealloc = TRUE;
    
      switch (pMsg->event)
      {
        case SB_ADV_EVT:
          safeToDealloc = SimpleBroadcaster_processAdvEvent((sbGapAdvEventData_t*)(pMsg->pData));
          break;
    
        default:
          // Do nothing.
          break;
      }
    
      if (safeToDealloc)
      {
        // Free message data
        if (pMsg->pData)
        {
          ICall_free(pMsg->pData);
        }
      }
    }

    接下来会出现另一个问题、您使用的是哪个 SDK 版本?

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

    尊敬的 Arthur:

    我正在使用 SDK 5.20.0.52。

    遗憾的是、错误仍然存在。 我已将广播设备任务的优先级设置为4 (低于 iCall 一级)、并且行为没有任何变化。 在案例后面移动去位也没有任何不同。

      当我使用级别5作为任务优先级时,ICALL_SYNC_Handle_post 执行后,ICCall 代码会继续。 然后、它运行到以下 iCall 代码的第52行(函数 iCall_waitMatch)、然后、同样、调试器不会继续:

     /*******************************************************************************
     * @fn          icall_directAPI
     * see headers for details.
     */
    uint32_t icall_directAPI( uint8_t service , icall_lite_id_t id, ... )
    {
      va_list argp;
      uint32_t res;
      icallLiteMsg_t liteMsg;
    
      // The following will push all parameter in the runtime stack.
      // This need to be call before any other local declaration of variable....
      va_start(argp, id);
    
      // Test that the API is not called in a Hwi or Swi context
      {
        BIOS_ThreadType threadtype = BIOS_getThreadType();
    
        if (threadtype == BIOS_ThreadType_Hwi ||
            threadtype == BIOS_ThreadType_Swi)
        {
    #ifdef HALNODEBUG
    #else /* ! HALNODEBUG */
          ICall_abort();
    #endif /* HALNODEBUG */
        }
      }
    
      // Todo - add string for every icall API function, instead of printing function address
      BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : icall_directAPI to BLE func=0x%x, status=%d\n", id, 0);
      // Create the message that will be send to the requested service..
      liteMsg.hdr.len = sizeof(icallLiteMsg_t);
      liteMsg.hdr.next = NULL;
      liteMsg.hdr.dest_id = ICALL_UNDEF_DEST_ID;
      liteMsg.msg.directAPI  = id;
      liteMsg.msg.pointerStack = (uint32_t*)(*((uint32_t*)(&argp)));
      ICall_sendServiceMsg(ICall_getEntityId(), service,
                           ICALL_MSG_FORMAT_DIRECT_API_ID, &(liteMsg.msg));
    
      // Since stack needs to always have a higher priority than the thread calling
      // the API, when we reach this point the API has been executed by the stack.
      // This implies the following:
      //  - API are not called in critical section or in section where task
      //    switching is disabled
      // It is possible that the stack is blocking on this API, in this case a
      // sync object needs to be used in order for this call to resume only when
      // the API has been process in full.
      {
        ICall_Errno errno;
        void *pCmdStatus = NULL;
    
        errno = ICall_waitMatch(ICALL_TIMEOUT_PREDEFINE, matchLiteCS, NULL, NULL,
                        (void **)&pCmdStatus);
        if (errno == ICALL_ERRNO_TIMEOUT)
        {
    #ifdef HALNODEBUG
    #elif  defined(EXT_HAL_ASSERT)
          HAL_ASSERT(HAL_ASSERT_CAUSE_ICALL_TIMEOUT);
    #else /* !EXT_HAL_ASSERT */
          ICall_abort();
    #endif /* EXT_HAL_ASSERT */
        }
        else if (errno == ICALL_ERRNO_SUCCESS)
        {
          if (pCmdStatus)
          {
            ICall_freeMsg(pCmdStatus);
          }
        }
        else
        {
    #ifdef HALNODEBUG
    #else /* ! HALNODEBUG */
          ICall_abort();
    #endif /* HALNODEBUG */
        }
      }
    
      // The return parameter is set in the runtime stack, at the location of the
      // first parameter.
      res = liteMsg.msg.pointerStack[0];
    
      va_end(argp);
    
      return (res);
    }

    ROV 显示在 iCall 任务运行时广播设备任务被阻止。 从  iCall_waitMatch 函数调用上方的注释来看、这是因为 iCall 任务具有与我的广播设备任务相同的优先级、对吧?

    此致、

    Alex

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

    尊敬的 Alex:

    优先级确实必须在 iCall 下、您所做的是好的。

    使用旧5.20 SDK 是否有原因? 我们的最新版本是6.10、该 SDK 是否也出现了问题?

    从您的第一个代码片段中、我看不到它为什么会失败的任何明显原因。 如果可能、我将在您尝试使用最新 SDK 时继续检查它。

    此致、

    Arthur

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

    尊敬的 Arthur:

    我已将项目迁移到 CC13xx CC26xx SDK 版本。 6.10.00.29。 GapAdv_loadByHandle 函数调用仍无法执行。 ICall 代码现在在调用后运行到 SPIn 中、请参阅下面的调用堆栈。

    如果您需要有关我的代码的更多信息、请告诉我。

    此致、

    Alex

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

    您好!

    我注意到您目前仅使用一个句柄、是否会使用 GAP_prepareLoadByHandle 和 GapAdv_loadByHandle 为您提供一个选项?

    https://dev.ti.com/tirex/content/simplelink_cc13xx_cc26xx_sdk_6_10_00_29/docs/ble5stack/ble_user_guide/html/ble-stack-5.x/gap-cc13xx_cc26xx.html#load-a-new-buffer-to-a-single-advertising-handle

    此致、

    Arthur

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

    尊敬的 Arthur:

    是的、我已经尝试过这一点(事实上、我发送给您的项目已经在1077和1082行中包含 GapAdv_prepareLoadByHandle 和 GapAdv_loadbyHandle)。 我应该指出这一点。  

    不过、软件的行为是相同的。

    此致、

    Alex

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

    Hei Alexander、

    我似乎无法重现此问题、因为它会在其他地方崩溃。 我将与您重新联系。