zigbee协议栈使用的是zstack版本,该协议栈的整体功能有点类似于操作系统。下面以SimpleApp例程为例,对协议栈的组网流程进行描述。
协议栈是用C语言实现的,由于C语言的入口都是main函数,因此需要找到main函数,下图为协议栈各层列表(主要包括应用层、硬件层、MAC层、网络层、安全层、服务层等),TI公司的编程比较规范,文件的命名就意味着相关的功能。
图1 协议栈的整体架构
可以看到,ZMain文件下面有ZMain.c文件,而该文件就是整个协议栈的入口地址。打开ZMain.c文件,可以看到函数intmain( void );该函数就是整个协议栈最开始的入口。在main函数里面可以看到语句:
// Initialize the operating system
osal_init_system();
该语句的实际含义是初始化zigbee协议栈。
进入函数osal_init_system()的内部(具体方法:使鼠标停留在osal_init_system上,并且单击右键,在弹出的选项中选择“go todefinition of osal_init_system”),定位到下列语句:
// Initialize the system tasks.
osalInitTasks();
从这个函数的名字就可以知道它是用于初始化系统任务的。在zigbee协议栈中,一个非常重要而且贯穿协议栈生命周期的概念就是任务,也就是说协议栈的信息处理和数据传输等过程都是通过任务来实现的,即如果某个节点需要传输一个数据包,它会通过调用相关任务通知操作系统需要发送数据包。
既然任务是个非常重要的概念,那么就很有必要进入到osalInitTasks()函数内部,看看这个函数究竟是初始化那些任务!!
类似,点击右键进入osalInitTasks函数内部,下面是该函数的内容:
voidosalInitTasks( void )
{
uint8 taskID = 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 );
}
函数内部表明,函数执行了协议栈各层的初始化操作,包括mac层、网络层、硬件层等各层初始化。这里看到了此语句:ZDApp_Init(taskID++ );该语句的作用是初始化zigbee设备对象(ZDO),那zigbee设备对象是用来干什么的呢?为什么要对它进行初始化呢?
一句话,应用层可以通过ZigBee设备对象(ZDO)对网络层参数进行配置和访问。也就是说ZDO会对要组建的zigbee网络进行各种配置。
那ZDApp_Init()内部又是怎么实现的呢?同理进入到ZDApp_Init()内部,可以看到ZDApp_Init()就是对网络的各种初始化配置,定位到下列语句:
if ( devState != DEV_HOLD )//在本人的zstack上devState不是DEV_HOLD
{
ZDOInitDevice( 0 );
}
所以就执行了语句:ZDOInitDevice(0 );该函数是什么作用呢??它是负责启动网络。在函数ZDOInitDevice()内,定位到下列语句:
// Trigger the network start
ZDApp_NetworkInit( extendedDelay );
到这里就设置了定时触发启动网络了;
而ZDApp_NetworkInit()函数内部是怎么样出发网络启动的呢??
右键点击ZDApp_NetworkInit(),进入到ZDApp_NetworkInit()内部,它的函数体如下:
voidZDApp_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_NetworkInit()内部有个if-else选择分支,if分支是经过一段时间后,再添加网络初始化任务,而else分支则是直接执行网络初始化任务,