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.

LAUNCHXL-CC1352P: CC1352P开发板做协调器,新设备入网导致协调器进入Error_raiseX状态

Part Number: LAUNCHXL-CC1352P
Other Parts Discussed in Thread: CC1352P, CC2652P

CC1352P协调器,加入一个不支持Zigbee 3.0的节点,超时触发BDB_TC_LK_EXCH_PROCESS_EXCH_FAIL事件后,在bdb_TCJoiningDeviceFree中释放入网节点信息。在bdb_TCJoiningDeviceFree中运行到OsalPort_free( descCurrent )这一步时,协调器死机,进入Error_raiseX函数,并且在if (Error_policy_D == Error_SPIN) 中陷入死循环。

同一块开发板,在多个不同版本的SDK上面验证,均出现该现象。同样的程序,移植到CC2652P模块上就不会出现该问题。

  • 您好

    已经收到了您的案例,调查需要些时间,感谢您的耐心等待

  • 我这边找到原因了,系bdb_TCProcessJoiningList释放设备记录导致,在队列中先释放指针,再从指针中获取下一个地址,或导致协调器获取到一个错误的指针。

    很奇怪,在CC1352P开发板上有这个问题,但是在我们自己的CC2652模块上没有该问题。

    void bdb_TCProcessJoiningList(void)
    {
      bdb_joiningDeviceList_t* tempJoiningDescNode;
    
      if(bdb_joiningDeviceList)
      {
        tempJoiningDescNode = bdb_joiningDeviceList;
    
        while(tempJoiningDescNode)
        {
          if(tempJoiningDescNode->NodeJoinTimeout)
          {
            tempJoiningDescNode->NodeJoinTimeout--;
          }
    
          if(tempJoiningDescNode->NodeJoinTimeout == 0)
          {
            uint8_t isTCLKExchangeRequired = bdb_doTrustCenterRequireKeyExchange();
            //Check if the key exchange is required
            if(isTCLKExchangeRequired)
            {
                AddrMgrEntry_t entry;
    
                entry.user = ADDRMGR_USER_DEFAULT;
                OsalPort_memcpy(entry.extAddr,tempJoiningDescNode->bdbJoiningNodeEui64, Z_EXTADDR_LEN);
    
                if(AddrMgrEntryLookupExt(&entry))
                {
                  ZDSecMgrAPSRemove(entry.nwkAddr,entry.extAddr,tempJoiningDescNode->parentAddr);
                }
            }
    
            // If we are here, a joining device has been expired due to timeout either because it is a
            // legacy device (does not perform key exchange), it is an Z3.0 device that did not perform
            // key exchange intentionally, or it is a Z3.0 device that has failed to perform key exchange.
            // Depending on our TC settings, below we decide if this joiner should be removed from the
            // security manager
    
            uint16_t keyNvIndex;
            uint16_t index;
            APSME_TCLinkKeyNVEntry_t TCLKDevEntry;
            uint8_t found;
    
            //search for the entry in the TCLK table
            keyNvIndex = APSME_SearchTCLinkKeyEntry(tempJoiningDescNode->bdbJoiningNodeEui64,&found, &TCLKDevEntry);
    
            uint16_t nwkAddr;
            //Look up nwkAddr before it is cleared by ZDSecMgrAddrClear
            AddrMgrNwkAddrLookup(tempJoiningDescNode->bdbJoiningNodeEui64, &nwkAddr);
    
            // If TC is mandating key exchange, remove devices that have not successfully performed key exchange.
            // Keep entries for ZG_PROVISIONAL_KEY so install code derived key is maintained, so joiner can reattempt join
            // If we got here and have a ZG_VERIFIED_KEY (unexpected), do not remove this entry either
            if( (isTCLKExchangeRequired == true) &&
                (TCLKDevEntry.keyAttributes != ZG_PROVISIONAL_KEY) &&
                (TCLKDevEntry.keyAttributes != ZG_VERIFIED_KEY)
              )
            {
              //Remove the entry in address manager
              ZDSecMgrAddrClear(tempJoiningDescNode->bdbJoiningNodeEui64);
    
              //If found, erase it.
              if(found == TRUE)
              {
                memset(&TCLKDevEntry,0,sizeof(APSME_TCLinkKeyNVEntry_t));
                TCLKDevEntry.keyAttributes = ZG_DEFAULT_KEY;
    
                //Increase the shift by one. Validate the maximum shift of the seed which is 15
                index = keyNvIndex;
    
                TCLinkKeyRAMEntry[index].rxFrmCntr = 0;
                TCLinkKeyRAMEntry[index].txFrmCntr = 0;
                TCLinkKeyRAMEntry[index].entryUsed = FALSE;
    
                //Update the entry
                osal_nv_write_ex( ZCD_NV_EX_TCLK_TABLE, keyNvIndex,
                                  sizeof(APSME_TCLinkKeyNVEntry_t),
                                  &TCLKDevEntry );
              }
            }
    
            if(pfnTCLinkKeyExchangeProcessCB)
            {
              bdb_TCLinkKeyExchProcess_t bdb_TCLinkKeyExchProcess;
              OsalPort_memcpy(bdb_TCLinkKeyExchProcess.extAddr,tempJoiningDescNode->bdbJoiningNodeEui64, Z_EXTADDR_LEN);
              bdb_TCLinkKeyExchProcess.nwkAddr = nwkAddr;
              bdb_TCLinkKeyExchProcess.status = BDB_TC_LK_EXCH_PROCESS_EXCH_FAIL;
    
              bdb_SendMsg(bdb_TaskID, BDB_TC_LINK_KEY_EXCHANGE_PROCESS, BDB_MSG_EVENT_SUCCESS,sizeof(bdb_TCLinkKeyExchProcess_t),(uint8_t*)&bdb_TCLinkKeyExchProcess);
            }
            //Free the device from the list
            //The next pointer needs to be obtained before the previous pointer is released, fixed by Luoyiming at 2025-03-06
            bdb_joiningDeviceList_t* joiningDeviceToRemove = tempJoiningDescNode;
            tempJoiningDescNode = tempJoiningDescNode->nextDev;
            bdb_TCJoiningDeviceFree(joiningDeviceToRemove);
          }
          else
          {
            //The next pointer can only be obtained when the previous pointer has not been released, fixed by Luoyiming at 2025-03-06
            tempJoiningDescNode = tempJoiningDescNode->nextDev;
          }
        }
      }
    
      //we are done with the list
      if(bdb_joiningDeviceList == NULL)
      {
        OsalPortTimers_stopTimer(bdb_TaskID,BDB_TC_JOIN_TIMEOUT);
      }
    }