Zigbee终端入网
参考https://www.cnblogs.com/cherishui/p/3689376.html
ZDO层的API为应用程序的终端提供了管理zigbee协调器,路由器或终端设备的接口,包括创建,查找和加入一个zigbee网络,绑定应用程序终端以及安全管理。
从主函数中到下边的网络函数
ZDApp_Init( taskID++ ); //ZDApp_Init(4) ,用户需考虑
就是这个任务函数管理设备的网络的创建,查找,加入以及绑定应用程序终端以及安全管理
(void)NLME_GetExtAddr(); // Load the saveExtAddr pointer.返回设备IEEE 64位地址的指针
ZDAppCheckForHoldKey检查自动启动保持位,如果在上电启动的时候,检测到手工按下SW_BYPASS_START键,板子上的灯会持续闪烁,设备状态设置为DEV_HOLD,不进行网络初始化。TI自带的其他例子里面,定义了HOLD_AUTO_START这个宏,如果定义了这个宏,设备启动后不会自动组网。设备状态为DEV_HOLD,否则,设备状态为DEV_INIT。不管以什么方式启动,
ZDO_Init:初始化ZDO条目,并设置设备的启动方式(ZDODeviceSetup),是协调器,终端还是路由器?
进入函数中只能看到 NLME_CoordinatorInit(); NLME_DeviceJoiningInit(); 被封装的两个函数一个是路由器一个是协调器 而两个预定义的宏可以看下
#define ZG_BUILD_JOINING_TYPE (ZSTACK_DEVICE_BUILD & (DEVICE_BUILD_ROUTER | DEVICE_BUILD_ENDDEVICE))
#define ZG_BUILD_RTR_TYPE (ZSTACK_DEVICE_BUILD & (DEVICE_BUILD_COORDINATOR | DEVICE_BUILD_ROUTER))
afRegister( (endPointDesc_t *)&ZDApp_epDesc );
注册ZDO设备对象到AF层
#if defined( ZDO_USERDESC_RESPONSE )
ZDApp_InitUserDesc();
#endif // ZDO_USERDESC_RESPONSE
如果设备状态为DEV_HOLDd的话,则不会自动启动网络,否则的话,会自动启动网络,如果是协调器则建立网络,如果是路由器或是终端则加入网络
if ( devState != DEV_HOLD )
{
ZDOInitDevice( 0 );
}
else
{
ZDOInitDevice( ZDO_INIT_HOLD_NWK_START );
// Blink LED to indicate HOLD_START
HalLedBlink ( HAL_LED_4, 0, 50, 500 );
}
初始化ZDO系统回调函数
ZDApp_InitZdoCBFunc();
ZDApp_RegisterCBs();
注册ADApp层的回调函数。
在ZDOInitDevice中,可以通过按键来跳过一些初始化设置,例如网络层的NV存储和网络层的初始化。确定好设备状态和初始化参数后,调用最关键的函数ZDApp_NetworkInit( extendedDelay ),顾名思义,该函数执行ZigBee网络的初始化操作。在这个函数里面
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 );
}
}
给ZDApp任务发起一个ZDO_NETWORK_INIT的消息,让其进入消息处理机制
前边我们知道ZDAppTaskID就是ZDApp_Init( taskID++ );这个传递过来的参数
而这个参数会被ZDApp_event_Loop函数接收,
ZDApp_event_Loop函数中有下边一段代码
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);
}
响应ZDO_NETWORK_INIT事件,再发起一个ZDO_STATE_CHANGE_EVT,然后执行ZDO_StartDevice来启动整个ZigBee设备网络层的实际初始化。
void ZDO_StartDevice( byte logicalType, devStartModes_t startMode, byte beaconOrder, byte superframeOrder )
{
ZStatus_t ret;
#if defined ( ZIGBEE_FREQ_AGILITY )
static uint8 discRetries = 0;//开始网络搭建,网络ID和扫描通道列表由f8wconfig.cfg中的配置决定,此处形成了非信标网络,beaconorder和superframeorder传入参数都为15
#endif
#if defined ( ZIGBEE_COMMISSIONING )
static uint8 scanCnt = 0;//如果设备是协调器,则向网络层发送NLME_NetworkFormationRequest请求原语来形成网络
#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 );
}
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
}
}
如果设备为路由器或者终端的话,则会发起NLME_NetworkDiscoveryRequest 请求原语来发起网络发现。如果设备的状态为MODE_RESUME,则会启动孤儿扫描流程。
NLME_NetworkFormationRequest请求原语的响应函数,在源码里面没有找到,估计是在库中封装响应了,不过,找到了ZDO_NetworkFormationConfirmCB这个函数,从名字上来猜想,应该是收到响应信息后调用的回调函数。还有一个表示网络状态的函数nwk_Status,也是被调用执行的。
从Z-Stack API文档中可以知道,NLME_NetworkFormationRequest函数返回的结果将传递给ZDO_NetworkFormationConfirmCB,网络建立成功后,会给ZDAppTask发送一个ZDO_NETWORK_START的消息,
(自我总结,如需更改请留言)