带大家来一起快速的看懂ZigBee的协议栈的运行流程。
1.读任何程序都需要从main函数入手,那我们先来看Zmain.c中的main函数。
问题:在main中我们会看到很多的函数,我们究竟要看哪个函数呢?
回答:这么多的函数中其实我们只需要关注osal_init_system()和osal_start_system()两个函数就可以了。我们在编程的时候其实也只会关系到这两个函数。
2.我们跟踪(把光标放在这个函数上点右键,再点击go to define)osal_init_system()这个函数,发现它在OSAL.c文件中。
问题:在这个函数中有遇到了很多函数,那我们又要关注那些函数呢?
回答:这个函数中我们只需要关注osalInitTasks()函数就可以了,这其实就是把每个事件作为每个任务。
3.我们跟踪osalInitTasks()这个函数,发现在OSAL_SampleApp.c中。其他的函数先不管。
在这个函数我们可以看到我们的任务编号是从0开始的,然后每添加一个任务任务编号(taskID++)就加一,并且为任务分配内存。如下:
uint8 taskID = 0;
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
在这个函数中需要我们特别关注的是SampleApp_Init(taskID)这个函数,因为我们在编程的时候这个函数是需要我们程序员去编写的,这个事协议栈提供的编程接口。
4.同样我们跟踪这个函数SampleApp_Init(taskID),发现它在SampleApp.c中(这个函数很重要)。在这个函数中我们看到需要我们去配置一些信息,如串口波特率、流控等等。
uartConfig.callBackFunc = Serial_CallBack;
这需要我们来定义串口回调函数来无线发送数据。
5.现在系统的初始化已经做好了,遇到SampleApp_Init()函数的return后一步一步的返回。
6.返回到main函数后,我们再来看osal_start_system()函数,注意这个函数一但进去之后,此函数就不会再返回。我们跟踪这个函数,发现它在OSAL.c中。
do {
if (tasksEvents[idx]) // Task is highest priority that is ready.
{
break;
}
} while (++idx < tasksCnt);
注意这段逻辑,这是把任务中优先级高的选出来。
events = tasksEvents[idx];//把优先级高的选出来赋值给事件来处理。
这里我们需要来看一个数组:
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK )
MT_ProcessEvent,
#endif
APS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_ProcessEvent,
#endif
ZDApp_event_loop,
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_event_loop,
#endif
SampleApp_ProcessEvent
};
我们知道这些都是事件处理函数。问题又来了,这么多我们应该看和用哪一个呢?
协议栈给用户提供的函数编程接口是SampleApp_ProcessEvent这个函数。
然而怎么调用到这个函数呢?看下面的代码。
events = (tasksArr[idx])( idx, events );//这是是一个函数指针的应用。自己补C语言,这里不赘述。
7.既然是这样我们就要跟踪SampleApp_ProcessEvent()这个函数,发现它在SampleApp.c中。
case AF_INCOMING_MSG_CMD:
SampleApp_MessageMSGCB( MSGpkt );
break;
这是我们需要关注的case,这个就是接受到数据的时候读出无线发过来的数据。SampleApp_MessageMSGCB( MSGpkt );这个函数就需要程序员进行编写。所以这个函数也非常的重要。
这就是协议栈的大体运行过程,当然这些还很浅显,还没有讨论一些深层次的内容,并且有些地方写得不合适的地方,希望大家指正,这里我表示万分的感激。