Ztack学习笔记(4)-系统网络分析

 协调器的组网,终端设备和路由设备发现网络以及加入网络

//第一步:Z-Stack  由 main()函数开始执行,main()函数共做了 2 件事:一是系统初始化,另外一件是开始执行轮转查询式操作系统
 int main( void )                          
{
  .......
  // Initialize the operating system
  osal_init_system();              //第二步,操作系统初始化
......
  osal_start_system();   //初始化完系统任务事件后,正式开始执行操作系统
  ......
} 

//第二步,进入 osal_init_system()函数,执行操作系统初始化
uint8 osal_init_system( void )      //初始化操作系统,其中最重要的是,初始化操作系统的任务
{
  // Initialize the Memory Allocation System
  osal_mem_init();

  // Initialize the message queue
  osal_qHead = NULL;

  // Initialize the timers
  osalTimerInit();

  // Initialize the Power Management System
  osal_pwrmgr_init();

  // Initialize the system tasks.
  osalInitTasks();                 //第三步,执行操作系统任务初始化函数

  // Setup efficient search for the first free block of heap.
  osal_mem_kick();
  return ( SUCCESS );
}

//第三步,进入osalInitTasks()函数,执行操作系统任务初始化
void osalInitTasks( void )       //第三步,初始化操作系统任务
{
  uint8 taskID = 0;
  tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
  osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));

  //任务优先级由高向低依次排列,高优先级对应 taskID 的值反而小
  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++ );   //第四步,ZDApp层,初始化  ,执行ZDApp_init函数后,如果是协调器将建立网络,如果是终端设备将加入网络。
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )  
  ZDNwkMgr_Init( taskID++ );
#endif
  SerialApp_Init( taskID );  //应用层SerialApp层初始化,需要用户考虑     在此处设置了一个按键触发事件,
                                         //当有按键按下的时候,产生一个系统消息
}                            

//第四步,进入ZDApp_init()函数,执行ZDApp层初始化
//The first step
void ZDApp_Init( uint8 task_id )     //The first step,ZDApp层初始化。
{
  // 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 );

#if defined( ZDO_USERDESC_RESPONSE )
  ZDApp_InitUserDesc();
#endif // ZDO_USERDESC_RESPONSE
 
  // Start the device?
  if ( devState != DEV_HOLD )        //devState 初值为DEV_INIT , 所以在初始化ZDA层时,就执行该条件语句
  {
    ZDOInitDevice( 0 );     //The second step, 接着转到ZDOInitDevice()函数,执行The third step;
  }
  else
  {
    // Blink LED to indicate HOLD_START
    HalLedBlink ( HAL_LED_4, 0, 50, 500 );
  }
  ZDApp_RegisterCBs();
} /* ZDApp_Init() */

//The third step,执行ZDOInitDevice()函数,执行设备初始化
uint8 ZDOInitDevice( uint16 startDelay )  //The third step, ZDO层初始化设备,
{
   .......
// Trigger the network start
  ZDApp_NetworkInit( extendedDelay );   //网络初始化,跳到相应的函数里头,执行The fourth step
   .......
}

//The fouth step,执行 ZDApp_NetWorkInit()函数
void ZDApp_NetworkInit( uint16 delay )  //The fourth step,网络初始化
{
  if ( delay )
  {
    // Wait awhile before starting the device
    osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay );    //发送ZDO_NETWORK_INIT(网络初始化)消息到 ZDApp层,转到                                                                                                                  //ZDApp层,执行The fifth step  , ZDApp_event_loop() 函数
  }                                                              
  else
  {
    osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );
  }
}

//The fifth step,转到ZDApp_event_loop()函数
UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events )
{
if ( events & ZDO_NETWORK_INIT )   //The fivth step,网络初始化事件处理
  {
    // Initialize apps and start the network
    devState = DEV_INIT;

    //设备逻辑类型,启动模式,信标时间,超帧长度,接着转到The sixth step,去启动设备,接着执行The sixth step,转到ZDO_StartDevice()
    ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType, devStartMode,  
                     DEFAULT_BEACON_ORDER, DEFAULT_SUPERFRAME_ORDER );

    // Return unprocessed events
    return (events ^ ZDO_NETWORK_INIT);
  }
}

//The sixth step,执行ZDO_StartDevice()函数,启动设备
void ZDO_StartDevice( byte logicalType, devStartModes_t startMode, byte beaconOrder, byte superframeOrder ) //The sixth step
{
......
 if ( ZG_BUILD_COORDINATOR_TYPE && logicalType == NODETYPE_COORDINATOR )   //当设备作为协调器时,执行这个条件语句。
  {
    if ( startMode == MODE_HARD )
    {
      devState = DEV_COORD_STARTING;  

       //向网络层发送网络形成请求。当网络层执行 NLME_NetworkFormationRequest()建立网络后,将给予 ZDO层反馈信息。
       // 接着转到The seventh step,去执行ZDApp层的  ZDO_NetworkFormationConfirmCB()函数
      ret = NLME_NetworkFormationRequest( zgConfigPANID, zgApsUseExtendedPANID, zgDefaultChannelList,
                                          zgDefaultStartingScanDuration, beaconOrder,
                                          superframeOrder, false );
    }
if ( ZG_BUILD_JOINING_TYPE && (logicalType == NODETYPE_ROUTER || logicalType == NODETYPE_DEVICE) ) //当为终端设备或路由时
  {
    if ( (startMode == MODE_JOIN) || (startMode == MODE_REJOIN) )
    {
      devState = DEV_NWK_DISC;

      // zgDefaultChannelList与协调器形成网络的通道号匹配。 网络发现请求。
      // 继而转到ZDO_NetworkDiscoveryConfirmCB()函数
      ret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList, zgDefaultStartingScanDuration );
    }
  }
......
}

//The seventh step,分两种情况,1.协调器   2.路由器或终端设备
 1)协调器
void ZDO_NetworkFormationConfirmCB( ZStatus_t Status ) //The seventh step,给予ZDO层网络形成反馈信息(协调器)
{
osal_set_event( ZDAppTaskID, ZDO_NETWORK_START ); //发送网络启动事件 到 ZDApp层,接着转到ZDApp_event_loop()函数                                 
......
}

UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events )
{
......
if ( events & ZDO_NETWORK_START )  // 网络启动事件
    {
      ZDApp_NetworkStartEvt();    //网络启动事件,接着跳转到The ninth step, 执行ZDApp_NetworkStartEvt()函数
  ......
    }
}

void ZDApp_NetworkStartEvt( void )     //处理网络启动事件
{
......
 osal_pwrmgr_device( PWRMGR_ALWAYS_ON );                           //电源总是上电
 osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT ); //设置网络状态改变事件,发送到ZDApp层,转到The tenth step,去
 ......                                                                                                 // ZDApp_event_loop()函数,找到相对应的网络改变事件。
}


2)路由器或终端设备
//The seventh step(终端设备), 当发现有网络存在时,网络层将给予 ZDO 层发现网络反馈信息
ZStatus_t ZDO_NetworkDiscoveryConfirmCB( uint8 ResultCount, networkDesc_t *NetworkList )  
{
   .......
  //把网络发现这个反馈消息,发送到ZDA层,转到 ZDApp_ProcessOSALMsg(),执行
  ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_DISC_CNF, sizeof(ZDO_NetworkDiscoveryCfm_t), (uint8 *)&msg );
}

void ZDApp_ProcessOSALMsg( osal_event_hdr_t *msgPtr )
{
   ......
   case ZDO_NWK_DISC_CNF:      // (终端设备),网络发现响应。
   ......
          //当发现有网络存在时,网络层将给予 ZDO 层发现网络反馈信息。然后由网络层发起加入网络请求,
          //如加入网络成功,则网络层将给予 ZDO 层加入网络反馈,执行NLME_JoinRequest()函数。然后转到 
          //The ninth step,执行 ZDO_JoinConfirmCB()函数
            if ( NLME_JoinRequest( ((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->extendedPANID,
                 BUILD_UINT16( ((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->panIdLSB, ((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->panIdMSB ),
                 ((ZDO_NetworkDiscoveryCfm_t *)msgPtr)->logicalChannel,
                 ZDO_Config_Node_Descriptor.CapabilityFlags ) != ZSuccess )
            {
              ZDApp_NetworkInit( (uint16)(NWK_START_DELAY
                  + ((uint16)(osal_rand()& EXTENDED_JOINING_RANDOM_MASK))) );
            }
          ......
   }

void ZDO_JoinConfirmCB( uint16 PanId, ZStatus_t Status )  //The ninth step(终端设备), 终端设备加入网络响应。
{
......
//将ZDO_NWK_JOIN_IND事件发送到ZDA层,执行 ZDApp_ProcessOSALMsg()函数。
  ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_JOIN_IND, sizeof(osal_event_hdr_t), (byte*)NULL );
}

void ZDApp_ProcessOSALMsg( osal_event_hdr_t *msgPtr )
{
......
 case ZDO_NWK_JOIN_IND:            //终端设备,加入网络反馈信息事件。
      if ( ZG_BUILD_JOINING_TYPE && ZG_DEVICE_JOINING_TYPE )
      {
        ZDApp_ProcessNetworkJoin(); //转到ZDApp_ProcessNetworkJoin(),执行ZDApp_ProcessNetworkJoin()函数。
      }
      break;
......
} 


在执行ZDApp_ProcessNetworkJoin()函数的时候,要分两种情况,一种是终端设备,一种是路由器:
3)终端设备:
void ZDApp_ProcessNetworkJoin( void )  //处理网络加入事件。
{
......
if ( nwkStatus == ZSuccess )
    {
      //设置 ZDO_STATE_CHANGE_EVT ,发送到ZDA层,执行 ZDApp_event_loop()函数。
      osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT ); 
    }
......
}

4)路由器:
void ZDApp_ProcessNetworkJoin( void )  
{
......
  if ( ZSTACK_ROUTER_BUILD )
        {
          // NOTE: first two parameters are not used, see NLMEDE.h for details
          if ( ZDO_Config_Node_Descriptor.LogicalType != NODETYPE_DEVICE )
          {
            NLME_StartRouterRequest( 0, 0, false );               //路由启动请求
          }
        }
......
}

void ZDO_StartRouterConfirmCB( ZStatus_t Status )
{
  nwkStatus = (byte)Status;
......
  osal_set_event( ZDAppTaskID, ZDO_ROUTER_START );
}


UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events )
{
  if ( events & ZDO_ROUTER_START ) 
    {
      if ( nwkStatus == ZSuccess )
      {
        if ( devState == DEV_END_DEVICE )
          devState = DEV_ROUTER;                         //设备状态变成路由器
  
        osal_pwrmgr_device( PWRMGR_ALWAYS_ON );
      }
      else
      {
        // remain as end device!!
      }
      osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );     //设置ZDO状态改变事件
  
      // Return unprocessed events
      return (events ^ ZDO_ROUTER_START);
    }
}


//The eighth step,执行ZDO状态改变事件
UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events )
{
.......
if ( events & ZDO_STATE_CHANGE_EVT )  //The eighth step, 网络改变事件,这个事件就是在设备加入网络成功后,
                                                                     //并在网络中的身份确定后产生的一个事件
  {
    ZDO_UpdateNwkStatus( devState );  //更新网络状态,转到The eleventh step,执行 ZDO_UpdateNwkStatus()函数。
  ......
  }
}

//The ninth step,执行ZDO_UpdateNwkStatus()函数,完成网络状态更新
void ZDO_UpdateNwkStatus(devStates_t state)  //The ninth step, 更新网络状态
{
......
      zdoSendStateChangeMsg(state, *(pItem->epDesc->task_id));  //发送状态改变消息到zdo层,这是The tenth step,转到
                                                                                                        //zdoSendStateChangeMsg()函数
.......
  ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();  //调用NLME_GetShortAddr()函数,获得16位短地址。
  (void)NLME_GetExtAddr();  // Load the saveExtAddr pointer.  //获得64位的IEEE地址。

}

//The tenth step,执行zdoSendStateChangeMsg()函数
static void zdoSendStateChangeMsg(uint8 state, uint8 taskId) //The tenth step,
{
  osal_event_hdr_t *pMsg = (osal_event_hdr_t *)osal_msg_find(taskId, ZDO_STATE_CHANGE);

  if (NULL == pMsg)
  {
    if (NULL == (pMsg = (osal_event_hdr_t *)osal_msg_allocate(sizeof(osal_event_hdr_t))))
    {
      // Upon failure to notify any EndPoint of the state change, re-set the ZDO event to
      // try again later when more Heap may be available.
      osal_set_event(ZDAppTaskID, ZDO_STATE_CHANGE_EVT);  //如果ZDO状态没有任何改变,再一次,跳到
                                                                                                        //ZDO_STATE_CHANGE_EVT事件处理函数。
    }
    else
    {
      pMsg->event = ZDO_STATE_CHANGE;      //如果ZDO状态改变了 了,把ZDO_STATE_CHANGE这个消息保存到pMsg
      pMsg->status = state;

      (void)osal_msg_send(taskId, (uint8 *)pMsg);    //转到MT_TASK.C,去执行The eleven step, MT_ProcessIncomingCommand()函数
    }
  }
  ......
}
//The eleventh step,去执行MT_ProcessIncomingCommand()函数
void MT_ProcessIncomingCommand( mtOSALSerialData_t *msg )
{
......
case ZDO_STATE_CHANGE:        //The thirteenth step, 接着跳到MT_ZdoStateChangeCB()函数。 
                                                      //自此,协调器组网形成(终端设备成功加入网络)
         MT_ZdoStateChangeCB((osal_event_hdr_t *)msg);
         break;
......
}

//第五步,//初始化玩系统任务事件后,正是开始执行操作系统,此时操作系统不断的检测有没有任务事件发生,一旦检测到有事件发生,就转 //到相应的处理函数,进行处理。
void osal_start_system( void )  //第五步,正式执行操作系统
{
#if !defined ( ZBIT ) && !defined ( UBIT )
  for(;;)  // Forever Loop     //死循环
#endif
  {
    uint8 idx = 0;
    osalTimeUpdate();
    Hal_ProcessPoll();  // This replaces MT_SerialPoll() and osal_check_timer().
    do {
      if (tasksEvents[idx])  // Task is highest priority that is ready.
      {
        break;        // 得到待处理的最高优先级任务索引号idx
      }
    } while (++idx < tasksCnt);

    if (idx < tasksCnt)
    {
      uint16 events;
      halIntState_t intState;
      HAL_ENTER_CRITICAL_SECTION(intState);  //进入临界区
      events = tasksEvents[idx];             //提取需要处理的任务中的事件
      tasksEvents[idx] = 0;  // Clear the Events for this task.   // 清除本次任务的事件
      HAL_EXIT_CRITICAL_SECTION(intState);   //退出临界区

      events = (tasksArr[idx])( idx, events ); //通过指针调用任务处理函数  , 紧接着跳到相应的函数去处理,此为第五步

      HAL_ENTER_CRITICAL_SECTION(intState);  //进入临界区
      tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.  // 保存未处理的事件
      HAL_EXIT_CRITICAL_SECTION(intState);   //退出临界区
    }
#if defined( POWER_SAVING )     
    else  // Complete pass through all task events with no activity?
    {
      osal_pwrmgr_powerconserve();  // Put the processor/system into sleep
    }
#endif
  }
}
//ZDApp.c
1
void ZDApp_Init( uint8 task_id ) 2 { 3 // Save the task ID 4 ZDAppTaskID = task_id; 5 6 // Initialize the ZDO global device short address storage 7 ZDAppNwkAddr.addrMode = Addr16Bit; 8 ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR;//0xFFFE 9 (void)NLME_GetExtAddr(); // Load the saveExtAddr pointer. 10 11 // Check for manual "Hold Auto Start" 12 ZDAppCheckForHoldKey();检测到有手工置位SW_1则会设置devState = DEV_HOLD,从而避开网络初始化 13 14 // Initialize ZDO items and setup the device - type of device to create. 15 ZDO_Init();//通过判断预编译来开启一些函数功能 16 17 // Register the endpoint description with the AF 18 // This task doesn't have a Simple description, but we still need 19 // to register the endpoint. 20 afRegister( (endPointDesc_t *)&ZDApp_epDesc ); 21 22 #if defined( ZDO_USERDESC_RESPONSE ) 23 ZDApp_InitUserDesc(); 24 #endif // ZDO_USERDESC_RESPONSE 25 26 // Start the device? 27 if ( devState != DEV_HOLD ) //devState 初值为DEV_INIT , 所以在初始化ZDA层时,就执行该条件语句
/*如果devState=DEV_HOLD,则不会调用ZDOInitDevice()来初始化网络
    即不组网也不入网.LED4闪烁等待应用程序来开启设备并初始化网络
  */
28 { 29 ZDOInitDevice( 0 ); 30 } 31 else 32 { 33 ZDOInitDevice( ZDO_INIT_HOLD_NWK_START ); 34 // Blink LED to indicate HOLD_START 35 HalLedBlink ( HAL_LED_4, 0, 50, 500 ); 36 } 37 38 // Initialize the ZDO callback function pointers zdoCBFunc[] 39 ZDApp_InitZdoCBFunc(); 40 41 ZDApp_RegisterCBs(); 42 } /* ZDApp_Init() */
 //ZDApp.c
1
uint8 ZDOInitDevice( uint16 startDelay ) 2 { 3 uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE; 4 uint16 extendedDelay = 0; 5 6 if ( devState == DEV_HOLD ) 7 { 8 // Initialize the RAM items table, in case an NV item has been updated. 9 zgInitItems( FALSE ); 10 } 11 12 ZDConfig_InitDescriptors(); 13 //devtag.071807.todo - fix this temporary solution 14 _NIB.CapabilityFlags = ZDO_Config_Node_Descriptor.CapabilityFlags; 15 16 #if defined ( NV_RESTORE ) 17 // Get Keypad directly to see if a reset nv is needed. 18 // Hold down the SW_BYPASS_NV key (defined in OnBoard.h) 19 // while booting to skip past NV Restore. 20 if ( HalKeyRead() == SW_BYPASS_NV ) 21 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE; 22 else 23 { 24 // Determine if NV should be restored 25 networkStateNV = ZDApp_ReadNetworkRestoreState(); 26 } 27 28 if ( networkStateNV == ZDO_INITDEV_RESTORED_NETWORK_STATE ) 29 { 30 networkStateNV = ZDApp_RestoreNetworkState(); 31 } 32 else 33 { 34 // Wipe out the network state in NV 35 NLME_InitNV(); 36 NLME_SetDefaultNV(); 37 // clear NWK key values 38 ZDSecMgrClearNVKeyValues(); 39 } 40 #endif 41 42 if ( networkStateNV == ZDO_INITDEV_NEW_NETWORK_STATE ) 43 { 44 ZDAppDetermineDeviceType(); 45 46 // Only delay if joining network - not restoring network state 47 extendedDelay = (uint16)((NWK_START_DELAY + startDelay) 48 + (osal_rand() & EXTENDED_JOINING_RANDOM_MASK)); 49 } 50 51 // Initialize the security for type of device 52 ZDApp_SecInit( networkStateNV ); 53 54 if( ZDO_INIT_HOLD_NWK_START != startDelay ) 55 { 56 devState = DEV_INIT; // Remove the Hold state 57 58 // Initialize leave control logic 59 ZDApp_LeaveCtrlInit(); 60 61 // Check leave control reset settings 62 ZDApp_LeaveCtrlStartup( &devState, &startDelay ); 63 64 // Leave may make the hold state come back 65 if ( devState == DEV_HOLD ) 66 { 67 // Set the NV startup option to force a "new" join. 68 zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE ); 69 70 // Notify the applications 71 osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT ); 72 73 return ( ZDO_INITDEV_LEAVE_NOT_STARTED ); // Don't join - (one time). 74 } 75 76 // Trigger the network start 77 ZDApp_NetworkInit( extendedDelay ); //网络初始化,跳到相应的函数里头 78 } 79 80 // set broadcast address mask to support broadcast filtering 81 NLME_SetBroadcastFilter( ZDO_Config_Node_Descriptor.CapabilityFlags ); 82 83 return ( networkStateNV ); 84 }
 1 void ZDApp_NetworkInit( uint16 delay )
 2 {
 3   if ( delay )
 4   {
 5     // Wait awhile before starting the device
 6     osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay );
 7     //发送ZDO_NETWORK_INIT(网络初始化)消息到 ZDApp层,转到                                                                                                                  //ZDApp层,执行The fifth step  , ZDApp_event_loop() 函数
8 } 9 else 10 { 11 osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT ); 12 } 13 }
  1 UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events )
  2 {
  3   uint8 *msg_ptr;
  4 
  5   if ( events & SYS_EVENT_MSG )
  6   {
  7     while ( (msg_ptr = osal_msg_receive( ZDAppTaskID )) )
  8     {
  9       ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr );
 10 
 11       // Release the memory
 12       osal_msg_deallocate( msg_ptr );
 13     }
 14 
 15     // Return unprocessed events
 16     return (events ^ SYS_EVENT_MSG);
 17   }
 18 
 19   if ( events & ZDO_NETWORK_INIT )//网络初始化事件处理
 20   {
 21     // Initialize apps and start the network
 22     devState = DEV_INIT;
 23     osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
 24 
 25     ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType, devStartMode,
 26                      DEFAULT_BEACON_ORDER, DEFAULT_SUPERFRAME_ORDER );
 27 //设备逻辑类型,启动模式,信标时间,超帧长度,去启动设备
 28     // Return unprocessed events
 29     return (events ^ ZDO_NETWORK_INIT);
 30   }
 31 
 32   if ( ZSTACK_ROUTER_BUILD )
 33   {
 34     if ( events & ZDO_NETWORK_START )
 35     {
 36       ZDApp_NetworkStartEvt();
 37 
 38       // Return unprocessed events
 39       return (events ^ ZDO_NETWORK_START);
 40     }
 41 
 42     if ( events & ZDO_ROUTER_START )
 43     {
 44       if ( nwkStatus == ZSuccess )
 45       {
 46         if ( devState == DEV_END_DEVICE )
 47           devState = DEV_ROUTER;
 48 
 49         osal_pwrmgr_device( PWRMGR_ALWAYS_ON );
 50       }
 51       else
 52       {
 53         // remain as end device!!
 54       }
 55       osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
 56 
 57       // Return unprocessed events
 58       return (events ^ ZDO_ROUTER_START);
 59     }
 60   }
 61 
 62   if ( events & ZDO_STATE_CHANGE_EVT )
 63   {
 64     ZDO_UpdateNwkStatus( devState );
 65 
 66     // At start up, do one MTO route discovery if the device is a concentrator
 67     if ( zgConcentratorEnable == TRUE )
 68     {
 69       // Start next event
 70       osal_start_timerEx( NWK_TaskID, NWK_MTO_RTG_REQ_EVT, 100 );
 71     }
 72 
 73     // Return unprocessed events
 74     return (events ^ ZDO_STATE_CHANGE_EVT);
 75   }
 76 
 77   if ( events & ZDO_COMMAND_CNF )
 78   {
 79     // User defined logic
 80 
 81     // Return unprocessed events
 82     return (events ^ ZDO_COMMAND_CNF);
 83   }
 84 
 85   if ( events & ZDO_NWK_UPDATE_NV )
 86   {
 87     ZDApp_SaveNetworkStateEvt();
 88 
 89     // Return unprocessed events
 90     return (events ^ ZDO_NWK_UPDATE_NV);
 91   }
 92 
 93   if ( events & ZDO_DEVICE_RESET )
 94   {
 95 #ifdef ZBA_FALLBACK_NWKKEY
 96     if ( devState == DEV_END_DEVICE_UNAUTH )
 97     {
 98       ZDSecMgrFallbackNwkKey();
 99     }
100     else
101 #endif
102     {
103       // Set the NV startup option to force a "new" join.
104       zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE );
105 
106       // The device has been in the UNAUTH state, so reset
107       // Note: there will be no return from this call
108       SystemResetSoft();
109     }
110   }
111 
112   if ( ZG_SECURE_ENABLED )
113   {
114     return ( ZDApp_ProcessSecEvent( task_id, events ) );
115   }
116   else
117   {
118     // Discard or make more handlers
119     return 0;
120   }
121 }
  //ZDObject.c
1
void ZDO_StartDevice( byte logicalType, devStartModes_t startMode, byte beaconOrder, byte superframeOrder ) 2 { 3 ZStatus_t ret; 4 #if defined ( ZIGBEE_FREQ_AGILITY ) 5 static uint8 discRetries = 0; 6 #endif 7 #if defined ( ZIGBEE_COMMISSIONING ) 8 static uint8 scanCnt = 0; 9 #endif 10 11 ret = ZUnsupportedMode; 12 13 if ( ZG_BUILD_COORDINATOR_TYPE && logicalType == NODETYPE_COORDINATOR )//当设备作为协调器时,执行这个条件语句。 14 { 15 if ( startMode == MODE_HARD ) 16 { 17 devState = DEV_COORD_STARTING; 18 ret = NLME_NetworkFormationRequest( zgConfigPANID, zgApsUseExtendedPANID, zgDefaultChannelList, 19 zgDefaultStartingScanDuration, beaconOrder, 20 superframeOrder, false );

      //向网络层发送网络形成请求。当网络层执行 NLME_NetworkFormationRequest()建立网络后,将给予 ZDO层反馈信息。

      // 接着去执行ZDApp层的 ZDO_NetworkFormationConfirmCB()函数

 21     }
 22     else if ( startMode == MODE_RESUME )
 23     {
 24       // Just start the coordinator
 25       devState = DEV_COORD_STARTING;
 26       ret = NLME_StartRouterRequest( beaconOrder, beaconOrder, false );
 27     }
 28     else
 29     {
 30 #if defined( LCD_SUPPORTED )
 31       HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
 32 #endif
 33     }
 34   }
 35 
 36   if ( ZG_BUILD_JOINING_TYPE && (logicalType == NODETYPE_ROUTER || logicalType == NODETYPE_DEVICE) )//当为终端设备或路由时
 37   {
 38     if ( (startMode == MODE_JOIN) || (startMode == MODE_REJOIN) )
 39     {
 40       devState = DEV_NWK_DISC;
 41

       //zgDefaultChannelList与协调器形成网络的通道号匹配。 网络发现请求。

      // 继而转到ZDO_NetworkDiscoveryConfirmCB()函数

 42   #if defined( MANAGED_SCAN )
 43       ZDOManagedScan_Next();
 44       ret = NLME_NetworkDiscoveryRequest( managedScanChannelMask, BEACON_ORDER_15_MSEC );
 45   #else
 46       ret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList, zgDefaultStartingScanDuration );
 47     #if defined ( ZIGBEE_FREQ_AGILITY )
 48       if ( !( ZDO_Config_Node_Descriptor.CapabilityFlags & CAPINFO_RCVR_ON_IDLE ) &&
 49             ( ret == ZSuccess ) && ( ++discRetries == 4 ) )
 50       {
 51         // For devices with RxOnWhenIdle equals to FALSE, any network channel
 52         // change will not be recieved. On these devices or routers that have
 53         // lost the network, an active scan shall be conducted on the Default
 54         // Channel list using the extended PANID to find the network. If the
 55         // extended PANID isn't found using the Default Channel list, an scan
 56         // should be completed using all channels.
 57         zgDefaultChannelList = MAX_CHANNELS_24GHZ;
 58       }
 59     #endif // ZIGBEE_FREQ_AGILITY
 60     #if defined ( ZIGBEE_COMMISSIONING )
 61       if (startMode == MODE_REJOIN && scanCnt++ >= 5 )
 62       {
 63         // When ApsUseExtendedPanID is commissioned to a non zero value via
 64         // application specific means, the device shall conduct an active scan
 65         // on the Default Channel list and join the PAN with the same
 66         // ExtendedPanID. If the PAN is not found, an scan should be completed
 67         // on all channels.
 68         // When devices rejoin the network and the PAN is not found from
 69         zgDefaultChannelList = MAX_CHANNELS_24GHZ;
 70       }
 71     #endif // ZIGBEE_COMMISSIONING
 72   #endif
 73     }
 74     else if ( startMode == MODE_RESUME )
 75     {
 76       if ( logicalType == NODETYPE_ROUTER )
 77       {
 78         ZMacScanCnf_t scanCnf;
 79         devState = DEV_NWK_ORPHAN;
 80 
 81         /* if router and nvram is available, fake successful orphan scan */
 82         scanCnf.hdr.Status = ZSUCCESS;
 83         scanCnf.ScanType = ZMAC_ORPHAN_SCAN;
 84         scanCnf.UnscannedChannels = 0;
 85         scanCnf.ResultListSize = 0;
 86         nwk_ScanJoiningOrphan(&scanCnf);
 87 
 88         ret = ZSuccess;
 89       }
 90       else
 91       {
 92         devState = DEV_NWK_ORPHAN;
 93         ret = NLME_OrphanJoinRequest( zgDefaultChannelList,
 94                                       zgDefaultStartingScanDuration );
 95       }
 96     }
 97     else
 98     {
 99 #if defined( LCD_SUPPORTED )
100       HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
101 #endif
102     }
103   }
104 
105   if ( ret != ZSuccess )
106   {
107     osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT, NWK_RETRY_DELAY );
108   }
109 }
void ZDO_NetworkFormationConfirmCB( ZStatus_t Status )

网络的格式化
          A:初始化的能量阀值为16。通过设置ZDApp_event_loop任务中的事件ID为ZDO_NETWORK_INIT以便执行B。
          B:调用NLME_NetworkFormationRequest函数进行申请,对申请的回应在程序中没对应的回调处理,猜想回调处理在lib库中处理。在程序找到了两个对申请结果作处理的函数,void ZDO_NetworkFormationConfirmCB( ZStatus_t Status )和void nwk_Status( uint16 statusCode,uint16 statusValue );在两个函数中都有申请的结果。如果不成功则nwk_Status先执行如果成功则ZDO_NetworkFormationConfirmCB先执行。
          C:系统(lib)调用ZDO_NetworkFormationConfirmCB函数,在函数中通过设置ZDApp_event_loop任务中的事件ID为ZDO_NETWORK_START以便执行D。
          D:调用ZDApp_NetworkStartEvt函数,在函数中检测返回的申请结果,如果不成功则能量阀值增加16并将ZDApp_event_loop任务中的事件ID置为ZDO_NETWORK_INIT以便执行B;如果成功则ZDApp_event_loop任务中的事件ID置为ZDO_STATE_CHANGE_EVT以便执行E。
          E:调用ZDO_UpdateNwkStatus函数,函数通过端点表向SampleApp_ProcessEvent任务发送一个ZDO_STATE_CHANGE命令,以便执行F。
          F:设置ZDApp_event_loop任务中的事件ID为SAMPLEAPP_SEND_PERIODIC_MSG_EVT以便执行G。
          G:发送一个定期信息,并设置ZDApp_event_loop任务中的事件ID为SAMPLEAPP_SEND_PERIODIC_MSG_EVT以便执行G。

 参考链接 

【1】Zigbee协议栈学习之串口透明传输实验(SerialApp)流程分析  

【2】协调器网络的建立

原文地址:https://www.cnblogs.com/gjianw217/p/4496093.html