Zstack协议栈开发.docx

上传人:b****5 文档编号:26434663 上传时间:2023-06-19 格式:DOCX 页数:12 大小:87.23KB
下载 相关 举报
Zstack协议栈开发.docx_第1页
第1页 / 共12页
Zstack协议栈开发.docx_第2页
第2页 / 共12页
Zstack协议栈开发.docx_第3页
第3页 / 共12页
Zstack协议栈开发.docx_第4页
第4页 / 共12页
Zstack协议栈开发.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

Zstack协议栈开发.docx

《Zstack协议栈开发.docx》由会员分享,可在线阅读,更多相关《Zstack协议栈开发.docx(12页珍藏版)》请在冰豆网上搜索。

Zstack协议栈开发.docx

Zstack协议栈开发

TIZ-stack协议栈开发环境和工作流程

系统软件设计是在硬件设计的基础上进行的,良好的软件设计是实现系统功能的重要环节,也是提高系统性能的关键所在。

节点设计基于通用性及便于开发的考虑,移植了TI公司的Z-Stack协议栈,其主要特点就是其兼容性,完全支持IEEE802.15.4/ZigBee的CC2430片上系统解决方案。

Z-Stack还支持丰富的新特性,如无线下载,可通过ZigBee网状网络(MeshNetwork)下载节点更新。

图ZigBee节点开发环境

TI的Z-Stack装载在一个基于IAR开发环境的工程里。

强大的IAREmbeddedWorkbench除了提供编译下载功能外,还可以结合编程器进行单步跟踪调试和监测片上寄存器、Flash数据等。

Z-Stack根据IEEE802.15.4和ZigBee标准分为以下几层:

API(ApplicationProgrammingInterface),HAL(HardwareAbstractLayer),MAC(MediaAccessControl),NWK(ZigbeeNetworkLayer),OSAL(OperatingSystemAbstractSystem),Security,Service,ZDO(ZigbeeDeviceObjects)。

使用IAR打开工程文件SampleApp.eww后,即可查看到整个协议栈从HAL层到APP层的文件夹分布。

该协议栈可以实现复杂的网络链接,在协调器节点中实现对路由表和绑定表的非易失性存储,因此网络具有一定的记忆功能。

Z-Stack采用操作系统的思想来构建,采用事件轮循机制,当各层初始化之后,系统进入低功耗模式,当事件发生时,唤醒系统,开始进入中断处理事件,结束后继续进入低功耗模式。

如果同时有几个事件发生,判断优先级,逐次处理事件。

这种软件构架可以极大地降级系统的功耗。

整个Z-stack的主要工作流程,大致分为系统启动,驱动初始化,OSAL初始化和启动,进入任务轮循几个阶段,下面将逐一详细分析。

图Z-Stack系统运行流程图

Figure.TheFlowChartofZ-Stack

系统初始化

系统上电后,通过执行ZMain文件夹中ZMain.c的ZSEGintmain()函数实现硬件的初始化,其中包括关总中断osal_int_disable(INTS_ALL)、初始化板上硬件设置HAL_BOARD_INIT()、初始化I/O口InitBoard(OB_COLD)、初始化HAL层驱动HalDriverInit()、初始化非易失性存储器sal_nv_init(NULL)、初始化MAC层ZMacInit()、分配64位地址zmain_ext_addr()、初始化操作系统osal_init_system()等。

硬件初始化需要根据HAL文件夹中的hal_board_cfg.h文件配置寄存器8051的寄存器。

TI官方发布Z-stack的配置针对的是TI官方的开发板CC2430DB、CC2430EMK等,如采用其他开发板,则需根据原理图设计改变hal_board_cfg.h文件配置,例如本方案制作的实验板与TI官方的I/O口配置略有不同,其中状态指示LED2的需要重新设置LED2控制引脚口、通用I/O口方向和控制函数定义等。

当顺利完成上述初始化时,执行osal_start_system()函数开始运行OSAL系统。

该任务调度函数按照优先级检测各个任务是否就绪。

如果存在就绪的任务则调用tasksArr[]中相对应的任务处理函数去处理该事件,直到执行完所有就绪的任务。

如果任务列表中没有就绪的任务,则可以使处理器进入睡眠状态实现低功耗。

程序流程如图3-13所示。

osal_start_system()一旦执行,则不再返回Main()函数。

OSAL任务调度流程图

Figure.TheFlowChartofOSALScheduler

OSAL任务

OSAL是协议栈的核心,Z-stack的任何一个子系统都作为OSAL的一个任务,因此在开发应用层的时候,必须通过创建OSAL任务来运行应用程序。

通过osalInitTasks()函数创建OSAL任务,其中TaskID为每个任务的唯一标识号。

任何OSAL任务必须分为两步:

一是进行任务初始化;二是处理任务事件。

任务初始化主要步骤如下:

(1)初始化应用服务变量。

constpTaskEventHandlerFntasksArr[]数组定义系统提供的应用服务和用户服务变量,如MAC层服务macEventLoop、用户服务SampleApp_ProcessEvent等

(2)分配任务ID和分配堆栈内存

voidosalInitTasks(void)主要功能是通过调用osal_mem_alloc()函数给各个任务分配内存空间,和给各个已定义任务指定唯一的标识号。

(3)在AF层注册应用对象

通过填入endPointDesc_t数据格式的EndPoint变量,调用afRegister()在AF层注册EndPoint应用对象。

通过在AF层注册应用对象的信息,告知系统afAddrType_t地址类型数据包的路由端点,例如用于发送周期信息的SampleApp_Periodic_DstAddr和发送LED闪烁指令的SampleApp_Flash_DstAddr。

(4)注册相应的OSAL或则HAL系统服务

在协议栈中,Z-stack提供键盘响应和串口活动响应两种系统服务,但是任何Z-Stask任务均不自行注册系统服务,两者均需要由用户应用程序注册。

值得注意的是,有且仅有一个OSALTask可以注册服务。

例如注册键盘活动响应可调用RegisterForKeys()函数。

(5)处理任务事件

处理任务事件通过创建“ApplicationName”_ProcessEvent()函数处理。

一个OSAL任务除了强制事件(MandatoryEvents)之外还可以定义15个事件。

SYS_EVENT_MSG(0x8000)是强制事件。

该事件主要用来发送全局的系统信息,包括以下信息:

AF_DATA_CONFIRM_CMD:

该信息用来指示通过唤醒AFDataRequest()函数发送的数据请求信息的情况。

ZSuccess确认数据请求成功的发送。

如果数据请求是通过AF_ACK_REQUEST置位实现的,那么ZSussess可以确认数据正确的到达目的地。

否则,ZSucess仅仅能确认数据成功的传输到了下一个路由。

AF_INCOMING_MSG_CMD:

用来指示接收到的AF信息。

KEY_CHANGE:

用来确认按键动作。

ZDO_NEW_DSTADDR:

用来指示自动匹配请求。

ZDO_STATE_CHANGE:

用来指示网络状态的变化。

网络层信息

Zigbee设备有两种网络地址:

1个是64位的IEEE地址,通常也叫作MAC地址或者扩展地址(Extendedaddress),另一个是16位的网络地址,也叫做逻辑地址(Logicaladdress)或者短地址。

64位长地址是全球唯一的地址,并且终身分配给设备。

这个地址可由制造商设定或者在安装的时候设置,是由IEEE来提供。

当设备加入Zigbee网络被分配一个短地址,在其所在的网络中是唯一的。

这个地址主要用来在网络中辨识设备,传递信息等。

协调器(Coordinator)首先在某个频段发起一个网络,网络频段的定义放在DEFAULT_CHANLIST配置文件里。

如果ZDAPP_CONFIG_PANID定义的PANID是0xFFFF(代表所有的PANID),则协调器根据它的IEEE地址随机确定一个PANID。

否则,根据ZDAPP_CONFIG_PANID的定义建立PANID。

当节点为Router或者EndDevice时,设备将会试图加入DEFAULT_CHANLIST所指定的工作频段。

如果ZDAPP_CONFIG_PANID没有设为0xFFFF,则Router或者EndDevice会加入ZDAPP_CONFIG_PANID所定义的PANID。

设备上电之后会自动的形成或加入网络,如果想设备上电之后不马上加入网络或者在加入网络之前先处理其他事件,可以通过定义HOLD_AUTO_START来实现。

通过调用ZDApp_StartUpFromApp()来手动定义多久时间之后开始加入网络。

设备如果成功的加入网络,会将网络信息存储在非易失性存储器(NVFlash)里,掉电后仍然保存,这样当再次上电后,设备会自动读取网络信息,这样设备对网络就有一定的记忆功能。

对NVFlash的动作,通过NV_RESTORE()和NV_ITNT()函数来执行。

有关网络参数的设置大多保存在协议栈Tools文件夹的f8wConfig.cfg里。

路由

Z-Stack采用无线自组网按需平面距离矢量路由协议AODV,建立一个Hoc网络,支持移动节点,链接失败和数据丢失,能够自组织和自修复。

当一个Router接受到一个信息包之后,NMK层将会进行以下的工作:

首先确认目的地,如果目的地就是这个Router的邻居,信息包将会直接传输给目的设备;否则,Router将会确认和目的地址相应的路由表条目,如果对于目的地址能找到有效的路由表条目,信息包将会被传递到该条目中所存储的下一个hop地址;如果找不到有效的路由表条目,路由探测功能将会被启动,信息包将会被缓存直到发现一个新的路由信息。

ZigBeeEndDevice不会执行任何路由函数,它只是简单的将信息传送给前面的可以执行路由功能的父设备。

因此,如果EndDevice想发送信息给另外一个EndDevice,在发送信息之间将会启动路由探测功能,找到相应的父路由节点。

TIZ-stack协议栈学习-添加新任务

1.Zstack中如何实现自己的任务

在Zstack(TI的Zigbee协议栈)中,对于每个用户自己新建立的任务通常需要两个相关的处理函数,包括:

(1).用于初始化的函数,如:

SampleApp_Init(),这个函数是在osalInitTasks()这个osal(Zstack中自带的小操作系统)中去调用的,其目的就是把一些用户自己写的任务中的一些变量,网络模式,网络终端类型等进行初始化;

(2).用于引起该任务状态变化的事件发生后所需要执行的事件处理函数,如:

SampleApp_ProcessEvent(),这个函数是首先在constpTaskEventHandlerFntasksArr[]中进行设置(绑定),然后在osalInitTasks()中如果发生事件进行调用绑定的事件处理函数.

下面分3个部分分析.

1.用户自己设计的任务代码在Zstack中的调用过程

(1).main()执行(在ZMain.c中)

main()--->osal_init_system()

(2).osal_init_system()调用osalInitTasks(),(在OSAL.c中)

osal_init_system()--->osalInitTasks()

(3).osalInitTasks()调用SampleApp_Init(),(在OSAL_SampleApp.c中)

osalInitTasks()--->SampleApp_Init()

在osalInitTasks()中实现了多个任务初始化的设置,其中macTaskInit(taskID++)到ZDApp_Init(taskID++)的几行代码表示对于几个系统运行初始化任务的调用,而用户自己实现的SampleApp_Init()在最后,这里taskID随着任务的增加也随之递增.所以用户自己实现的任务的初始化操作应该在osalInitTasks()中增加.

voidosalInitTasks(void)

{

uint8taskID=0;

//这里很重要,调用osal_mem_alloc()为当前OSAL中的各任务分配存储空间(实际上是一个任//务数组),并用tasksEvents指向该任务数组(任务队列).

tasksEvents=(uint16*)osal_mem_alloc(sizeof(uint16)*tasksCnt);

osal_memset(tasksEvents,0,(sizeof(uint16)*tasksCnt));//将taskSEvents所指向的空间清零

macTaskInit(taskID++);

nwk_init(taskID++);

Hal_Init(taskID++);

#ifdefined(MT_TASK)

MT_TaskInit(taskID++);

#endif

APS_Init(taskID++);

ZDApp_Init(taskID++);

SampleApp_Init(taskID);//用户自己需要添加的任务

}

2.任务处理调用的重要数据结构

这里要解释一下,在Zstack里,对于同一个任务可能有多种事件发生,那么需要执行不同的事件处理,为了方便,对于每个任务的事件处理函数都统一在一个事件处理函数中实现,然后根据任务的ID号(task_id)和该任务的具体事件(events)调用某个任务的事件处理函数,进入了该任务的事件处理函数之后,再根据events再来判别是该任务的哪一种事件发生,进而执行相应的事件处理.pTaskEventHandlerFn是一个指向函数(事件处理函数)的指针,这里实现的每一个数组元素各对应于一个任务的事件处理函数,比如SampleApp_ProcessEvent对于用户自行实现的事件处理函数uint16SampleApp_ProcessEvent(uint8task_id,uint16events),所以这里如果我们实现了一个任务,还需要把实现的该任务的事件处理函数在这里添加.

constpTaskEventHandlerFntasksArr[]={

macEventLoop,

nwk_event_loop,

Hal_ProcessEvent,

#ifdefined(MT_TASK)//一个MT任务命令

MT_ProcessEvent,

#endif

APS_event_loop,

ZDApp_event_loop,

SampleApp_ProcessEvent

};

注意,tasksEvents和tasksArr[]里的顺序是一一对应的,tasksArr[]中的第i个事件处理函数对应于tasksEvents中的第i个任务的事件.

//计算出任务的数量

constuint8tasksCnt=sizeof(tasksArr)/sizeof(tasksArr[0]);

uint16*tasksEvents;

3.对于不同事件发生后的任务处理函数的调用

osal_start_system()很重要,决定了当某个任务的事件发生后调用对应的事件处理函数

voidosal_start_system(void)

{

#if!

defined(ZBIT)

for(;;)//ForeverLoop

#endif

{

uint8idx=0;

Hal_ProcessPoll();//ThisreplacesMT_SerialPoll()and//osal_check_timer().

//这里是轮训任务队列,并检查是否有某个任务的事件发生

do{

if(tasksEvents[idx])//Taskishighestprioritythatisready.

{

break;

}

}while(++idx

if(idx

{

uint16events;

halIntState_tintState;

HAL_ENTER_CRITICAL_SECTION(intState);

events=tasksEvents[idx];//处理该idx的任务事件,是第idx个任务的事件发生了

tasksEvents[idx]=0;//CleartheEventsforthistask.

HAL_EXIT_CRITICAL_SECTION(intState);

//对应调用第idx个任务的事件处理函数,用events说明是什么事件

events=(tasksArr[idx])(idx,events);

//当没有处理完,把返回的events继续放到tasksEvents[idx]当中

HAL_ENTER_CRITICAL_SECTION(intState);

tasksEvents[idx]|=events;//Addbackunprocessedeventstothecurrenttask.

HAL_EXIT_CRITICAL_SECTION(intState);

}

#ifdefined(POWER_SAVING)

else//Completepassthroughalltaskeventswithnoactivity?

{

osal_pwrmgr_powerconserve();//Puttheprocessor/systemintosleep

}

#endif

}

}

2.Z-stack添加一个新的任务

在osalInitTasks()和tasksArr[]添加相应的项就可以了。

1.修改osalInitTasks()voidosalInitTasks(void){OuhsApp_Init(taskID++);PhotoApp_Init(taskID);}

2.修改tasksArr[]constpTaskEventHa

在osalInitTasks()和tasksArr[]添加相应的项就可以了。

1.修改osalInitTasks()

voidosalInitTasks(void)

{

……

OuhsApp_Init(taskID++);

PhotoApp_Init(taskID);

}

2.修改tasksArr[]

constpTaskEventHandlerFntasksArr[]={

……

OuhsApp_ProcessEvent

PhotoApp_ProcessEvent

};

3.添加_Init()和_ProcessEvent()

voidPhotoApp_Init(uint8task_id)

{

PhotoApp_TaskID=task_id;

PhotoInit();

RegisterForPhoto(PhotoApp_TaskID);

}

uint16PhotoApp_ProcessEvent(uint8task_iduint16events)

{

afIncomingMSGPacket_t*MSGpkt;

if(events&SYS_EVENT_MSG)

{

MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive(PhotoApp_TaskID);

while(MSGpkt)

{

switch(MSGpkt->hdr.event)

{

casePHOTO_CHANGE:

HalLedblink(HAL_LED_1330300);

//P0IE=1;

break;

}

//Releasethememory

osal_msg_deallocate((uint8*)MSGpkt);

//Next-ifoneisavailable

MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive(PhotoApp_TaskID);

}

//returnunprocessedevents

return(events^SYS_EVENT_MSG);

}

//Discardunknownevents

return0;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1