Zigbee網絡設備啓動—主要函數說明

 

Zigbee網絡設備啓動—基本問題說明網絡

 

Zigbee網絡設備啓動流程—終端(自啓動模式)app

Zigbee網絡設備啓動—主要函數說明  

2010-07-09 20:32:17|  分類: Zigbee |  標籤: |舉報 |字號 訂閱 函數

使用的協議棧版本信息: ZigBee2006\ZStack-1.4.3-1.2.1oop

一、ZDApp_Init()及其中幾個函數的說明.
(1)ZDApp_Init()
****************************************
void ZDApp_Init( byte task_id )
{
  uint8 capabilities;
ui

  // Save the task ID
  ZDAppTaskID = task_id;
this

  // Initialize the ZDO global device short address storage
  ZDAppNwkAddr.addrMode = Addr16Bit;
  ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR;  //0xFFFE
  (void)NLME_GetExtAddr(); 
// Load the saveExtAddr pointer.
spa

  // Check for manual"Hold Auto Start"
  //檢測到有手動設置SW_1則會設置devState = DEV_HOLD,從而避開網絡初始化

  ZDAppCheckForHoldKey();
指針

  // Initialize ZDO items and setup the device - type of device to create.
  ZDO_Init(); 
//經過預編譯來初始化一些功能函數.
rest


  // 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 );
orm

#if defined( ZDO_USERDESC_RESPONSE )
  ZDApp_InitUserDesc();
#endif
// ZDO_USERDESC_RESPONSE

  // set broadcast address mask to support broadcast filtering
  NLME_GetRequest(nwkCapabilityInfo, 0, &capabilities);
  NLME_SetBroadcastFilter( capabilities );

  // Start the device?
  if ( devState != DEV_HOLD )
  {
    ZDOInitDevice( 0 );
  }
 
/*若是devState=DEV_HOLD,則不會調用ZDOInitDevice()來初始化網絡
    不組網也不進網.LED4閃爍指示這是一個非自動啓動模式,等待應
    用程序來開啓是網絡設備*/

  else
  {
    // Blink LED to indicate HOLD_START
    HalLedBlink ( HAL_LED_4, 0, 50, 500 );
  }

  ZDApp_RegisterCBs();
}
****************************************
這裏說明三個函數:
ZDAppCheckForHoldKey()
ZDO_Init()
ZDOInitDevice( 0 )

(1)ZDAppCheckForHoldKey()
**************************
void ZDAppCheckForHoldKey( void )
{
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
  //我的認爲:能夠直接經過讀取按鍵來看是否須要採用HOLD_START模式
  //若是發現SW_1按下(普通按鍵吧)/向上(Joystick up),則設置DEV_HOLD;
  // Get Keypad directly to see if a HOLD_START is needed.
  // Hold down the SW_BYPASS_START key (see OnBoard.h)
  // while booting to avoid starting up the device.
  if ( HalKeyRead () == SW_BYPASS_START)  //HAL_KEY_SW_1
  {
    // Change the device state to HOLD on start up
    devState = DEV_HOLD;
  }
#endif // HAL_KEY
}
參見基本問題說明3.
*************************
(2)、ZDO_Init()
*************************
void ZDO_Init( void )
{
  /*
  //REFLECTOR若是定義了這個編譯選項則使用「源綁定」,
  In the Zigbee 2006 release,the binding mechanism is implemented in
  all devices and is called source binding.綁定機制能夠在全部設備中實現,
  04版的只能在協調器中實現.*/
  // Initialize ZD items
  #if defined ( REFLECTOR )
  ZDO_EDBind = NULL;
  #endif

  // Setup the device - type of device to create.
  ZDODeviceSetup();
}
*************************
看下ZDODeviceSetup(),具體見各節點啓動流程記錄.
*************************
//Call set functions depending on the type of device compiled.
//根據編譯選項來設置;好比simpleApp中的燈節點,預編譯了ZDO_COORDINATOR和
//REFLECTOR和SOFT_START,所以會根據這些來選擇開啓一些函數功能.

static void ZDODeviceSetup( void )
{
#if defined( ZDO_COORDINATOR ) //編譯了ZDO_COORDINATOR
  NLME_CoordinatorInit();
#endif

#if defined ( REFLECTOR ) //編譯了REFLECTOR
  #if defined ( ZDO_COORDINATOR ) //編譯了REFLECTOR且編譯了ZDO_COORDINATOR
    APS_ReflectorInit( APS_REFLECTOR_PUBLIC );
  #else //編譯了REFLECTOR且編譯了路由器或終端
    APS_ReflectorInit( APS_REFLECTOR_PRIVATE ); //路由器/終端
  #endif
#endif

    //沒有編譯ZDO_COORDINATOR或者編譯了SOFT_START
#if !defined( ZDO_COORDINATOR ) || defined( SOFT_START )
  NLME_DeviceJoiningInit();
#endif
}
*************************
(3)、ZDOInitDevice()
*************************
uint8 ZDOInitDevice( uint16 startDelay )
{
    //初始化設備網絡狀態爲ZDO_INITDEV_NEW_NETWORK_STATE:新的網絡狀態.
    //可能意味着ZCD_NV_STARTUP_OPTION不能恢復,或沒有任何網絡狀態恢復
  uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
  uint16 extendedDelay = 0;

  devState = DEV_INIT;    // Remove the Hold state
 
  //----------------------------------
  // Initialize leave control logic
  //函數讀取NV項目ZCD_NV_LEAVE_CTRL的值,ZDApp_LeaveCtrl指向這個值

  ZDApp_LeaveCtrlInit();

  // Check leave control reset settings
  //設備的斷開會形成DEV_HOLD狀態,這裏面設置的.

  ZDApp_LeaveCtrlStartup( &devState, &startDelay );

  // Leave may make the hold state come back
  //以上兩個函數設置了對設備離開時的控制,若是有延時則延時,沒有則
  //把設備狀態設爲DEV_HOLD

  if ( devState == DEV_HOLD )
    //ZDO_INITDEV_LEAVE_NOT_STARTED:該設備沒有在網絡中,下次調用才啓用.
    return ( ZDO_INITDEV_LEAVE_NOT_STARTED );   // Don't join - (one time).
  //----------------------------------

#if defined ( NV_RESTORE )
  // Get Keypad directly to see if a reset nv is needed.
  // Hold down the SW_BYPASS_NV key (defined in OnBoard.h)
  // while booting(引導) to skip past NV Restore.
  if ( HalKeyRead() == SW_BYPASS_NV )
    //SW_BYPASS_NV按鍵處於按下狀態時,則避開網絡層的NV存儲
    networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE; //設備網絡狀態爲新的網絡狀態
 
  else
  {
    // Determine if NV should be restored
    //函數返回的設備網絡狀態要麼是新的網絡狀態;要麼是恢復的網絡狀態;以此
    //來肯定要不要讀取NV裏相應條目來恢復網絡先前狀態
    networkStateNV = ZDApp_ReadNetworkRestoreState();
  }

   //若是設備的網絡狀態爲恢復的網絡狀態
  if ( networkStateNV == ZDO_INITDEV_RESTORED_NETWORK_STATE )
  {
    //恢復設備先前的網絡狀態參數
    //設置devStartMode = MODE_RESUME!!!!

    networkStateNV = ZDApp_RestoreNetworkState();
  }
  else //若是設備的網絡狀態爲新的網絡狀態,在下面進行處理
  {
    // Wipe out(清除) the network state in NV
    NLME_InitNV();
    NLME_SetDefaultNV();  //設置默認NV條目
  }
#endif

  //若是設備的網絡狀態爲新的網絡狀態
  if ( networkStateNV == ZDO_INITDEV_NEW_NETWORK_STATE )
  {
    //根據預編譯來設置設備新的網絡狀態參數
    ZDAppDetermineDeviceType(); 
/*!!!!*/

    // Only delay if joining network - not restoring network state
    extendedDelay = (uint16)((NWK_START_DELAY + startDelay)
              + (osal_rand() & EXTENDED_JOINING_RANDOM_MASK));
  }

  // Initialize device security
  ZDApp_SecInit( networkStateNV );

  // Trigger the network start
  ZDApp_NetworkInit( extendedDelay );

  return ( networkStateNV );
}
*************************
看下五個函數:
ZDApp_LeaveCtrlInit()
ZDApp_ReadNetworkRestoreState()
ZDApp_RestoreNetworkState()
ZDAppDetermineDeviceType()
ZDApp_NetworkInit( extendedDelay )

(3.1)ZDApp_LeaveCtrlInit()
*************************
void ZDApp_LeaveCtrlInit( void )
{
  uint8 status;


  // Initialize control state
  ZDApp_LeaveCtrl = ZDAPP_LEAVE_CTRL_INIT; 
//0

  //初始化一個NV條目.這個函數檢查一個NV條目的存在與否.
  //若是不存在,它將被創建和初始化隨着數據一塊兒傳給函數,
  //這個函數必須在調用osal_nv_read() or osal_nv_write()以前被調用
  status = osal_nv_item_init( ZCD_NV_LEAVE_CTRL,   //用戶定義的條目ID
                              sizeof(ZDApp_LeaveCtrl),                 //條目的大小
                              &ZDApp_LeaveCtrl );                        
//指向條目初始化的數據

  if ( status == ZSUCCESS ) //這個NV條目存在,則把這個條目值讀出來,ZDApp_LeaveCtrl指向它
  {
    // Read saved control
    osal_nv_read( ZCD_NV_LEAVE_CTRL,  //用戶定義的項目ID
                  0,                                                  //Memory offset into item in bytes.
                  sizeof( uint8 ),                             //條目長度
                  &ZDApp_LeaveCtrl);                  //數據保存緩衝區指針
  }
}
*************************
(3.2)ZDApp_ReadNetworkRestoreState()
若是預編譯了NV_RESTORE而且沒有手工設置避開NV存儲機制,則經過這個函數來判斷是否須要恢復設備原先的網絡狀態.
*************************
//返回要麼是新的網絡狀態;要麼是恢復的網絡狀態
//返回默認爲恢復的狀態,但若是從讀取ZCD_NV_STARTUP_OPTION這個NV條目中
//讀取出來的設備網絡狀態是ZCD_STARTOPT_DEFAULT_NETWORK_STATE,則返回
//新的網絡狀態ZDO_INITDEV_NEW_NETWORK_STATE
uint8 ZDApp_ReadNetworkRestoreState( void )
{                        //設備的網絡狀態爲恢復的網絡狀態
  uint8 networkStateNV = ZDO_INITDEV_RESTORED_NETWORK_STATE;

  // Look for the New Network State option.  默認的網絡狀態
  if ( zgReadStartupOptions() & ZCD_STARTOPT_DEFAULT_NETWORK_STATE )
  {
    //網絡狀態初始化,即新的網絡狀態,可能意味着沒有任何網絡狀態恢復
    networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
  }

  return ( networkStateNV );
}
*************************
(3.3)ZDApp_RestoreNetworkState()
若是3.2的函數獲得的networkStateNV爲恢復的網絡狀態,則經過這個函數來讀取存儲在NV裏的先前的網絡狀態.
*************************
uint8 ZDApp_RestoreNetworkState( void )
{
  …………

  // Initialize NWK NV items
  nvStat = NLME_InitNV();

  if ( nvStat != NV_OPER_FAILED )
  {
    if ( NLME_RestoreFromNV() )
    {
      // Are we a coordinator
      //設備的網絡狀態爲恢復的網絡狀態則恢復先前網絡狀態參數
      //先判斷若是短地址是0則設置設備邏輯類型爲協調器,並設置
      //devStartMode = MODE_RESUME,其它狀況設置devStartMode = MODE_RESUME
      ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();
      if ( ZDAppNwkAddr.addr.shortAddr == 0 )  //若是短地址是0,即協調器
      {
        ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR; //!!!!!
      }
      devStartMode = MODE_RESUME; //MODE_RESUME!!!!!!!!
    }
    else
      nvStat = NV_ITEM_UNINIT;

   …………

  if ( nvStat == ZSUCCESS )
    return ( ZDO_INITDEV_RESTORED_NETWORK_STATE );//說明設備的網絡狀態已經恢復
  else
    return ( ZDO_INITDEV_NEW_NETWORK_STATE );
}
*************************
(3.4)ZDAppDetermineDeviceType()
若是設備的網絡狀態爲新的網絡狀態(第一種狀況:未編譯NV_RESTORE則在ZDOInitDevice()開頭初始化爲ZDO_INITDEV_NEW_NETWORK_STATE;第二種狀況:編譯了NV_RESTORE但ZDApp_ReadNetworkRestoreState()獲得的設備網絡狀態爲ZDO_INITDEV_NEW_NETWORK_STATE,即不能恢復或無狀態恢復.).這個函數僅適用於編譯了SOFT_START的設備,不支持終端設備.好比對於自動啓動模式的SampleApp,沒有編譯SOFT_START.所以本函數對其沒做用.具體見各種型設備啓動流程.
*************************

 * @fn      ZDAppDetermineDeviceType()
 *
 * @brief   Determines the type of device to start.  Right now
 *          this only works with the SOFT_START feature.  So it doesn't
 *          support the end device type.
 *          //終端邏輯類型只能做爲終端
 */

//像simpleApp這個例子中,燈節點和中心收集節點都同時預編譯了
//SOFT_START和HOLD_AUTO_START;而開關節點和傳感器節點都只預編譯了
//HOLD_AUTO_START;
//開關節點和傳感器節點不管按哪一個鍵都是做爲終端設備啓動的
//而燈節點和中心收集節點能夠選擇做爲協調器或路由器.
void ZDAppDetermineDeviceType( void )
{
  /*
  像simpleApp中燈節點和中心收集節點都編譯了SOFT_START,
  zgDeviceLogicalType在ZGlobals.h中被初始化爲ZG_DEVICETYPE_SOFT.而像
  開關節點和傳感器節點沒有編譯SOFT_START,則zgDeviceLogicalType被初始化爲
  ZG_DEVICETYPE_ENDDEVICE.以前卡在這裏很長時間,由於像燈節點和中心收集節點
  編譯過SOFT_START,那zgDeviceLogicalType不就等於ZG_DEVICETYPE_SOFT,最終在
  這個函數裏也只能執行devStartMode = MODE_JOIN這一句,這與燈節點和中心收集
  節點能夠經過按鍵來選擇做爲協調器或路由器不符,糾結了好久,最後才發現,在按鍵
  選擇設備的邏輯類型後,會把這個邏輯類型值寫入NV條目ZCD_NV_LOGICAL_TYPE,而
  ZDO全局變量zgDeviceLogicalType等於NV條目ZCD_NV_LOGICAL_TYPE的值,經過按鍵
  選擇邏輯類型會改變zgDeviceLogicalType的值.好比燈節點按K1選擇設備的邏輯類型
  爲協調器ZG_DEVICETYPE_COORDINATOR,寫入NV條目ZCD_NV_LOGICAL_TYPE存儲,則此時
zgDeviceLogicalType的值即爲  ZG_DEVICETYPE_COORDINATOR!!!見基本問題說明5.
  */

  if ( zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE )
    return;

#if defined ( SOFT_START )//
  if ( zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR )
  {
    devStartMode = MODE_HARD;     // Start as a coordinator
    ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR;
  }
  else
  {
    if ( zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER )
    {
      softStartAllowCoord = FALSE;  // Don't allow coord to start
      continueJoining = TRUE;
    }
   
    devStartMode = MODE_JOIN;     // Assume joining
  }
#endif // SOFT_START
}
*************************
(3.5)ZDApp_NetworkInit( extendedDelay )
函數設置觸發事件ZDO_NETWORK_INIT.
*************************
void ZDApp_NetworkInit( uint16 delay )
{
  if ( delay )
  {
    // Wait awhile before starting the device
    osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay );  //須要延時
  }
  else
  {
    osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );  //不需延時
  }
}
*************************

****************************************
二、ZDO_StartDevice()
ZDApp_event_loop()對事件ZDO_NETWORK_INIT處理以下:
*************************
if ( events & ZDO_NETWORK_INIT )
  {
    // Initialize apps and start the network
    devState = DEV_INIT;
    ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType, devStartMode,
                     DEFAULT_BEACON_ORDER, DEFAULT_SUPERFRAME_ORDER );

    // Return unprocessed events
    return (events ^ ZDO_NETWORK_INIT);
  }
*************************
兩個重要的網絡狀態參數:ZDO_Config_Node_Descriptor.LogicalType和devStartMode,
ZDO_Config_Node_Descriptor.LogicalType的初始化見基本問題說明6.devStartMode的初始化見4.但兩個參數的值能夠經過函數(3.3)ZDApp_RestoreNetworkState()[若是編譯了NV_RESTORE]和函數(3.4)ZDAppDetermineDeviceType()來改變.
*************************
void ZDO_StartDevice( byte logicalType, devStartModes_t startMode, byte beaconOrder, byte superframeOrder )
{
  ZStatus_t ret;

  ret = ZUnsupportedMode;

#if defined(ZDO_COORDINATOR)

  if ( logicalType == NODETYPE_COORDINATOR )
  {
    if ( startMode == MODE_HARD ) //MODE_HARD
    {
      devState = DEV_COORD_STARTING;  //Started as Zigbee Coordinator
      ret = NLME_NetworkFormationRequest( zgConfigPANID, zgDefaultChannelList,
                                          zgDefaultStartingScanDuration, beaconOrder,
                                          superframeOrder, false );
    }
    else if ( startMode == MODE_RESUME )  //MODE_RESUME 恢復
    {
      // Just start the coordinator
      devState = DEV_COORD_STARTING;
      ret = NLME_StartRouterRequest( beaconOrder, beaconOrder, false );
    }
    else  //錯誤,啓動模式未知
    {
      …………
    }
  }
#endif
  // !ZDO_COORDINATOR


  if ( logicalType == NODETYPE_ROUTER || logicalType == NODETYPE_DEVICE )
  {
    if ( (startMode == MODE_JOIN) || (startMode == MODE_REJOIN) )
    {
      devState = DEV_NWK_DISC;  
//Discovering PAN's to join

  #if defined( MANAGED_SCAN )
      ZDOManagedScan_Next();
      ret = NLME_NetworkDiscoveryRequest( managedScanChannelMask, BEACON_ORDER_15_MSEC );
  #else
      ret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList, zgDefaultStartingScanDuration );
  #endif
    }
    else if ( startMode == MODE_RESUME )//MODE_RESUME 恢復
    {
      if ( logicalType == NODETYPE_ROUTER )
      {
        …………
        nwk_ScanJoiningOrphan(&scanCnf);

        ret = ZSuccess;
      }
      else
      {
        devState = DEV_NWK_ORPHAN;  //孤兒
        ret = NLME_OrphanJoinRequest( zgDefaultChannelList,
                                      zgDefaultStartingScanDuration );
      }
    }
    else
    {
      …………
    }
  }
  …………
}
*************************

三、協調器建網,路由器/終端入網的回調函數
(1)ZDO_NetworkFormationConfirmCB():協調器創建網絡請求的回調函數
 * @brief       This function reports the results of the request to
 *              initialize a coordinator in a network.
 *
 * @param       Status - Result of NLME_NetworkFormationRequest()

(2)ZDO_StartRouterConfirmCB():做爲路由器啓動請求的回調函數
 * @brief       This function reports the results of the request to
 *              start functioning as a router in a network.
 *
 * @param       Status - Result of NLME_StartRouterRequest()

(3)ZDO_JoinConfirmCB():路由器/終端加入網絡請求的回調函數
 * @brief       This function allows the next hight layer to be notified
 *              of the results of its request to join itself or another
 *              device to a network.
 *
 * @param       Status - Result of NLME_JoinRequest()

(4) ZDO_NetworkDiscoveryConfirmCB路由器/終端發現網絡請求的回調函數
 * @fn          ZDO_NetworkDiscoveryConfirmCB
 *
 * @brief       This function returns a choice of PAN to join.
 *
 * @param       ResultCount - Number of routers discovered
 * @param       NetworkList - Pointer to list of network descriptors


四種回調函數會分別觸發ZDAppTaskID相應事件:
ZDO_NetworkFormationConfirmCB(): osal_set_event( ZDAppTaskID, ZDO_NETWORK_START );
ZDO_StartRouterConfirmCB():osal_set_event( ZDAppTaskID, ZDO_ROUTER_START );
ZDO_JoinConfirmCB():ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_JOIN_IND, sizeof                                   (osal_event_hdr_t), (byte*)NULL );
ZDO_NetworkDiscoveryConfirmCB(): ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_DISC_CNF, sizeof                                 (ZDO_NetworkDiscoveryCfm_t), (byte *)&msg );

參照上面ZDO_StartDevice()函數,能夠看到相應功能的請求函數.回調函數具體調用流程參見種類型設備的啓動流程.

相關文章
相關標籤/搜索