TI Z-stack协议栈开发环境和工作流程
2017-12-09 14:44
309 查看
ZStack 的体系结构由称为层的各模块组成。每一层为其上层提供特定的服务:即由
数据服务实体提供数据传输服务;管理实体提供所有的其他管理服务。每个服务实体通
过相应的服务接入点(SAP) 为其上层提供一个接口,每个服务接入点通过服务原语来完
成所对应的功能。
ZStack 根据 IEEE 802.15.4 和 ZigBee 标准分为以下几层:API(Application Program
ming Interface),HAL(Hardware Abstract Layer),MAC(Media Access Control),NWK(Z
igbee Network Layer),OSAL(Operating System Abstract System),Security,Service,Z
DO(Zigbee Device Objects)。ZStack 的体系结构如图所示
整个 ZStack 的主要工作流程,如图所示,大致分为以下 6 步:
(1) 关闭所有中断;
(2) 芯片外部(板载外设)初始化;
(3) 芯片内部初始化;
(4) 初始化操作系统;
(5) 打开所有中断;
(6) 执行操作系统。
其中,初始化操作系统和执行操作系统这两步是最为关键的两步。这两步都是在位
于 ZMain 文件夹下的 ZMain.c 文件里的 main 函数里进行的。
osal_init_system()函数里面是一些系统初始化操作,我们需要关心的是 osalInitTasks()函
数,至于其他的初始化函数,都是关于芯片正常工作所需要的配置,所以,用户可以不
用考虑。
下面分别介绍各层。
物理层(PHY)
物理层定义了物理无线信道和 MAC 子层之间的接口,提供物理层数据服务和物理
层管理服务,物理层内容:
(1)ZigBee 的激活;
(2) 当前信道的能量检测;
269
(3) 接收链路服务质量信息;
(4) ZigBee 信道接入方式;
(5) 信道频率选择;
(6) 数据传输和接收。
介质接入控制子层(MAC)
MAC 层负责处理所有的物理无线信道访问,并产生网络信号、同步信号;支持 P
AN 连接和分离,提供两个对等 MAC 实体之间可靠的链路。MAC 层功能:
(1) 网络协调器产生信标;
(2) 与信标同步;
(3) 支持 PAN (个域网) 链路的建立和断开;
(4) 为设备的安全性提供支持;
(5) 信道接入方式采用免冲突载波检测多址接入(CSMA-CA)机制;
(6) 处理和维护保护时隙(GTS )机制;
(7) 在两个对等的 MAC 实体之间提供一个可靠的通信链路。
网络层(NWK)
ZStack 的核心部分在网络层。网络层主要实现节点加入或离开网络、接收或抛弃其
他节点、路由查找及传送数据等功能。网络层功能:
(1) 网络发现;
(2) 网络形成;
(3) 允许设备连接;
(4) 路由器初始化;
(5) 设备同网络连接;
(6)直接将设备同网络连接;
(7)断开网络连接;
(8)重新复位设备;
(9)接收机同步;
(10)信息库维护。
应用层(APL)
ZStack 应用层框架包括应用支持层(APS)、ZigBee 设备对象(ZDO)和**商所定义
270
的应用对象。
(1) 应用支持层的功能包括:维持绑定表、在绑定的设备之间传送消息。
(2) ZigBee 设备对象的功能包括:定义设备在网络中的角色(如 ZigBee 协调器和终
端设备) ,发起和响应绑定请求,在网络设备之间建立安全机制。ZigBee 设备对象还负
责发现网络中的设备,并且决定向他们提供何种应用服务。
ZigBee 应用层除了提供一些必要函数以及为网络层提供合适的服务接口外,一个重
要的功能是应用者可在这层定义自己的应用对象。
应用程序框架(AF)
运行在 ZigBee 协议栈上的应用程序实际上就是厂商自定义的应用对象,并且遵循
规范(profile)运行在端点 1~240 上。在 ZigBee 应用中,提供 2 种标准服务类型:键值
对(KVP)或报文(MSG)。
ZigBee 设备对象(ZDO )
远程设备通过 ZDO 请求描述符信息,接收到这些请求时,ZDO 会调用配置对象获
取相应描述符值。另外,ZDO 提供绑定服务。
TI Z-stack协议栈学习-添加新任务
1.Zstack中如何实现自己的任务
在Zstack(TI的Zigbee协议栈)中,对于每个用户自己新建立的任务通常需要两个相关的处理函数,包括:
(1).用于初始化的函数,如:SampleApp_Init(),这个函数是在osalInitTasks()这个osal(Zstack中自带的小操作系统)中去调用的,其目的就是把一些用户自己写的任务中的一些变量,网络模式,网络终端类型等进行初始化;
(2).用于引起该任务状态变化的事件发生后所需要执行的事件处理函数,如: SampleApp_ProcessEvent(),这个函数是首先在const pTaskEventHandlerFn tasksArr[]中进行设置(绑定),然后在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()中增加.
void osalInitTasks( void )
{
uint8 taskID = 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++);
#if defined(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对于用户自行实现的事件处理函数uint16
SampleApp_ProcessEvent( uint8 task_id,uint16 events ),所以这里如果我们实现了一个任务,还需要把实现的该任务的事件处理函数在这里添加.
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK ) //一个MT任务命令
MT_ProcessEvent,
#endif
APS_event_loop,
ZDApp_event_loop,
SampleApp_ProcessEvent
};
注意, tasksEvents和tasksArr[]里的顺序是一一对应的,tasksArr[]中的第i个事件处理函数对应于tasksEvents中的第i个任务的事件.
//计算出任务的数量
const uint8 tasksCnt =sizeof(tasksArr)/sizeof(tasksArr[0]);
uint16 *tasksEvents;
3. 对于不同事件发生后的任务处理函数的调用
osal_start_system()很重要,决定了当某个任务的事件发生后调用对应的事件处理函数
void osal_start_system(void)
{
#if!defined(ZBIT)
for(;;)//Forever Loop
#endif
{
uint8 idx = 0;
Hal_ProcessPoll();//This replaces MT_SerialPoll() and //osal_check_timer().
//这里是轮训任务队列,并检查是否有某个任务的事件发生
do{
if (tasksEvents[idx])//Task is highest priority that is ready.
{
break;
}
}while(++idx<tasksCnt);
if(idx<tasksCnt)
{
uint16 events;
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState);
events=tasksEvents[idx];//处理该idx的任务事件,是第idx个任务的事件发生了
tasksEvents[idx] = 0; // Clear the Events for this task.
HAL_EXIT_CRITICAL_SECTION(intState);
//对应调用第idx个任务的事件处理函数,用events说明是什么事件
events = (tasksArr[idx])( idx, events );
//当没有处理完,把返回的events继续放到tasksEvents[idx]当中
HAL_ENTER_CRITICAL_SECTION(intState);
tasksEvents[idx] |= events; // Add back unprocessed events to the current task.
HAL_EXIT_CRITICAL_SECTION(intState);
}
#if defined( POWER_S**ING )
else // Complete pass through all task events with no activity?
{
osal_pwrmgr_powerconserve(); // Put the processor/system into sleep
}
#endif
}
}
2.Z-stack添加一个新的任务
在osalInitTasks()和tasksArr[]添加相应的项就可以了。
1.修改osalInitTasks()void osalInitTasks(void){OuhsApp_Init(taskID++);PhotoApp_Init(taskID);}
2.修改tasksArr[]const pTaskEventHa
在osalInitTasks()和tasksArr[]添加相应的项就可以了。
1.修改osalInitTasks()
void osalInitTasks( void )
{
……
OuhsApp_Init( taskID++ );
PhotoApp_Init( taskID);
}
2.修改tasksArr[]
const pTaskEventHandlerFn tasksArr[] = {
……
OuhsApp_ProcessEvent
PhotoApp_ProcessEvent
};
3.添加_Init()和_ProcessEvent()
void PhotoApp_Init(uint8 task_id)
{
PhotoApp_TaskID=task_id;
PhotoInit();
RegisterForPhoto( PhotoApp_TaskID );
}
uint16 PhotoApp_ProcessEvent( uint8 task_id uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
if ( events &SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( PhotoApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case PHOTO_CHANGE:
HalLedblink( HAL_LED_1 3 30 300 );
//P0IE=1;
break;
}
// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next - if one is **ailable
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( PhotoApp_TaskID );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
// Discard unknown events
return 0;
}
数据服务实体提供数据传输服务;管理实体提供所有的其他管理服务。每个服务实体通
过相应的服务接入点(SAP) 为其上层提供一个接口,每个服务接入点通过服务原语来完
成所对应的功能。
ZStack 根据 IEEE 802.15.4 和 ZigBee 标准分为以下几层:API(Application Program
ming Interface),HAL(Hardware Abstract Layer),MAC(Media Access Control),NWK(Z
igbee Network Layer),OSAL(Operating System Abstract System),Security,Service,Z
DO(Zigbee Device Objects)。ZStack 的体系结构如图所示
整个 ZStack 的主要工作流程,如图所示,大致分为以下 6 步:
(1) 关闭所有中断;
(2) 芯片外部(板载外设)初始化;
(3) 芯片内部初始化;
(4) 初始化操作系统;
(5) 打开所有中断;
(6) 执行操作系统。
其中,初始化操作系统和执行操作系统这两步是最为关键的两步。这两步都是在位
于 ZMain 文件夹下的 ZMain.c 文件里的 main 函数里进行的。
osal_init_system()函数里面是一些系统初始化操作,我们需要关心的是 osalInitTasks()函
数,至于其他的初始化函数,都是关于芯片正常工作所需要的配置,所以,用户可以不
用考虑。
下面分别介绍各层。
物理层(PHY)
物理层定义了物理无线信道和 MAC 子层之间的接口,提供物理层数据服务和物理
层管理服务,物理层内容:
(1)ZigBee 的激活;
(2) 当前信道的能量检测;
269
(3) 接收链路服务质量信息;
(4) ZigBee 信道接入方式;
(5) 信道频率选择;
(6) 数据传输和接收。
介质接入控制子层(MAC)
MAC 层负责处理所有的物理无线信道访问,并产生网络信号、同步信号;支持 P
AN 连接和分离,提供两个对等 MAC 实体之间可靠的链路。MAC 层功能:
(1) 网络协调器产生信标;
(2) 与信标同步;
(3) 支持 PAN (个域网) 链路的建立和断开;
(4) 为设备的安全性提供支持;
(5) 信道接入方式采用免冲突载波检测多址接入(CSMA-CA)机制;
(6) 处理和维护保护时隙(GTS )机制;
(7) 在两个对等的 MAC 实体之间提供一个可靠的通信链路。
网络层(NWK)
ZStack 的核心部分在网络层。网络层主要实现节点加入或离开网络、接收或抛弃其
他节点、路由查找及传送数据等功能。网络层功能:
(1) 网络发现;
(2) 网络形成;
(3) 允许设备连接;
(4) 路由器初始化;
(5) 设备同网络连接;
(6)直接将设备同网络连接;
(7)断开网络连接;
(8)重新复位设备;
(9)接收机同步;
(10)信息库维护。
应用层(APL)
ZStack 应用层框架包括应用支持层(APS)、ZigBee 设备对象(ZDO)和**商所定义
270
的应用对象。
(1) 应用支持层的功能包括:维持绑定表、在绑定的设备之间传送消息。
(2) ZigBee 设备对象的功能包括:定义设备在网络中的角色(如 ZigBee 协调器和终
端设备) ,发起和响应绑定请求,在网络设备之间建立安全机制。ZigBee 设备对象还负
责发现网络中的设备,并且决定向他们提供何种应用服务。
ZigBee 应用层除了提供一些必要函数以及为网络层提供合适的服务接口外,一个重
要的功能是应用者可在这层定义自己的应用对象。
应用程序框架(AF)
运行在 ZigBee 协议栈上的应用程序实际上就是厂商自定义的应用对象,并且遵循
规范(profile)运行在端点 1~240 上。在 ZigBee 应用中,提供 2 种标准服务类型:键值
对(KVP)或报文(MSG)。
ZigBee 设备对象(ZDO )
远程设备通过 ZDO 请求描述符信息,接收到这些请求时,ZDO 会调用配置对象获
取相应描述符值。另外,ZDO 提供绑定服务。
TI Z-stack协议栈学习-添加新任务
1.Zstack中如何实现自己的任务
在Zstack(TI的Zigbee协议栈)中,对于每个用户自己新建立的任务通常需要两个相关的处理函数,包括:
(1).用于初始化的函数,如:SampleApp_Init(),这个函数是在osalInitTasks()这个osal(Zstack中自带的小操作系统)中去调用的,其目的就是把一些用户自己写的任务中的一些变量,网络模式,网络终端类型等进行初始化;
(2).用于引起该任务状态变化的事件发生后所需要执行的事件处理函数,如: SampleApp_ProcessEvent(),这个函数是首先在const pTaskEventHandlerFn tasksArr[]中进行设置(绑定),然后在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()中增加.
void osalInitTasks( void )
{
uint8 taskID = 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++);
#if defined(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对于用户自行实现的事件处理函数uint16
SampleApp_ProcessEvent( uint8 task_id,uint16 events ),所以这里如果我们实现了一个任务,还需要把实现的该任务的事件处理函数在这里添加.
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK ) //一个MT任务命令
MT_ProcessEvent,
#endif
APS_event_loop,
ZDApp_event_loop,
SampleApp_ProcessEvent
};
注意, tasksEvents和tasksArr[]里的顺序是一一对应的,tasksArr[]中的第i个事件处理函数对应于tasksEvents中的第i个任务的事件.
//计算出任务的数量
const uint8 tasksCnt =sizeof(tasksArr)/sizeof(tasksArr[0]);
uint16 *tasksEvents;
3. 对于不同事件发生后的任务处理函数的调用
osal_start_system()很重要,决定了当某个任务的事件发生后调用对应的事件处理函数
void osal_start_system(void)
{
#if!defined(ZBIT)
for(;;)//Forever Loop
#endif
{
uint8 idx = 0;
Hal_ProcessPoll();//This replaces MT_SerialPoll() and //osal_check_timer().
//这里是轮训任务队列,并检查是否有某个任务的事件发生
do{
if (tasksEvents[idx])//Task is highest priority that is ready.
{
break;
}
}while(++idx<tasksCnt);
if(idx<tasksCnt)
{
uint16 events;
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState);
events=tasksEvents[idx];//处理该idx的任务事件,是第idx个任务的事件发生了
tasksEvents[idx] = 0; // Clear the Events for this task.
HAL_EXIT_CRITICAL_SECTION(intState);
//对应调用第idx个任务的事件处理函数,用events说明是什么事件
events = (tasksArr[idx])( idx, events );
//当没有处理完,把返回的events继续放到tasksEvents[idx]当中
HAL_ENTER_CRITICAL_SECTION(intState);
tasksEvents[idx] |= events; // Add back unprocessed events to the current task.
HAL_EXIT_CRITICAL_SECTION(intState);
}
#if defined( POWER_S**ING )
else // Complete pass through all task events with no activity?
{
osal_pwrmgr_powerconserve(); // Put the processor/system into sleep
}
#endif
}
}
2.Z-stack添加一个新的任务
在osalInitTasks()和tasksArr[]添加相应的项就可以了。
1.修改osalInitTasks()void osalInitTasks(void){OuhsApp_Init(taskID++);PhotoApp_Init(taskID);}
2.修改tasksArr[]const pTaskEventHa
在osalInitTasks()和tasksArr[]添加相应的项就可以了。
1.修改osalInitTasks()
void osalInitTasks( void )
{
……
OuhsApp_Init( taskID++ );
PhotoApp_Init( taskID);
}
2.修改tasksArr[]
const pTaskEventHandlerFn tasksArr[] = {
……
OuhsApp_ProcessEvent
PhotoApp_ProcessEvent
};
3.添加_Init()和_ProcessEvent()
void PhotoApp_Init(uint8 task_id)
{
PhotoApp_TaskID=task_id;
PhotoInit();
RegisterForPhoto( PhotoApp_TaskID );
}
uint16 PhotoApp_ProcessEvent( uint8 task_id uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
if ( events &SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( PhotoApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case PHOTO_CHANGE:
HalLedblink( HAL_LED_1 3 30 300 );
//P0IE=1;
break;
}
// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next - if one is **ailable
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( PhotoApp_TaskID );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
// Discard unknown events
return 0;
}
相关文章推荐
- TI Z-stack协议栈开发环境和工作流程
- TI Z-stack协议栈开发环境和工作流程
- TI Z-stack协议栈开发环境和工作流程
- 【转】TI Z-stack协议栈开发环境和工作流程
- struts2系列(一):struts2入门(struts2的产生、struts2的工作流程、搭建struts2开发环境)
- 【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)
- 开发环境和工作流程
- 【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)
- 驰骋工作流程引擎 java .net 开发人员- 英才招聘
- 【cc2541开发环境】BLE-CC254x-1.4.0协议栈的安装
- 一步步告诉你stm32开发环境搭建流程
- Linux服务器开发/测试环境搭建流程
- 苹果产品开发的绝密工作流程
- 使用otter实现MySQL跨机房双向同步 工作流程 环境 目标 名词解释 安装 配置 配置mysql 导入 manager 系统表 导入 node 同步算法依赖的系统表 管理配置 添加zookee
- Android studio3.0环境下进行NDK开发的环境配置与流程
- MTK 开发流程和开发环境小记
- App开发之前的工作准备和开发中的一些流程
- 软件项目开发环境构建之一:整体流程
- git- 利用分支进行开发的工作流程
- 工作小结:Emacs的Flex开发环境搭建