带大家来一起快速的看懂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 );这个函数就需要程序员进行编写。所以这个函数也非常的重要。 这就是协议栈的大体运行过程,当然这些还很浅显,还没有讨论一些深层次的内容,并且有些地方写得不合适的地方,希望大家指正,这里我表示万分的感激。
|