Z-Stack 软件架构分析
Posted iczelion
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Z-Stack 软件架构分析相关的知识,希望对你有一定的参考价值。
1 Osal_start_system(); // No Return from here
1 void osal_start_system( void ) 2 { 3 #if !defined ( ZBIT ) 4 for(;;) // Forever Loop 5 6 #endif 7 { 8 uint8 idx = 0; 9 10 Hal_ProcessPoll(); // This replaces MT_SerialPoll() and osal_check_timer(). 11 12 13 do { 14 if (tasksEvents[idx]) // 最高优先级任务被找到 15 16 { 17 break; 18 } 19 } while (++idx < tasksCnt); //其中tasksCnt为tasksArr数组中元素的个数 20 21 //得到了待处理的具有最高优先级的任务的索引号 idx 22 23 if (idx < tasksCnt) 24 { 25 uint16 events; 26 halIntState_t intState; 27 // 进入/退出临界区,来提取出需要处理的任务中的事件,其实这和μC/OS-II操作系统中进入临界区很相似,μC/OS-II中使用OS_ENTER_CRITICAL();OS_EXIT_CRITICAL(); 28 29 HAL_ENTER_CRITICAL_SECTION(intState); 30 events = tasksEvents[idx]; 31 tasksEvents[idx] = 0; // Clear the Events for this task. 32 33 HAL_EXIT_CRITICAL_SECTION(intState);//通过指针调用来执行对应的任务处理函数 34 35 36 events = (tasksArr[idx])( idx, events ); 37 //进入/退出临界区,保存尚未处理的事件 38 39 HAL_ENTER_CRITICAL_SECTION(intState); 40 tasksEvents[idx] |= events; // Add back unprocessed events to the current task. 41 42 HAL_EXIT_CRITICAL_SECTION(intState); 43 } //本次事件处理结束, 44 45 #if defined( POWER_SAVING ) 46 else // 所有的任务事件都被查询结束后,没有任何事件被激活 47 48 { 49 osal_pwrmgr_powerconserve(); // 系统进入休眠状态。 50 51 } 52 #endif 53 } 54 }
操作系统专门分配了存放所有任务事件的tasksEvents[]数组,每一个单元对应存放着每一个任务的所有事件,在这个函数中首先通过一个do—while循环来遍历tasksEvents[],找到一个具有待处理事件的优先级最高的任务,序号低的任务优先级高,然后跳出循环,此时,就得到了最高优先级任务的序号idx,然后通过events=tasksEvents[idx]语句,将这个当前具有最高优先级的任务的事件取出,接着就调用(tasksArr[idx])(inx,events)函数来执行具体的处理函数了,taskArr[]是一个函数指针数组,根据不同的idx就可以执行不同的函数。
TI给出了几个例子来演示Z-Stack协议栈,其实这些例子中的大部分代码是相同的,只有用户的应用层,添加了不同的任务及事件处理函数。这里以GeneralApp这个例子来说明。
首先,明确系统中要执行的几个任务。在GeneralApp这个例子中,几个任务函数组成了上述的tasksArr函数指针数组,在Osal_GeneralApp.c中定义,osal_start_system()函数通过函数指针(tasksArr[idx])(inx,events)调用。
tasksArr数组如下:
1 const pTaskEventHandlerFn tasksArr[] = { 2 macEventLoop, //MAC层任务处理函数 3 4 nwk_event_loop, //网络层任务处理函数 5 6 Hal_ProcessEvent, //硬件抽象层任务处理函数 7 8 #if defined( MT_TASK ) 9 10 MT_ProcessEvent, //调试任务处理函数 可选 11 12 #endif 13 14 APS_event_loop, //应用层任务处理函数,用户不用修改 15 16 ZDApp_event_loop, //设备应用层任务处理函数,用户可以根据需要修改 17 18 GenericApp_ProcessEvent //用户应用层任务处理函数,用户自己生成 19 20 };
如果不算调试任务,操作系统一共要处理6项任务,分别为MAC层,网络层。硬件抽象层,应用层,ZigBee设备应用层以及完全由用户处理的应用层,其优先级由高到低。MAC层任务具有最高优先级,用户层具有最低的优先级。Z-Stack已经编写了对从MAC层到ZigBee设备应用层这五层任务的事件处理函数,一般情况下不需要修改这些函数,只需要按照自己的需求编写应用层的任务及事件处理函数就可以。
其它的几个例子文件中,唯一不同的是最后一个函数其它的函数都是一样的。一般情况下用户只需要额外添加三个文件就可以完成一个项目。一个是主文件,存放具体的任务事件处理函数如上述事例中的GenericApp_ProcessEvent,一个是这个主文件的头文件,另外一个是操作系统的接口文件以Osal开头,是专门存放任务处理函数数组tasksArr[]的文件。这样就实现了Z-Stack代码的公用,用户只需要添加这几个文件,编写自己的任务处理函数就可以了。到现在是不是感觉很简单,别不想想像的那么复杂,这个操作系统抽象层和实时操作系统中的μC/OS-II有相似之处,唉μC/OS-II中可以分配给64个任务。了解了这个操作系统的话,理解OSAL应该不是很困难,但是,Z-Stack只是基于这个OSAL运行,但重点不在这里,而是ZigBee设备之间的通信的实现,以及组网,组成不同的网络结构,这些才是整个ZigBee协议中的核心内容,当然也应该远比我们添加几个文件来的复杂。
Z-Stack在项目中的目录结构
在Z-Stack项目中大约有14个目录文件,目录文件下面又有很多的子目录和文件。下面就来看看这14个根目录,具体是有什么作用:
(1) App:应用层目录,这个目录下的文件就是创建一个新项目时自己要添加的文件,
(2) HAL:硬件层目录,Common目录下的文件是公用文件,基本上与硬件无关,其中hal_assert.c是断言文件,用于调用,hal_drivers.c是驱动文件,抽象出与硬件无关的驱动函数,包含有与硬件相关的配置和驱动及操作函数。Include目录下主要包含各个硬件模块的头文件,而Target目录下的文件是跟硬件平台相关的,可能看到有两个平台,分别是Cc2430DB平台和一个CC2430EB平台。后面的DB和EB表示的是TI公司开发板的型号,其实还有一种类型是BB的,BB: Battery Board
DB: Development Board EB: Evaluation Board
分别对应TI公司开发的三种板型,其功能按上顺序依次变强。可以参看"Z-Stack User‘s Guide for CC2430"的图片,可以获得更直观的认识。
(3) MAC:MAC层目录,High Level和Low Level两个目录表示MAC层分为了高层和底层两层,Include目录下则包含了MAC层的参数配置文件及基MAC的LIB库函数接口文件,这里的MAC层的协议是不开源的,以库的形式给出
(4) MT:监制调试层目录,该目录下的文件主要用于调试目的,即实现通过串口调试各层,与各层进行直接交互。
(5) NWK:网络层目录,含有网络层配置参数文件及网络层库的函数接口文件,及APS层库的函数接口
(6) OSAL:协议栈的操作系统抽象层目录
(7) Profile:AF层目录,Application Farmework 应用框架,包含AF层处理函数接口文件。
(8) Security:安全层目录,包含安全层处理函数接口文件
(9) Services:ZigBee和802.15.4设备地址处理函数目录,包括地址模式的定义及地址处理函数
(10) Tools:工作配置目录,包括空间划分及Z-Stack相关配置信息
(11) ZDO:指ZigBee设备对象,可认为是一种公共的功能集,文件用户用自定义的对象调用APS子层的服务和NWK层的服务
(12) ZMAC:其中Zmac.c是Z-StackMAC导出层接口文件,zmac_cb.c是ZMAC需要调用的网络层函数
(13) Zmain:Zmain.c主要包含了整个项目的入口函数main(),在OnBoard.c包含硬件开始平台类外设进行控制的接口函数
(14) Output:输出文件目录,这个是EW8051 IDE自动生成的
以上是关于Z-Stack 软件架构分析的主要内容,如果未能解决你的问题,请参考以下文章