ZDO_STATE_CHANGE 只有当设备角色发生转变后才会触发,才能被告诉COOR你的网络中有一个设备变了角色。
zigbee网络启动流程 ---- 协调器
main()->osal_init_system()->osalInitTasks()->ZDApp_Init()
进入ZDApp_Init()函数:
void ZDApp_Init( uint8 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 )
{
ZDOInitDevice( 0 );
}
else
{
// Blink LED to indicate HOLD_START
HalLedBlink ( HAL_LED_4, 0, 50, 500 );
}
ZDApp_RegisterCBs();
}
协调器没有编译HOLD_AUTO_START,也没有手工设置SW_1,初始化devState = DEV_INIT(参见基本问题说明3).因此直接在ZDApp_Init()中进入ZDOInitDevice( 0 )开启设备.
uint8 ZDOInitDevice( uint16 startDelay )
{
uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
uint16 extendedDelay = 0;
if ( devState == DEV_HOLD )
{
// Initialize the RAM items table, in case an NV item has been updated.
zgInitItems( FALSE );
}
ZDConfig_InitDescriptors();
//devtag.071807.todo - fix this temporary solution
_NIB.CapabilityFlags = ZDO_Config_Node_Descriptor.CapabilityFlags;
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
ZDApp_LeaveCtrlStartup( &devState, &startDelay );
// Leave may make the hold state come back以上两个函数设置了对设备离开时的控制,如果有延时则延时,没有则把设备状态设为DEV_HOLD
if ( devState == DEV_HOLD )
{
// Set the NV startup option to force a "new" join.
zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE );
// Notify the applications
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
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 )
networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
else
{
// Determine if NV should be restored
networkStateNV = ZDApp_ReadNetworkRestoreState();
}
if ( networkStateNV == ZDO_INITDEV_RESTORED_NETWORK_STATE )
{
networkStateNV = ZDApp_RestoreNetworkState();
}
else
{
// Wipe out the network state in NV
NLME_InitNV();
NLME_SetDefaultNV();
// clear NWK key values
ZDSecMgrClearNVKeyValues();
}
#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 the security for type of device
ZDApp_SecInit( networkStateNV );
// Trigger the network start
ZDApp_NetworkInit( extendedDelay );
// set broadcast address mask to support broadcast filtering
NLME_SetBroadcastFilter( ZDO_Config_Node_Descriptor.CapabilityFlags );
return ( networkStateNV );
}
注:
(1)自启动模式下SampleApp的终端和路由器总体流程基本一致、
(2)以SampleApp为例,ZDO_StartDevice()函数的两个重要参数比较:
终端:
ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_DEVICE
devStartMode = MODE_JOIN
路由器:
ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_ROUTER
devStartMode = MODE_JOIN
协调器:
ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR
devStartMode = MODE_HARD
ZDO_STATE_CHANGE 只有当设备角色发生转变后才会触发,才能被告诉COOR你的网络中有一个设备变了角色。