• 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】协调器网络的建立

  • 相关阅读:
    协程—gevent模块的使用
    协程—概念以及基本使用
    Python—同步和互斥
    Hugo博客搭建
    Linux编辑利器-Vim
    Linux命令与Shell
    python入门基础
    .netcore程序在linux下用supervisor守护
    .netcore中添加Swagger
    winform或wpf中全局异常捕获
  • 原文地址:https://www.cnblogs.com/gjianw217/p/4496093.html
Copyright © 2020-2023  润新知