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.

Can't set event when register ZDO Message Device_annce

Other Parts Discussed in Thread: Z-STACK

I use Z-stack mesh 1.0 to develop a small demo network (Actually I used the latest Z-stack Home, but as the problem occur, I thought it was the Z-stack problem, so I move back to Z-stack mesh. Unfortunately, the problem still exist). The coordinator must use the Device_annce message to obtain knowledge of new device joining. Therefore, I call function: 

ZDO_RegisterForZDOMsg( HVACQueen_TaskID, Device_annce ); 

in

userApplication_Init();

to register the Device_annce event. Besides, I put 

switch ( MSGpkt->hdr.event )
{
      case ZDO_CB_MSG:
      HVACQueen_ProcessZDOMsgs((zdoIncomingMsg_t *)MSGpkt);
      break;

in the user application event processing function.

Coordinator can receive the Device_annce message properly. Moreover, in the end of the ZDO Msg processing function, I set an event to process the information. 

HVACQueen_ProcessZDOMsgs((zdoIncomingMsg_t *)MSGpkt)

{

...

osal_set_event(HVACQueen_TaskID , HVACPTL0_EVENT_TIMEOUT_EVT);

return true;

}

Now, here is the funny thing begin. The coordinator will goes to an error status! The sniffer file is attacked as below:

leaveEvent.psd

Moreover, if I comment the osal_set_event(userApplication_TaskID , HVACPTL0_EVENT_TIMEOUT_EVT); in theHVACQueen_ProcessZDOMsgs() function. So the ZDO_CB_MSG handler function will be looks like:

HVACQueen_ProcessZDOMsgs((zdoIncomingMsg_t *)MSGpkt)

{

...

// osal_set_event(HVACQueen_TaskID , HVACPTL0_EVENT_TIMEOUT_EVT);

return true;

}

Then, the coordinator works smoothly as hell. Sniffer file as below. Note that I reset the end-device couple times to repeat join process.

withoutEvent.psd

  • Thanks god, all edits have been saved. Need to mention that it doesn't matter if the event is set in the ZDO processing function. I have set a timer event, and the situation is the same. Once there is an event, the coordinator goes down. In Zigbee Mesh, the coordinator always goes to halAssertHazardLights() function and never goes out. In Zigbee Home, it goes to UpdatesystemClock() (might spell wrong) and never goes out.
  • One more thing, the event is process in userApplication_ProcessEvent() function, it looks like below:

    if (events & HVACPTL0_EVENT_TIMEOUT_EVT )
      {
        ...
        
        return ( events ^ HVACPTL0_EVENT_TIMEOUT_EVT ); 
      }  

    Can somebody please help me out... I spend 3 days on this problem... I figure that there is something I did wrong so the coordinator doesn't works well. 

  • Can you show me the source code in HVACQueen_ProcessZDOMsgs? And how do you define HVACPTL0_EVENT_TIMEOUT_EVT?
  • Sure! The  HVACQueen_ProcessZDOMsgs() as follow:

    static void HVACQueen_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )
    {
      switch ( inMsg->clusterID )
      {
        case Device_annce:
          if(hvacHandleZDODeviceAnnounce(inMsg))
            HalLedBlink (HAL_LED_2, 5, 20, 1000);
          break;
          
        case End_Device_Bind_rsp:
          if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )
          {
            // Light LED
            HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
          }
    #if defined( BLINK_LEDS )
          else
          {
            // Flash LED to show failure
            HalLedSet ( HAL_LED_4, HAL_LED_MODE_FLASH );
          }
    #endif
          break;
    
        case Match_Desc_rsp:
          {
            ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
            if ( pRsp )
            {
              if ( pRsp->status == ZSuccess && pRsp->cnt )
              {
                HVACQueen_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
                HVACQueen_DstAddr.addr.shortAddr = pRsp->nwkAddr;
                // Take the first endpoint, Can be changed to search through endpoints
                HVACQueen_DstAddr.endPoint = pRsp->epList[0];
    
                // Light LED
                HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
              }
              osal_mem_free( pRsp );
            }
          }
          break;
      }
    }

    hvacHandleZDODeviceAnnounce() was define as:

    uint8 hvacHandleZDODeviceAnnounce(zdoIncomingMsg_t * MSGpkt)
    {
      ZDO_DeviceAnnce_t Annce;
      AddrMgrEntry_t annouEntry;
      PTL0_InitTypeDef outGoingPTL0Msg;
      uint8 *ptl0_payloadbuf;
      
      // Parse message
      ZDO_ParseDeviceAnnce( MSGpkt, &Annce );
      
      annouEntry.user = ADDRMGR_USER_DEFAULT;
      osal_memcpy( annouEntry.extAddr, Annce.extAddr, Z_EXTADDR_LEN );
      
      // check devcie available? Already in table?
      if(AddrMgrEntryLookupExt( &annouEntry ))
      {
        // its a new child. Prepare a network status update for STM32.
        // use memory allocation to save data, must release memory after process
        
        // prepare the buffer to store the data payload
        ptl0_payloadbuf = (uint8 *)osal_mem_alloc( PTL0_NWK_STATUS_RP_NEWDEV_DATALENGTH );
        
        // check valid
        if (ptl0_payloadbuf == NULL)
          return false;
        
        // copy mac address to data payload
        osal_memcpy( ptl0_payloadbuf, Annce.extAddr, Z_EXTADDR_LEN );
        
        // assemble message.
        // (not finish)
        outGoingPTL0Msg.CMD1 = PTL0_NWK_STATUS_RP;
        outGoingPTL0Msg.CMD2 = PTL0_NWK_STATUS_RP_NEWDEV;
        outGoingPTL0Msg.datapointer = ptl0_payloadbuf;
        outGoingPTL0Msg.length = Z_EXTADDR_LEN;
        outGoingPTL0Msg.SOF = PTL0_SOF;
        outGoingPTL0Msg.version = PTL0_FRAMEVER;
    
        // push to event stack, set event
        if(ptl0_pushEvent(outGoingPTL0Msg))
        {
          osal_set_event(HVACQueen_TaskID , HVACPTL0_EVENT_TIMEOUT_EVT);
          return true;
        }
        else
          return false;
      }
      else
      {
        // mac address already in table, child reset, rejoin network.
        // Do nothing for now. 
        asm("NOP");
      }
      return true;
    }

    Note that ptl0_pushEvent() is not push to osal event. It push data to a ring buffer.

    The HVACPTL0_EVENT_TIMEOUT_EVT was define as:

    // Application Events (OSAL) - These are bit weighted definitions.
    #define HVACQUEEN_SEND_MSG_EVT       0x0001
    #define HVACPTL0_EVENT_TIMEOUT_EVT   0x0004 

    I've tried different bit weighted value, none of them works...

    Looking forward to hear from you!!!!

  • Do you mean if you comment out "osal_set_event(HVACQueen_TaskID , HVACPTL0_EVENT_TIMEOUT_EVT);" then your application works fine?

  • Yes. If I comment out this osal_set_event, there will be zero event in HVACQueen_ProcessEvent(); (besides SYS_EVENT_MSG). Basically the HVACQueen_ProcessEvent() looks like:

    uint16 HVACQueen_ProcessEvent( uint8 task_id, uint16 events )
    {
      afIncomingMSGPacket_t *MSGpkt;
      afDataConfirm_t *afDataConfirm;
    
      // Data Confirmation message fields
      byte sentEP;
      ZStatus_t sentStatus;
      byte sentTransID;       // This should match the value sent
      (void)task_id;  // Intentionally unreferenced parameter
    
      if ( events & SYS_EVENT_MSG )
      {
        MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( HVACQueen_TaskID );
        while ( MSGpkt )
        {
          switch ( MSGpkt->hdr.event )
          {
            case ZDO_CB_MSG:
              HVACQueen_ProcessZDOMsgs((zdoIncomingMsg_t *)MSGpkt);
              break;
    
            case CMD_SERIAL_MSG:
              // UART data, uart handler
              HVACQueen_HandleUart ((mtOSALSerialData_t *)MSGpkt);
              
            case AF_DATA_CONFIRM_CMD:
              /*
              // This message is received as a confirmation of a data packet sent.
              // The status is of ZStatus_t type [defined in ZComDef.h]
              // The message fields are defined in AF.h
              afDataConfirm = (afDataConfirm_t *)MSGpkt;
    
              sentEP = afDataConfirm->endpoint;
              (void)sentEP;  // This info not used now
              sentTransID = afDataConfirm->transID;
              (void)sentTransID;  // This info not used now
    
              sentStatus = afDataConfirm->hdr.status;
              // Action taken when confirmation is received.
              if ( sentStatus != ZSuccess )
              {
                // The data wasn't delivered -- Do something
              }
              break;*/
    
            case AF_INCOMING_MSG_CMD:
              HVACQueen_MessageMSGCB( MSGpkt );
              break;
    
            case ZDO_STATE_CHANGE:
              HVACQueen_NwkState = (devStates_t)(MSGpkt->hdr.status);
              if ( (HVACQueen_NwkState == DEV_ZB_COORD) ||
                   (HVACQueen_NwkState == DEV_ROUTER) ||
                   (HVACQueen_NwkState == DEV_END_DEVICE) )
              {
                // Start sending "the" message in a regular interval.
                //osal_start_timerEx( HVACQueen_TaskID,
                //                    HVACQUEEN_SEND_MSG_EVT,
                //                    txMsgDelay );
              }
              break;
    
            default:
              break;
          }
    
          // Release the memory
          osal_msg_deallocate( (uint8 *)MSGpkt );
    
          // Next
          MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( HVACQueen_TaskID );
        }
    
        // return unprocessed events
        return (events ^ SYS_EVENT_MSG);
      }
    
      if (events & HVACPTL0_EVENT_TIMEOUT_EVT )
      {
        PTL0_InitTypeDef* PTL0_sendBuf;
        
        // If there is any event, prepare to send
        while(ptl0_queryEvent())
        {
          // get event
          PTL0_sendBuf = ptl0_getEvent();
          
          // send through PTL0 UART
          ptl0_sendMsg(*PTL0_sendBuf);
          
          // update PTL0 status
          ptl0_updateStat((*PTL0_sendBuf).CMD1);
          
          // release memory
          osal_mem_free(PTL0_sendBuf);
        }
        
        return ( events ^ HVACPTL0_EVENT_TIMEOUT_EVT ); 
      }  
    
      // Discard unknown events
      return 0;
    }
    

  • Wrong code, here you go:

    uint16 HVACQueen_ProcessEvent( uint8 task_id, uint16 events )
    {
      afIncomingMSGPacket_t *MSGpkt;
      afDataConfirm_t *afDataConfirm;
    
      // Data Confirmation message fields
      byte sentEP;
      ZStatus_t sentStatus;
      byte sentTransID;       // This should match the value sent
      (void)task_id;  // Intentionally unreferenced parameter
    
      if ( events & SYS_EVENT_MSG )
      {
        MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( HVACQueen_TaskID );
        while ( MSGpkt )
        {
          switch ( MSGpkt->hdr.event )
          {
            case ZDO_CB_MSG:
              HVACQueen_ProcessZDOMsgs((zdoIncomingMsg_t *)MSGpkt);
              break;
    
            case CMD_SERIAL_MSG:
              // UART data, uart handler
              HVACQueen_HandleUart ((mtOSALSerialData_t *)MSGpkt);
              break;
              
            case AF_DATA_CONFIRM_CMD:
              /*
              // This message is received as a confirmation of a data packet sent.
              // The status is of ZStatus_t type [defined in ZComDef.h]
              // The message fields are defined in AF.h
              afDataConfirm = (afDataConfirm_t *)MSGpkt;
    
              sentEP = afDataConfirm->endpoint;
              (void)sentEP;  // This info not used now
              sentTransID = afDataConfirm->transID;
              (void)sentTransID;  // This info not used now
    
              sentStatus = afDataConfirm->hdr.status;
              // Action taken when confirmation is received.
              if ( sentStatus != ZSuccess )
              {
                // The data wasn't delivered -- Do something
              }*/
              break;
    
            case AF_INCOMING_MSG_CMD:
              HVACQueen_MessageMSGCB( MSGpkt );
              break;
    
            case ZDO_STATE_CHANGE:
              HVACQueen_NwkState = (devStates_t)(MSGpkt->hdr.status);
              if ( (HVACQueen_NwkState == DEV_ZB_COORD) ||
                   (HVACQueen_NwkState == DEV_ROUTER) ||
                   (HVACQueen_NwkState == DEV_END_DEVICE) )
              {
                // Start sending "the" message in a regular interval.
                //osal_start_timerEx( HVACQueen_TaskID,
                //                    HVACQUEEN_SEND_MSG_EVT,
                //                    txMsgDelay );
              }
              break;
    
            default:
              break;
          }
    
          // Release the memory
          osal_msg_deallocate( (uint8 *)MSGpkt );
    
          // Next
          MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( HVACQueen_TaskID );
        }
    
        // return unprocessed events
        return (events ^ SYS_EVENT_MSG);
      }
    
      if (events & HVACPTL0_EVENT_TIMEOUT_EVT )
      {
        PTL0_InitTypeDef* PTL0_sendBuf;
        
        // If there is any event, prepare to send
        while(ptl0_queryEvent())
        {
          // get event
          PTL0_sendBuf = ptl0_getEvent();
          
          // send through PTL0 UART
          ptl0_sendMsg(*PTL0_sendBuf);
          
          // update PTL0 status
          ptl0_updateStat((*PTL0_sendBuf).CMD1);
          
          // release memory
          osal_mem_free(PTL0_sendBuf);
        }
        
        return ( events ^ HVACPTL0_EVENT_TIMEOUT_EVT ); 
      }  
    
      // Discard unknown events
      return 0;
    }

  • Since your application would hit halAssertHazardLights, you can set a breakpoint on it and check call stack to know who invokes it.
  • Thanks for your quick reply! You are my hero bro.

    So finally I find the problem, its the osal_mem_free() function in HVACPTL0_EVENT_TIMEOUT_EVT event processing function. Program goes into osal_mem_free() and jump to halAssertHazardLights.

    In the application, after receiving a Device_annce, osal_mem_alloc(); will be called to get some memory to store information for later process. Then, the pointer (not global pointer) to the memory and others information will store in a structure and also saved for process afterwards. After that, in the HVACPTL0_EVENT_TIMEOUT_EVT event processing function, the structure will be loaded and the pointer as well. The memory is free with the pointer loaded after processing.

    This is how I imagine the application should works...  Apparently it doesn't..sigh...Can you help me on this? 

  • If the problem is "osal_mem_free(PTL0_sendBuf)", you can try to following code.

    if (PTL0_sendBuf!=NULL)
    osal_mem_free(PTL0_sendBuf);
  • Still the same... program goes to osal_mem_free(); then jump to halAssertHazardLights...
  • Where do you do memory allocation for PTL0_sendBuf?
  • In Device_annuce ZDO message handler function. The pointer to the memory was then saved in a ring buffer and read out and release in HVACPTL0_EVENT_TIMEOUT_EVT event process function.
  • I think the problem might be "ptl0_sendMsg(*PTL0_sendBuf);". You do "osal_mem_free(PTL0_sendBuf);" before PTL0_sendBuf is really used by UART. Try to comment out "ptl0_sendMsg(*PTL0_sendBuf);" and test again.
  • Opoos.. Still doesn't work... I agree with you, it should be a problem. I've comment out "ptl0_sendMsg(*PTL0_sendBuf);" but problem still exist. Same same...
  • I would suggest you to use a static array for PTL0_sendBuf instead of doing memory allocation.
  • Okay then, I'll use static array... Appreciate for your help!!
  • You are welcome.