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 = ;
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, , (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( ); //The second step, 接着转到ZDOInitDevice()函数,执行The third step;
}
else
{
// Blink LED to indicate HOLD_START
HalLedBlink ( HAL_LED_4, , , );
}
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.路由器或终端设备
)协调器
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()函数,找到相对应的网络改变事件。
} )路由器或终端设备
//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()函数的时候,要分两种情况,一种是终端设备,一种是路由器:
)终端设备:
void ZDApp_ProcessNetworkJoin( void ) //处理网络加入事件。
{
......
if ( nwkStatus == ZSuccess )
{
//设置 ZDO_STATE_CHANGE_EVT ,发送到ZDA层,执行 ZDApp_event_loop()函数。
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
}
......
} )路由器:
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( , , 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 = ;
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] = ; // 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 )
{
// Save the task ID
ZDAppTaskID = task_id; // 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. // Check for manual "Hold Auto Start"
ZDAppCheckForHoldKey();检测到有手工置位SW_1则会设置devState = DEV_HOLD,从而避开网络初始化 // 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层时,就执行该条件语句
/*如果devState=DEV_HOLD,则不会调用ZDOInitDevice()来初始化网络
即不组网也不入网.LED4闪烁等待应用程序来开启设备并初始化网络
*/
{
ZDOInitDevice( );
}
else
{
ZDOInitDevice( ZDO_INIT_HOLD_NWK_START );
// Blink LED to indicate HOLD_START
HalLedBlink ( HAL_LED_4, , , );
} // Initialize the ZDO callback function pointers zdoCBFunc[]
ZDApp_InitZdoCBFunc(); ZDApp_RegisterCBs();
} /* ZDApp_Init() */
//ZDApp.c
1 uint8 ZDOInitDevice( uint16 startDelay )
{
uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
uint16 extendedDelay = ; 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; #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 ); if( ZDO_INIT_HOLD_NWK_START != startDelay )
{
devState = DEV_INIT; // Remove the Hold state // Initialize leave control logic
ZDApp_LeaveCtrlInit(); // Check leave control reset settings
ZDApp_LeaveCtrlStartup( &devState, &startDelay ); // Leave may make the hold state come back
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).
} // Trigger the network start
ZDApp_NetworkInit( extendedDelay ); //网络初始化,跳到相应的函数里头
} // set broadcast address mask to support broadcast filtering
NLME_SetBroadcastFilter( ZDO_Config_Node_Descriptor.CapabilityFlags ); return ( networkStateNV );
}
void ZDApp_NetworkInit( uint16 delay )
{
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 );
}
}
UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events )
{
uint8 *msg_ptr; if ( events & SYS_EVENT_MSG )
{
while ( (msg_ptr = osal_msg_receive( ZDAppTaskID )) )
{
ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr ); // Release the memory
osal_msg_deallocate( msg_ptr );
} // Return unprocessed events
return (events ^ SYS_EVENT_MSG);
} if ( events & ZDO_NETWORK_INIT )//网络初始化事件处理
{
// Initialize apps and start the network
devState = DEV_INIT;
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT ); ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType, devStartMode,
DEFAULT_BEACON_ORDER, DEFAULT_SUPERFRAME_ORDER );
//设备逻辑类型,启动模式,信标时间,超帧长度,去启动设备
// Return unprocessed events
return (events ^ ZDO_NETWORK_INIT);
} if ( ZSTACK_ROUTER_BUILD )
{
if ( events & ZDO_NETWORK_START )
{
ZDApp_NetworkStartEvt(); // Return unprocessed events
return (events ^ ZDO_NETWORK_START);
} 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 ); // Return unprocessed events
return (events ^ ZDO_ROUTER_START);
}
} if ( events & ZDO_STATE_CHANGE_EVT )
{
ZDO_UpdateNwkStatus( devState ); // At start up, do one MTO route discovery if the device is a concentrator
if ( zgConcentratorEnable == TRUE )
{
// Start next event
osal_start_timerEx( NWK_TaskID, NWK_MTO_RTG_REQ_EVT, );
} // Return unprocessed events
return (events ^ ZDO_STATE_CHANGE_EVT);
} if ( events & ZDO_COMMAND_CNF )
{
// User defined logic // Return unprocessed events
return (events ^ ZDO_COMMAND_CNF);
} if ( events & ZDO_NWK_UPDATE_NV )
{
ZDApp_SaveNetworkStateEvt(); // Return unprocessed events
return (events ^ ZDO_NWK_UPDATE_NV);
} if ( events & ZDO_DEVICE_RESET )
{
#ifdef ZBA_FALLBACK_NWKKEY
if ( devState == DEV_END_DEVICE_UNAUTH )
{
ZDSecMgrFallbackNwkKey();
}
else
#endif
{
// Set the NV startup option to force a "new" join.
zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE ); // The device has been in the UNAUTH state, so reset
// Note: there will be no return from this call
SystemResetSoft();
}
} if ( ZG_SECURE_ENABLED )
{
return ( ZDApp_ProcessSecEvent( task_id, events ) );
}
else
{
// Discard or make more handlers
return ;
}
}
//ZDObject.c
1 void ZDO_StartDevice( byte logicalType, devStartModes_t startMode, byte beaconOrder, byte superframeOrder )
{
ZStatus_t ret;
#if defined ( ZIGBEE_FREQ_AGILITY )
static uint8 discRetries = ;
#endif
#if defined ( ZIGBEE_COMMISSIONING )
static uint8 scanCnt = ;
#endif ret = ZUnsupportedMode; if ( ZG_BUILD_COORDINATOR_TYPE && logicalType == NODETYPE_COORDINATOR )//当设备作为协调器时,执行这个条件语句。
{
if ( startMode == MODE_HARD )
{
devState = DEV_COORD_STARTING;
ret = NLME_NetworkFormationRequest( zgConfigPANID, zgApsUseExtendedPANID, zgDefaultChannelList,
zgDefaultStartingScanDuration, beaconOrder,
superframeOrder, false );
//向网络层发送网络形成请求。当网络层执行 NLME_NetworkFormationRequest()建立网络后,将给予 ZDO层反馈信息。
// 接着去执行ZDApp层的 ZDO_NetworkFormationConfirmCB()函数
}
else if ( startMode == MODE_RESUME )
{
// Just start the coordinator
devState = DEV_COORD_STARTING;
ret = NLME_StartRouterRequest( beaconOrder, beaconOrder, false );
}
else
{
#if defined( LCD_SUPPORTED )
HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
#endif
}
} 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()函数
#if defined( MANAGED_SCAN )
ZDOManagedScan_Next();
ret = NLME_NetworkDiscoveryRequest( managedScanChannelMask, BEACON_ORDER_15_MSEC );
#else
ret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList, zgDefaultStartingScanDuration );
#if defined ( ZIGBEE_FREQ_AGILITY )
if ( !( ZDO_Config_Node_Descriptor.CapabilityFlags & CAPINFO_RCVR_ON_IDLE ) &&
( ret == ZSuccess ) && ( ++discRetries == ) )
{
// For devices with RxOnWhenIdle equals to FALSE, any network channel
// change will not be recieved. On these devices or routers that have
// lost the network, an active scan shall be conducted on the Default
// Channel list using the extended PANID to find the network. If the
// extended PANID isn't found using the Default Channel list, an scan
// should be completed using all channels.
zgDefaultChannelList = MAX_CHANNELS_24GHZ;
}
#endif // ZIGBEE_FREQ_AGILITY
#if defined ( ZIGBEE_COMMISSIONING )
if (startMode == MODE_REJOIN && scanCnt++ >= )
{
// When ApsUseExtendedPanID is commissioned to a non zero value via
// application specific means, the device shall conduct an active scan
// on the Default Channel list and join the PAN with the same
// ExtendedPanID. If the PAN is not found, an scan should be completed
// on all channels.
// When devices rejoin the network and the PAN is not found from
zgDefaultChannelList = MAX_CHANNELS_24GHZ;
}
#endif // ZIGBEE_COMMISSIONING
#endif
}
else if ( startMode == MODE_RESUME )
{
if ( logicalType == NODETYPE_ROUTER )
{
ZMacScanCnf_t scanCnf;
devState = DEV_NWK_ORPHAN; /* if router and nvram is available, fake successful orphan scan */
scanCnf.hdr.Status = ZSUCCESS;
scanCnf.ScanType = ZMAC_ORPHAN_SCAN;
scanCnf.UnscannedChannels = ;
scanCnf.ResultListSize = ;
nwk_ScanJoiningOrphan(&scanCnf); ret = ZSuccess;
}
else
{
devState = DEV_NWK_ORPHAN;
ret = NLME_OrphanJoinRequest( zgDefaultChannelList,
zgDefaultStartingScanDuration );
}
}
else
{
#if defined( LCD_SUPPORTED )
HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
#endif
}
} if ( ret != ZSuccess )
{
osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT, NWK_RETRY_DELAY );
}
}
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】协调器网络的建立
Ztack学习笔记(4)-系统网络分析的更多相关文章
- Ztack学习笔记(2)-系统初始化分析
main函数先执行初始化工作,包括硬件.网络层.任务等的初始化. 一 系统初始化 系统初始化函数主要完成内存分配.消息队列头.定时器.电源管理.任务系统及内存栈等的初始化,具体如下代码所示: //os ...
- Symfony2 学习笔记之系统路由
mfony2 学习笔记之系统路由 漂亮的URL绝对是一个严肃的web应用程序必须做到的,这种方式使index.php?article_id=57这类的丑陋URL被隐藏,由更受欢迎的像 /read/ ...
- Linux学习笔记-Linux系统简介
Linux学习笔记-Linux系统简介 UNIX与Linux发展史 UNIX是父亲,Linux是儿子. UNIX发行版本 操作系统 公司 硬件平台 AIX IBM PowerPC HP-UX HP P ...
- Ztack学习笔记(1)-初识Ztack
一.Zigbee协议 Zigbee是IEEE 802.15.4协议的代名词,是一种短距离.低功耗的无线通信技术.这一名称来源于蜜蜂的八字舞,因为蜜蜂(bee)是靠飞翔和“嗡嗡”(zig)地抖动翅膀的“ ...
- 【小梅哥SOPC学习笔记】系统时钟的使用
给NIOS II CPU添加一颗澎湃的心——系统时钟的使用 本实验介绍如何在Qsys中添加一个定时器作为NIOS II的心跳定时器,并在NIOS II中软件编程使用该定时器. 将上一个实验watchd ...
- 深度学习笔记------windows系统下进行Linux-Ubuntu14.04双系统安装笔记(二)
在上一篇文章中介绍了新手如何安装Ubuntu14.04的双系统,本文会说明Ubuntu系统下搜狗输入法的安装,并就我遇见的一些bug给出最简单的解决办法. 第一部分.搜狗输入法的安装 本身搜狗输入法的 ...
- 《深入理解Android:Telephon原理剖析与最佳实践》学习笔记(系统框架)
Android智能手机的系统结构: 智能手机的硬件基本结构大多采用双处理器架构:主处理器和从处理器,主处理器主要运行开放式操作系统以及操作系统之上的应用,负责整个系统的控制,称之为AP,从处理 ...
- STM32学习笔记:系统时钟和SysTick定时器
原文:http://blog.sina.com.cn/s/blog_49cb42490100s60d.html 1. STM32的时钟系统 在STM32中,一共有5个时钟源,分别是HSI.HS ...
- ASP.NET MVC4学习笔记路由系统实现
一.路由实现 路由系统实际是一个实现了ASP.NET IHttpModule接口的模块,通过注册HttpApplication的PostResolveRequestCache 事件对Url路由处理.总 ...
随机推荐
- 慕课网-安卓工程师初养成-2-11 Java常量
来源:http://www.imooc.com/code/1256 所谓常量,我们可以理解为是一种特殊的变量,它的值被设定后,在程序运行过程中不允许改变. 语法:final 常量名 = 值; 程序中使 ...
- 【考试】简单的sql语句
)显示正好为5个字符的员工的姓名 HR@ORA11GR2>select last_name,first_name from employees ; )显示不带有"R"的员工的 ...
- x86_64 Ubuntu 14.04 LST安装gcc4.1.2 转载
由于编译源码软件需要用到gcc4.1.2版本,但是本机已经安装有gcc4.8.4,下载gcc4.1.2源码编译总会出现运行找不到库文件错误,或者i386和x86_64不兼容问题,在http://ask ...
- python中operator.itemgetter
直接上例子: rs= [... {... "datetime": "Mon, 31 Aug 2015 23:00:00 GMT",... ...
- NOI2002 银河英雄传说
P1196 银河英雄传说 367通过 1.1K提交 题目提供者该用户不存在 标签并查集NOI系列2001(或之前) 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 莱因哈特什么鬼? 私人代码 ...
- TCP/IP详解学习笔记(15)-- TCP的流量控制和拥塞控制
TCP的流量控制 1.概述 所谓的流量控制就是让发送方的发送速率不要太快,让接收方来得及接受.利用滑动窗口机制可以很方便的在TCP连接上实现对发送方的流量控制.TCP的窗口单位是字节,不是报 ...
- CLRS:master theory in complexity of algorithm
T(n)=aT(n/b)+f(n); where we can interpret n/b to mean either floor(b/n) or ceil(b/n), Then T (n) has ...
- javacript 优化2
上面一篇文章大致介绍了一些javascript当中使用的一些小技巧,当下这篇文章继续介绍一下内存管理.松散耦合.性能方面的一些小知识.为避免错误应该注意的点 内存管理 1.循环引用 如果循环引用中包含 ...
- Acronis 备份使用
1:至Acronis 中国官网,可了解到:Acronis True Image 是PC产品,Acronis Backup是企业产品 2:Acronis Backup 11.5.0.39029 :htt ...
- maven项目使用mybatis-generator自动生成代码
1.添加mybatis-generator插件,打开pom.xml文件 在project节点下添加: <build> <plugins> <!-- MyBatis代码生成 ...