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()函數,能夠看到相應功能的請求函數.回調函數具體調用流程參見種類型設備的啓動流程.