也许现在你看不明白他写了什么,放心总有一天你看得明白的,可是有个疑问会不会冒出来了呢?那我自己的代码写在哪啊!,难道我还得改这个大循环不成?!别急,现在我们来说说这协议栈是怎么工作的。 首先,我们要来说的就是zstack的操作系统---OSAL,我们的协议栈其实是运行在TI的OSAL操作系统之上的,我们的程序(在程序中叫做task)和协议栈的各层都是作为osal的一个个任务在运行,由osal来调度的。我们刚才看到的是如何去启动了osal系统而已,既然我们的程序和协议栈都是osal的一个任务,那么我们如何把自己的任务注册进来呢?这是接下来我们要说的问题,至于osal的基本机制,我们以后再说,现在要做的是先让大家能够下载些程序下去玩玩,满足一下虚荣之心先。 3.建立自己的任务 还是按照例子来说比较好说,那么我们挑选的例子就是TI的一个基本的例子,实现了一些最基本的入网和收发数据亮灯程序。我挑选了ZStack-CC2530-2.5.1a\Projects\zstack\Samples\GenericApp这个工程来说明如何建立自己的任务,打开ZStack-CC2530-2.5.1a\Projects\zstack\Samples\GenericApp\CC2530DB里面的IAR工程,我们可以看到这样子的架构 当然你重头到尾建立这样子一个工程是挺费劲的,TI已经提供好了,那就用TI的例子修改就行了,没必要重头到尾建立一次,我建过,还是要看着TI的配置来做,很麻烦,很多配置东西你要清楚才能配置好。我们要建立自己任务,那么这些东西都在App这个Group里面,看看里面有啥东西 可以看出只有三个文件,这三个文件却大有头,这样子的架构几乎成了TI的zstack的程序架构,几乎所有的都是这样子写的,GenericApp.h放的是一些用户的宏定义,GenericApp.c实现我们自己的任务代码,OSAL_GenericApp.c主要是实现osal协议的协议初始化接口的编写,我们的任务添加,就靠这三个文件了!好,我们先不看我们的任务代码是怎么实现的,我们先看OSAL_GenericApp.c是怎么添加我们的任务的和初始化osal的任务的,内容不多,就全放上来吧 [cpp] view plain copy
- #include "ZComDef.h"
- #include "hal_drivers.h"
- #include "OSAL.h"
- #include "OSAL_Tasks.h"
-
- #if defined ( MT_TASK )
- #include "MT.h"
- #include "MT_TASK.h"
- #endif
-
- #include "nwk.h"
- #include "APS.h"
- #include "ZDApp.h"
- #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
- #include "ZDNwkMgr.h"
- #endif
- #if defined ( ZIGBEE_FRAGMENTATION )
- #include "aps_frag.h"
- #endif
-
- #include "GenericApp.h"
-
- /*********************************************************************
- * GLOBAL VARIABLES
- */
-
- // The order in this table must be identical to the task initialization calls below in osalInitTask.
- 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
- GenericApp_ProcessEvent
- };
-
- const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
- uint16 *tasksEvents;
-
- /*********************************************************************
- * FUNCTIONS
- *********************************************************************/
-
- /*********************************************************************
- * @fn osalInitTasks
- *
- * @brief This function invokes the initialization function for each task.
- *
- * @param void
- *
- * @return none
- */
- void osalInitTasks( 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++ );
- #if defined( MT_TASK )
- MT_TaskInit( taskID++ );
- #endif
- APS_Init( taskID++ );
- #if defined ( ZIGBEE_FRAGMENTATION )
- APSF_Init( taskID++ );
- #endif
- ZDApp_Init( taskID++ );
- #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
- ZDNwkMgr_Init( taskID++ );
- #endif
- GenericApp_Init( taskID );
- }
其实里面就两样东西是重要的,一个是tasksArr这个数组,一个是osalInitTasks这个函数
tasksArr其实就是osal的一个任务列表,里面包含了osal系统中所有的任务,里面有我们任务处理事件的循环,当有消息是给我们的任务的时候osal就会调用我们的任务处理循环GenericApp_ProcessEvent,当然啦,osal没有win系统那么牛叉,更没有Linux系统那么让人感到可爱,他是一个让人感到不恶心,可是不讨人喜欢的小小的实时操作系统。osalInitTasks这个其实就是任务初始化函数,在上面的osal_start_system之前会被调用,而且这个函数会调用很多任务的初始化函数,同样包括我们自己的任务的初始化函数GenericApp_Init,至于GenericApp_ProcessEvent和GenericApp_Init等下再说,我们先来看看到底是啥时候调用了osalInitTasks,以及tasksArr是如何被osal使用的。 我们回到main函数中,可以看到这样子的一个函数被调用了osal_init_system,我们再看看看osal_init_system做了什么 [cpp] view plain copy
- uint8 osal_init_system( void )
- {
- // Initialize the Memory Allocation System
- osal_mem_init();
-
- // Initialize the message queue
- osal_qHead = NULL;
-
- // Initialize the timers
- osalTimerInit();
-
- // Initialize the Power Management System
- osal_pwrmgr_init();
-
- // Initialize the system tasks.
- osalInitTasks();
-
- // Setup efficient search for the first free block of heap.
- osal_mem_kick();
-
- return ( SUCCESS );
- }
很明显,在这里他不但初始化了osal的内存管理,电源管理,并且调用了我们的osalInitTasks函数来初始化osal的所有task,所以在系统进入大循环之前,这些任务是被初始化了的,而osal是如何知道我们的这些任务的呢,就是通过tasksArr这个数组。我们来看看osal_run_system可以看到这样子一段events = (tasksArr[idx])( idx, events );由此可以看出,我们的任务是这样子被添加进来的,并且任务初始化的时候每个task都带了一个taskID,osal就是根据这个taskID来区分每个task,event是哪个task发起的,应该发给哪个task。
|