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.

CC2530: Possible bug in Z-Stack 3.0.1, ZDO_MGMT_LEAVE_REQ cannot leave SampleSwitch ZED in Z-Stack 3.0.1

Part Number: CC2530
Other Parts Discussed in Thread: Z-STACK

When I test sending ZDO_MGMT_LEAVE_REQ from coordinator (using SampleLight in Z-Stack Home 1.2.2a) to SampleSwitch ZED in Z-Stack 3.0, I find ZED sends Management Leave Response. However, I see device still do rejoin to coordinator after I power cycle my SampleSwitch. I check ZDO_ProcessMgmtLeaveReq and find the following red lines might be the root cause.

void ZDO_ProcessMgmtLeaveReq( zdoIncomingMsg_t *inMsg )
{
  NLME_LeaveReq_t req;
  ZStatus_t       status;
  uint8           option;
  uint8 *msg = inMsg->asdu;
 
  if ( ( AddrMgrExtAddrValid( msg ) == FALSE                 ) ||
       ( osal_ExtAddrEqual( msg, NLME_GetExtAddr() ) == TRUE )    )
  {
    if ( ( ZG_BUILD_COORDINATOR_TYPE ) && ( ZG_DEVICE_COORDINATOR_TYPE ) )
    {
      // Coordinator shall drop the leave request for itself
      // section 3.6.1.10.3.1 R21
      return;
    }
    else
    {
      // Remove this device
      req.extAddr = NULL;
    }
  }
  else
  {
    // Remove child device
    req.extAddr = msg;
  }
  if ( ( ZG_BUILD_ENDDEVICE_TYPE ) && ( ZG_DEVICE_ENDDEVICE_TYPE ) )
  {
    //Only the parent device can request to leave, otherwise silently discard the frame
    if(inMsg->srcAddr.addr.shortAddr != _NIB.nwkCoordAddress)
    {
      return;
    }
  }

  option = msg[Z_EXTADDR_LEN];
  if ( option & ZDP_MGMT_LEAVE_REQ_RC )
  {
    req.removeChildren = TRUE;
  }

  if ( option & ZDP_MGMT_LEAVE_REQ_REJOIN )
  {
     req.rejoin = TRUE;
  }

  req.silent = FALSE;
 
  //According to R21 spec sec2.4.3.3.5.2 Mgmt leave rsp must contain the status response from the nwk leave processing.
  //Latest discussion in Zigbee indicates that mgmt leave rsp due to an OTA command must have status=success (9/12/16)
  status = ZSuccess;
 
  ZDP_MgmtLeaveRsp( inMsg->TransSeq, &(inMsg->srcAddr), status, FALSE );
 
  if ( ZG_BUILD_ENDDEVICE_TYPE )
  {
    // Stop polling and get ready to reset
    NLME_SetPollRate( 0 );
    NLME_SetResponseRate(0);
    NLME_SetQueuedPollRate(0);
  }
 
  NLME_LeaveReq(&req);
 
  if (! (option & ZDP_MGMT_LEAVE_REQ_REJOIN) )
  {
    if(req.extAddr == NULL)
    {
      bdb_setFN();
    }
  }
}

Since ZDO_ProcessMgmtLeaveReq uses NLME_SetPollRate, NLME_SetResponseRate, and NLME_SetQueuedPollRate to set all polling rate to 0 and send NLME_LeaveReq, the device won't get ack and go to ZDApp_LeaveReset to do a proper factory reset.

Also, the code checks if(req.extAddr == NULL) to do bdb_setFN but req.extAddr won't be null because it would be assigned by req.extAddr = msg in previous code.

Due to both cases above won't triggered, the device would rejoin after it sends Management Leave Response and does power cycle.

My best guess to fix the problem is to comment out "NLME_SetPollRate, NLME_SetResponseRate, and NLME_SetQueuedPollRate" or "if(req.extAddr == NULL)". I don't know if there is any side effect. Can anyone from TI help to check and verify this issue?

  • Hi YK,

    Thank you for the detailed description. I have sent both this thread and the original from to our software developers and they will reply as soon as enough information about this behavior has been gathered.

    Regards,
    Ryan
  • Hi YK,

    Can you provide a capture of this behavior.

    Also the MAC ACK is not dependent of polling and is not required for the factory new reset.

    If req.extAddr is not NULL, then the address is different from the device that you are debugging, that's the only way to have this result. The first condition in ZDO_ProcessMgmtLeaveReq():

    if ( ( AddrMgrExtAddrValid( msg ) == FALSE ) ||
    ( osal_ExtAddrEqual( msg, NLME_GetExtAddr() ) == TRUE ) )

    If the address of the message is valid and is equal to the local device address then req.extAddr will be assigned as NULL.

    I hope this helps,

    Regards,

    Jose Alvarez

  • and When I redo the test for getting sniffer log, I find it works like magic. The code can go into else part "req.extAddr = NULL;" case of "if ( ( AddrMgrExtAddrValid( msg ) == FALSE ) || ( osal_ExtAddrEqual( msg, NLME_GetExtAddr() ) == TRUE ) )" so it works as expected. I don't know why I keep seeing this trouble yesterday. I will close this issue first and keep doing some test.