ZigBee协议栈初始化网络启动流程.docx
《ZigBee协议栈初始化网络启动流程.docx》由会员分享,可在线阅读,更多相关《ZigBee协议栈初始化网络启动流程.docx(19页珍藏版)》请在冰豆网上搜索。
ZigBee协议栈初始化网络启动流程
ZigBee协议栈初始化网络启动流程
ZigBee的基本流程:
由协调器的组网(创建PANID),终端设备和路由设备发现网络以及加入网络。
基本流程:
main()->osal_init_system()->osalInitTasks()->ZDApp_Init(),进协议栈初始化函数ZDApp_Init()。
1.1进入程序入口main()。
ZMain.c中
C++Code
intmain(void)
{
//Turnoffinterrupts
osal_int_disable(INTS_ALL);
//InitializationforboardrelatedstuffsuchasLEDs
HAL_BOARD_INIT();
//Makesuresupplyvoltageishighenoughtorun
zmain_vdd_check();
//InitializeboardI/O
InitBoard(OB_COLD);
//InitialzeHALdrivers
HalDriverInit();
//InitializeNVSystem
osal_nv_init(NULL);
//InitializetheMAC
ZMacInit();
//Determinetheextendedaddress
zmain_ext_addr();
//InitializebasicNVitems
zgInit();
#ifndefNONWK
//SincetheAFisn'tatask,callit'sinitializationroutine
afInit();
#endif
//Initializetheoperatingsystem
osal_init_system();
//Allowinterrupts
osal_int_enable(INTS_ALL);
//Finalboardinitialization
InitBoard(OB_READY);
//Displayinformationaboutthisdevice
zmain_dev_info();
/*DisplaythedeviceinfoontheLCD*/
#ifdefLCD_SUPPORTED
zmain_lcd_init();
#endif
#ifdefWDT_IN_PM1
/*IfWDTisused,thisisagoodplacetoenableit.*/
WatchDogEnable(WDTIMX);
#endif
osal_start_system();//NoReturnfromhere
return0;//Shouldn'tgethere.
}//main()
1.2给任务添加ID
sapi.c中
C++Code
voidosalInitTasks(void)//为各自进程添加ID用于任务的查找
{
uint8taskID=0;
tasksEvents=(uint16*)osal_mem_alloc(sizeof(uint16)*tasksCnt);
osal_memset(tasksEvents,0,(sizeof(uint16)*tasksCnt));
macTaskInit(taskID++);
nwk_init(taskID++);
Hal_Init(taskID++);//硬件抽象层初始化
#ifdefined(MT_TASK)
MT_TaskInit(taskID++);
#endif
APS_Init(taskID++);
ZDApp_Init(taskID++);//判断如果协调器节点建立网络、如果终端节点加入网络
SAPI_Init(taskID);
}
1.3初始化ZigBee协议栈网络
ZDApp.c
C++Code
voidZDApp_Init(uint8task_id)
{
//SavethetaskID
ZDAppTaskID=task_id;
//InitializetheZDOglobaldeviceshortaddressstorage
ZDAppNwkAddr.addrMode=Addr16Bit;
ZDAppNwkAddr.addr.shortAddr=INVALID_NODE_ADDR;
(void)NLME_GetExtAddr();//LoadthesaveExtAddrpointer.
//Checkformanual"HoldAutoStart"
//检测到有手工设置HAL_KEY_SW_1则会设置devState=DEV_HOLD,从而避开网络初始化
ZDAppCheckForHoldKey();
//InitializeZDOitemsandsetupthedevice-typeofdevicetocreate.
ZDO_Init();//通过判断预编译来开启一些函数功能
//RegistertheendpointdescriptionwiththeAF
//Thistaskdoesn'thaveaSimpledescription,butwestillneed
//toregistertheendpoint.
afRegister((endPointDesc_t*)&ZDApp_epDesc);
#ifdefined(ZDO_USERDESC_RESPONSE)
ZDApp_InitUserDesc();
#endif//ZDO_USERDESC_RESPONSE
//Startthedevice?
if(devState!
=DEV_HOLD)
{
ZDOInitDevice(0);
}
else
{
//BlinkLEDtoindicateHOLD_START
HalLedBlink(HAL_LED_4,0,50,500);
}
ZDApp_RegisterCBs();
}/*ZDApp_Init()*/
如果设置devState为DEV_HOLD,则不会执行ZDOInitDevice;反之,系统会调用此函数是设备组网或者入网。
看下这个函数完成的功能是什么样子的。
ZDOInitDevice是设备在网络中启动。
它会读取NV中的ZCD_NV_STARTUP_OPTION选项决定是否恢复网络状态。
如果应用层强制进行新的join操作,它应该在调用这个函数之前设置ZCD_NV_STARTUP_OPTION中的ZCD_STARTOPT_DEFAULT_NETWORK_STATE位。
可以调用zgWrieStartupOptions()函数完成这些设置。
1.4初始化设备(启动网络和设置网络类型)
ZDApp.c
C++Code
uint8ZDOInitDevice(uint16startDelay)
{
uint8networkStateNV=ZDO_INITDEV_NEW_NETWORK_STATE;
uint16extendedDelay=0;
if(devState==DEV_HOLD)
{
//InitializetheRAMitemstable,incaseanNVitemhasbeenupdated.
zgInitItems(FALSE);
}
ZDConfig_InitDescriptors();
//devtag.071807.todo-fixthistemporarysolution
_NIB.CapabilityInfo=ZDO_Config_Node_Descriptor.CapabilityFlags;
devState=DEV_INIT;//RemovetheHoldstate
//函数读取NV项目ZCD_NV_LEAVE_CTRL的值,ZDApp_LeaveCtrl指向这个值
//Initializeleavecontrollogic
ZDApp_LeaveCtrlInit();
//Checkleavecontrolresetsettings//设备的断开会造成DEV_HOLD状态
ZDApp_LeaveCtrlStartup(&devState,&startDelay);
//Leavemaymaketheholdstatecomeback
if(devState==DEV_HOLD)
{
//设置启动选项
//SettheNVstartupoptiontoforcea"new"join.
zgWriteStartupOptions(ZG_STARTUP_SET,ZCD_STARTOPT_DEFAULT_NETWORK_STATE);
//通知应用层触发事件
//Notifytheapplications
osal_set_event(ZDAppTaskID,ZDO_STATE_CHANGE_EVT);
return(ZDO_INITDEV_LEAVE_NOT_STARTED);//Don'tjoin-(onetime).
}
#ifdefined(NV_RESTORE)
//GetKeypaddirectlytoseeifaresetnvisneeded.
//HolddowntheSW_BYPASS_NVkey(definedinOnBoard.h)
//whilebootingtoskippastNVRestore.
if(HalKeyRead()==SW_BYPASS_NV)
networkStateNV=ZDO_INITDEV_NEW_NETWORK_STATE;
else
{
//通过读取ZCD_NV_STARTUP_OPTION选项决定是否进行网络恢复
//DetermineifNVshouldberestored
networkStateNV=ZDApp_ReadNetworkRestoreState();
}
if(networkStateNV==ZDO_INITDEV_RESTORED_NETWORK_STATE)
{
networkStateNV=ZDApp_RestoreNetworkState();
}
else
{
//WipeoutthenetworkstateinNV
NLME_InitNV();
NLME_SetDefaultNV();
}
#endif
if(networkStateNV==ZDO_INITDEV_NEW_NETWORK_STATE)//如果是要启动新的网络
{
ZDAppDetermineDeviceType();//根据选项设置设备的网络类型,默认路由类型
//Onlydelayifjoiningnetwork-notrestoringnetworkstate
extendedDelay=(uint16)((NWK_START_DELAY+startDelay)
+(osal_rand()&EXTENDED_JOINING_RANDOM_MASK));
}
//Initializethesecurityfortypeofdevice
ZDApp_SecInit(networkStateNV);
//触发启动网络
//Triggerthenetworkstart
ZDApp_NetworkInit(extendedDelay);
//setbroadcastaddressmasktosupportbroadcastfiltering用于处理合法的广播地址
NLME_SetBroadcastFilter(ZDO_Config_Node_Descriptor.CapabilityFlags);
return(networkStateNV);
}
这个函数注意功能:
初始化设备配置,ZDAppDetermineDeviceType()设置网络类型(协调、路由、终端),ZDApp_NetworkInit(extendedDelay)初始化网络并开启或加入网络。
1.5定时开启网络
ZDApp.c
进入ZDApp_NetworkInit()函数,等待一段时间在执行ZDO_NETWORK_INIT,跳入事件处理ZDApp层ZDAPP_EVENT_LOOP()函数开启网络。
C++Code
voidZDApp_NetworkInit(uint16delay)
{
if(delay)
{
//Waitawhilebeforestartingthedevice
osal_start_timerEx(ZDAppTaskID,ZDO_NETWORK_INIT,delay);
//发送ZDO_NETWORK_INIT(网络初始化)消息到ZDApp层,转到ZDApp层,ZDApp_event_loop()函数。
}
else
{
osal_set_event(ZDAppTaskID,ZDO_NETWORK_INIT);
}
}
1.6启动设备
ZDApp.c
ZDApp_event_loop()函数是回调函数,循环处理主事件。
设备逻辑类型,启动模式,信标时间,超帧长度
C++Code
UINT16ZDApp_event_loop(uint8task_id,UINT16events)
{
uint8*msg_ptr;
if(events&SYS_EVENT_MSG)
{
while((msg_ptr=osal_msg_receive(ZDAppTaskID)))
{
ZDApp_ProcessOSALMsg((osal_event_hdr_t*)msg_ptr);
//Releasethememory
osal_msg_deallocate(msg_ptr);
}
//Returnunprocessedevents
return(events^SYS_EVENT_MSG);
}
if(events&ZDO_NETWORK_INIT)
{
//Initializeappsandstartthenetwork
devState=DEV_INIT;
//设备逻辑类型,启动模式,信标时间,超帧长度,接着转到去启动设备,转到ZDO_StartDevice()
ZDO_StartDevice((uint8)ZDO_Config_Node_Descriptor.LogicalType,devStartMode,
DEFAULT_BEACON_ORDER,DEFAULT_SUPERFRAME_ORDER);