zstack中ZDO层机制

ZDO层的初使化在

void osalInitTasks( void )

{
  uint8 taskID = 0;


  tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
  osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
  macTaskInit( taskID++ );
  nwk_init( taskID++ );
  Hal_Init( taskID++ );
#if defined( MT_TASK )
  MT_TaskInit( taskID++ );
#endif
  APS_Init( taskID++ );
#if defined ( ZIGBEE_FRAGMENTATION )
  APSF_Init( taskID++ );
#endif
  ZDApp_Init( taskID++ );
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
  ZDNwkMgr_Init( taskID++ );
#endif
  Console_Init( taskID++ );
  Comm_UartTaskInit (taskID++);
  App_Init( taskID++);

}

ZDO层的循环事件函数

const pTaskEventHandlerFn tasksArr[] = {
  macEventLoop,
  nwk_event_loop,
  Hal_ProcessEvent,
#if defined( MT_TASK )
  MT_ProcessEvent,
#endif
  APS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )
  APSF_ProcessEvent,
#endif
  ZDApp_event_loop,
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
  ZDNwkMgr_event_loop,
#endif
  Console_ProcessEvent,
  Comm_UartTaskPro,
  App_ProcessEvent
};


先看初使化函数

void ZDApp_Init( uint8 task_id )
{
  // Save the task ID
  ZDAppTaskID = task_id;
  // Initialize the ZDO global device short address storage
  ZDAppNwkAddr.addrMode = Addr16Bit;
  ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR;
  (void)NLME_GetExtAddr();  // Load the saveExtAddr pointer.
  // Check for manual "Hold Auto Start"
  ZDAppCheckForHoldKey();
  // Initialize ZDO items and setup the device - type of device to create.
  ZDO_Init();
  // Register the endpoint description with the AF
  // This task doesn't have a Simple description, but we still need
  // to register the endpoint.
  afRegister( (endPointDesc_t *)&ZDApp_epDesc );//在这里和应用层一样,先通过端点描述符注册端点。这样,从APS层到ZDO层的数据首先到达 afIncomingData函数

 #if defined( ZDO_USERDESC_RESPONSE )
  ZDApp_InitUserDesc();
 #endif // ZDO_USERDESC_RESPONSE
  // Start the device?
  if ( devState != DEV_HOLD )
  {
    ZDOInitDevice( 0 );
  }
  else
  {
    // Blink LED to indicate HOLD_START
    HalLedBlink ( HAL_LED_4, 0, 50, 500 );
  }  
  ZDApp_RegisterCBs();//这个函数下面讲
}

void ZDApp_RegisterCBs( void )//这个函数里注册ZDO从空中来的一些响应簇到ZDAppTaskID
{
#if defined ( ZDO_IEEEADDR_REQUEST ) || defined ( REFLECTOR )
  ZDO_RegisterForZDOMsg( ZDAppTaskID, IEEE_addr_rsp );
#endif
#if defined ( ZDO_NWKADDR_REQUEST ) || defined ( REFLECTOR )
  ZDO_RegisterForZDOMsg( ZDAppTaskID, NWK_addr_rsp );
#endif  
#if ZG_BUILD_COORDINATOR_TYPE
  ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_rsp );
  ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_rsp );
  ZDO_RegisterForZDOMsg( ZDAppTaskID, End_Device_Bind_req );
#endif
#if defined ( REFLECTOR )
  ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_req );
  ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_req );
#endif  
}

ZStatus_t ZDO_RegisterForZDOMsg( uint8 taskID, uint16 clusterID )

//从函数的内容可以知道,注册一个簇实际就是在zdoMsgCBs链表中增加一个元素, typedef struct{void *next;uint8 taskID;uint16 clusterID;} ZDO_MsgCB_t;

{
  ZDO_MsgCB_t *pList;
  ZDO_MsgCB_t *pLast;
  ZDO_MsgCB_t *pNew;


  // Look for duplicate
  pList = pLast = zdoMsgCBs;
  while ( pList )
  {
    if ( pList->taskID == taskID && pList->clusterID == clusterID )
    {
      return ( ZSuccess );
    }
    pLast = pList;
    pList = (ZDO_MsgCB_t *)pList->next;
  }
  // Add to the list
  pNew = (ZDO_MsgCB_t *)osal_mem_alloc( sizeof ( ZDO_MsgCB_t ) );
  if ( pNew )
  {
    pNew->taskID = taskID;
    pNew->clusterID = clusterID;
    pNew->next = NULL;
    if ( zdoMsgCBs )
    {
      pLast->next = pNew;
    }
    else
    {
      zdoMsgCBs = pNew;
    }
    return ( ZSuccess );
  }
  else
  {
    return ( ZMemError );
  }
}


在ZDApp_event_loop中的SYS_EVENT_MSG事件中会调用ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr )函数。这个函数首先会对到来的消息做判断,如果消息是从APS层过来的(AF_INCOMING_MSG_CMD),则会调用ZDP_IncomingData( (afIncomingMSGPacket_t *)msgPtr ):

void ZDP_IncomingData( afIncomingMSGPacket_t *pData )
{
  uint8 x = 0;
  uint8 handled;
  zdoIncomingMsg_t inMsg;


  inMsg.srcAddr.addrMode = Addr16Bit;
  inMsg.srcAddr.addr.shortAddr = pData->srcAddr.addr.shortAddr;
  inMsg.wasBroadcast = pData->wasBroadcast;
  inMsg.clusterID = pData->clusterId;
  inMsg.SecurityUse = pData->SecurityUse;
  inMsg.asduLen = pData->cmd.DataLength-1;
  inMsg.asdu = pData->cmd.Data+1;
  inMsg.TransSeq = pData->cmd.Data[0];
  inMsg.macDestAddr = pData->macDestAddr;
  handled = ZDO_SendMsgCBs( &inMsg );//这个函数会判断到来的消息对应的簇是否为response,并且是否已经在zdoMsgCBs链表中注册过,如果注册过,则把这条消息       // copy到ZDO_CB_MSG,再发给ZDApptask任务。


#if (defined MT_ZDO_CB_FUNC)
#if !defined MT_TASK
  if (zgZdoDirectCB)
#endif
  {
    MT_ZdoDirectCB( pData, &inMsg );
  }
#endif


  while ( zdpMsgProcs[x].clusterID != 0xFFFF )
  {
    if ( zdpMsgProcs[x].clusterID == inMsg.clusterID )//判断这条消息是否为request消息,如果是request消息则在zdpMsgProcs结构体数组中通过指针调用对应簇ID的函数对其

   //做出相应的响应,然后直接return函数
    {
      zdpMsgProcs[x].pFn( &inMsg );
      return;
    }
    x++;
  }


  // Handle unhandled messages
  if ( !handled ) //如果在zdoMsgCBs链表中没有这条消息的簇ID,并且在adpMsgProcs结构体数组中也没有发现这条消息对应的簇ID,那么就认为这条ZDO消息不被设备支持,

   //即调用ZDApp_inMsgCB(&inMsg)函数做错误处理。
    ZDApp_InMsgCB( &inMsg );
}


void ZDApp_ProcessOSALMsg( osal_event_hdr_t *msgPtr )
{
  // Data Confirmation message fields
  uint8 sentEP;       // This should always be 0
  uint8 sentStatus;
  afDataConfirm_t *afDataConfirm;
  uint8 tmp;


  switch ( msgPtr->event )
  {
    // Incoming ZDO Message
    case AF_INCOMING_MSG_CMD:
      ZDP_IncomingData( (afIncomingMSGPacket_t *)msgPtr );
      break;
      
    case ZDO_CB_MSG: //从上面的注释可以知道,进入这个case的消息首先都会进入AF_INCOMING_MSG_CMD,只有ZDO在AF_INCOMING_MSG_CMD中发现从APS过来          // 的消息是在zdoMsgCBs链表中注册过的response簇,才会把这个消息通过OSAL机制设置为ZDO_CB_MSG事件COPY到这里。
      ZDApp_ProcessMsgCBs( (zdoIncomingMsg_t *)msgPtr );
      break;

      .....

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值