06 ZStack的task工作流程分析

本文深入解析ZStack-CC2530的安装与使用,重点介绍了其内部多任务操作系统的工作原理,包括任务调度机制、事件处理流程及任务间的通信方式。

安装ZStack-CC2530-2.5.1a.exe

默认安装到”C:\Texas Instruments\ZStack-CC2530-2.5.1a”目录下.
这里写图片描述

Components目录里实现 hal层、stack网络协议栈、mac层的封装, 而且也实现了osal操作系统的功能等. 通常情况下我们就是调用里面实现好的功能函数就可以了.

Documents目录里存放有各个分层的的功能函数的说明文档.

Projects目录存放TI提供的应用案例,我们可以基于这些案例上根据项目需要求进行修改.

Tools目录里存放TI提供的,用于在pc端使用的工具.

/////////////////////////////////////////////
这里写图片描述
打开此目录下的SampleApp.eww工程.

///////////////
在此位置选择要编译的设备类型, 不管是要作协调器,路由器,终端设备都是共用一个工程源码的。只要选择不同的设备类型,在编译时会自动编译加入相应的设备角色功能.
这里写图片描述

工程里目录说明(摘自开发板文档):
这里写图片描述

ZStack虽然叫zigbee协议栈,但除了网络数据的协议栈外还有一个多任务的操作系统。
////////////////////////////////////////////////////////////////////////////////////////////////////
协议栈里的操作系统工作原理分析:
里面的操作系统是支持多任务(多进程)同时执行的, 每个任务都是基于事件触发调度的。简单来说, 此系统就是在main函数里用个死循环,循环检查每个任务是否有事件发生, 如有事件发生则调用此任务的事件处理函数。

每个任务都有一个唯一的任务号,根据此任务号可以区别相应的任务。每个任务的事件都由一个uint16类型变量来存放,
每种事件占用一位,相应的位为1即表示有相应的事件发生。而且每个任务都有一个事件处理函数,只要有事件发生了,
系统就会调用任务的事件处理函数来处理已发生的事件. 除此外,每个任务还有一个初始化函数,
用于记录分配的任务号并作任务工作前的初始化工作

在OSAL_SampleApp.c源文件里:

每个任务的事件处理函数地址由全局函数指针数组tasksArr数组来存放。此数组的元素个数即就是系统里的任务个数。
同时此数组里是按任务的任务号从小到大顺序来存放的,即可以tasksArr[任务号]得到相应任务的事件处理函数地址.
//协议栈里的每个分层都由一个任务来实现相应的功能。
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任务的事件处理函数
};

const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] ); //此全局变量记录任务的个数
uint16 *tasksEvents; //注意全局指针变量tasksEvents其实相当于一个数组(uint16 tasksEvents[tasksCnt]), 每个任务的事件都由一个uint16元素来记录。 即tasksEvents[任务号]可得到相应任务的事件信息.

void osalInitTasks( void ) //系统初始化所有任务的函数,此函数在系统初始化后被调用
{
  uint8 taskID = 0; //用于分配的任务号

  tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt); //这里动态分配空间,用于记录每个任务的事件信息.
  osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt)); //就是先把每个任务的事件信息清零

  //下面是调用每个任务的初始化函数,并传递分配的任务号。注意此顺序需与在tasksArr函数指针数组里的初始化顺序一致.
  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
  SampleApp_Init( taskID ); //调用SampleApp任务的初始化函数
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
系统的具体工作流程:

系统最先是从工程的ZMain目录里的ZMain.c的79行的main函数开始执行的.

//这里只关注任务的调度,其它的就不深入了
int main(void)
{
    ...
    osal_init_system();  //系统初始化函数
        ...
        //里面有调用上面的系统任务函数
        osalInitTasks();
            ...
            //再进一步也就会调用各个任务的初始化函数,也包括SampleApp任务的初始化函数
            SampleApp_Init( taskID ); 

    ...
    //main函数最后,就是开始系统工作了
    osal_start_system();    
        //osal_start_system函数里面就是个死循环,循环调用osal_run_system
        osal_run_system(); //此函数就是任务调度的实现
}

void osal_run_system( void )
{
  uint8 idx = 0; //此变量用于记录当前检查的任务的任务号

  osalTimeUpdate();
  Hal_ProcessPoll();

  do {
    if (tasksEvents[idx])  //不要忘了tasksEvents就是一个记录所有任务事件的数组,以任务号为下标.
    {
      break;  //如果tasksEvents[idx]不为零,则表示任务号为idx的任务有事件发生需要处理事件, 结束当前循环.
    }
  } while (++idx < tasksCnt); //tasksCnt为任务的个数

  if (idx < tasksCnt)  // 有事件发生的任务需处理
  {
    uint16 events;
    halIntState_t intState;

    HAL_ENTER_CRITICAL_SECTION(intState); //进入防止并发处理的状态(上锁)
    events = tasksEvents[idx]; //先用events变量记录任务的事件
    tasksEvents[idx] = 0;  // Clear the Events for this task.
    HAL_EXIT_CRITICAL_SECTION(intState); //退出防止并发的状态(解锁)

    activeTaskID = idx;
    events = (tasksArr[idx])( idx, events ); //不要忘了tasksArr是一个全局函数指针变量数组,记录所有任务的事件处理函数的地址. 这里调用有事件发生的任务的事件处理函数,并传递它的任务号及事件信息。最后用events变量存放返回值,返回值为尚未处理的事件信息,如返回0则表示当前已发生事件都已经处理了.

    ...
    HAL_ENTER_CRITICAL_SECTION(intState);
    tasksEvents[idx] |= events; //把没有处理的事件信息存放到tasksEvent数组里,下次检查时,将会处理还没有处理的事件.
    HAL_EXIT_CRITICAL_SECTION(intState);
  }
    ...
}

总结,每个任务有一个初始化函数及事件处理函数, 而且所有任务的事件都在tasksEvent里存放起来。任务间的通信可以通过改变相应任务的事件信息来实现.

<think>好的,我现在需要回答用户关于ZStack协调器工作机制和实现原理的问题。用户已经提供了多个相关的引用资料,我需要仔细分析这些资料并综合出一个清晰的回答。 首先,用户提供的引用中提到Z-Stack协议栈的结构,包括OSAL操作系统、CC2530硬件模块和AF无线网络应用[^1][^2]。协调器作为ZigBee网络的中心节点,需要负责网络的初始化和维护。根据引用[3],ZigBee组网包括网络发现、路由发现和节点加入三个阶段,协调器应该在这三个阶段中起关键作用。 然后,引用[5]提到ZStack中的任务划分,每个任务有唯一的task_id,并且通过事件处理机制来管理。协调器作为任务之一,应该有自己的task_id和事件处理函数。硬件抽象层(HAL)处理硬件相关操作[^4],这可能涉及到协调器的射频模块配置和通信。 接下来,我需要整理协调器的工作流程。首先,协调器初始化硬件,如CC2530的射频模块,这可能通过HAL层完成[^5]。然后,启动网络组建,分配网络地址,可能涉及网络层的配置。接着,处理设备加入请求,维护路由表,这些属于网络层的功能。任务调度方面,OSAL负责管理任务事件,协调器的事件处理函数可能包括处理入网请求、数据转发等。 还需要考虑安全性,比如使用加密算法,但引用中没有明确提到,可能需要推测或留空。另外,引用[5]提到应用层由开发者编写,协调器的应用逻辑可能包括启动网络、管理设备等。 最后,用户要求生成相关问题,需要根据协调器的功能、协议栈结构、任务调度等方面提出问题,比如协调器启动流程、任务事件处理、网络地址分配等。</think>### ZStack协调器工作机制及实现原理 ZStack协调器是ZigBee网络的**核心控制节点**,负责网络初始化、设备接入管理和数据路由。其工作机制可分为以下关键步骤: #### 1. **硬件初始化与协议栈启动** - 协调器上电后通过**HAL层**初始化射频模块(如CC2530芯片),配置信道、PAN ID等参数 - 加载**网络层协议栈**,设置网络拓扑结构(如树状/网状网络) - 初始化**OSAL任务系统**,为协调器分配唯一的`task_id`[^5] #### 2. **网络组建阶段** ```c // 网络初始化代码示例(Z-Stack) void Coordinator_Init() { zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR; //声明设备类型 ZDO_Init(); //初始化网络层 afRegister( (endPointDesc_t*)&Coordinator_epDesc ); //注册应用端点 } ``` - 执行信道能量扫描(Energy Scan)选择最优信道[^3] - 建立**网络信标**(Beacon),广播网络参数 - 生成16位短地址(默认为0x0000)并分配子设备地址块[^3] #### 3. **设备接入管理** - 通过**ZDO层**(ZigBee Device Object)处理`ZDO_DEVICE_ANNOUNCE`消息[^5] - 维护**邻居表**(Neighbor Table)记录子设备信息 - 实施**安全认证**(如AES-128加密) #### 4. **任务调度机制** OSAL操作系统通过**事件轮询**处理协调器任务: ```c // 事件处理伪代码 void Coordinator_ProcessEvent(uint8 task_id, uint16 events) { if(events & NETWORK_JOIN_REQUEST_EVENT) { handleJoinRequest(); //处理入网请求 } if(events & DATA_ROUTING_EVENT) { routeDataPacket(); //数据包路由 } } ``` 每个事件对应特定操作,通过`osal_set_event()`触发 #### 5. **数据路由实现** - 维护**路由表**(Routing Table) - 使用**Cluster Tree**或**AODV**路由算法转发数据包 - 通过**AF层**(Application Framework)实现端到端通信[^1] : Z-Stack协议栈包含完整的网络层实现 : 协调器需要完成网络参数配置 : 任务事件机制是OSAL调度的核心
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值