关闭

Z-stack中OSAL任务机制分析

标签: zigebeeZ-stackOSALtasksEventtasksArr
1220人阅读 评论(0) 收藏 举报
分类:

  关于Z-STACK的任务处理机制已经有很多前辈写过了一些教程,我这里写一点自己的理解。
  首先认识几个名词:
  协议:标准,约定。
  协议栈:各层协议的总和,也就是实现这些协议的代码。
  Z-STACK:zigbee协议栈的名字。
  OSAL类似于操作系统,是以实现多任务为核心的系统资源管理机制。
  任务:又可称为线程(个人理解,这里说的可能不对),是一个简单的任务执行过程,在任务执行的过程中CPU完全属于该任务。在Z-STACK中,不同的层拥有不同的任务ID,并且这个任务ID的号码与该层任务的执行次序一致。
  Z-STACK中重要的三个变量:
  TasksCnt,TasksEvents,tasksArr[idx];
  TasksCnt:任务的总个数,写死了,不会变化。
  TasksEvents:是个指针,当然同时也是一个数组。其索引idx代表不同的层,由于Z-stack的每一个层都有一个唯一的任务ID,所以idx的值与同层的任务ID值一样。同时,数组的某个元素的值表示了该层有几个事件。下面以应用层为例说明:
  看tasksEvents的定义与动态内存分配:

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

  等价为uint16 tasksEvents[TasksCnt],一个数组,数组中的每个元素都是个两字节的数字,共有TasksCnt个元素。
  再看OSAL的任务初始化函数

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 );
}

  发现每个层的初始化函数传入的参数taskID都是递增的,这个taskID也就是本层的任务号,同时也是本层tasksEvents[idx]中idx的值。例如GenericApp_Init( taskID ),这个是应用层的初始化(用户自定义的函数,可能名字会不一样),到这里的taskID值为8的话,那么代表用户自定义任务的tasksEvents[idx]中idx的值也是8。
  再看tasksEvents[idx]这个元素的值,代表的是某一层的事件,初始值0x0000,按位展开就是:0000 0000 0000 0000,每一个二进制位都可以用来设置一个事件,例如系统事件宏定义:

#define    SYS_EVENT_MSG               0x8000

  按位展开就是1000 0000 0000 0000,
  假如我们定义一个发送事件为

#define   SERIALAPP_SEND_EVT           0x0001,

  按位展开就是0000 0000 0000 0001,
  那么假如tasksEvents[8]= 0x8001,就代表着同时有SYS_EVENT_MSG和SERIALAPP_SEND_EVT两个事件。
  任务调度中有个死循环,不断检测这个元素的值是否非0,检测到

  do {
    if (tasksEvents[idx])  // Task is highest priority that is ready.
    {
      break;//有事件发生则跳出循环
    }
  } while (++idx < tasksCnt);

  具体怎么处理每个任务的不同事件,见tasksArr[idx];
tasksArr[idx]的定义:

typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short event );

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
};

  可以看出tasksArr[idx]是一个指针(也就是数组),指向一个函数(数组元素是函数),函数的参数就是task_id与events。task_id与本层的任务ID是对应的,当然也对应着tasksEvents[idx]中idx的值,而events正好也对应这元素tasksEvents[idx]的值。如

uint16 GenericApp_ProcessEvent( uint8 task_id, uint16 events )

  这些函数也就是各个层的处理函数。
  再来看一下每个事件具体是怎样处理的:
在处理用户自定义的任务函数——GenericApp_ProcessEvent函数中,有如下语句:
  如果检测到SYS_EVENT_MSG(也就是tasksEvents[8]的二进制位最高位是1)

  if ( events & SYS_EVENT_MSG )
{
    处理语句
}
return (events ^ SYS_EVENT_MSG);

  返回值执行了异或操作,也就是说把SYS_EVENT_MSG占据的这一个二进制位清零了,代表这个事件执行完毕,且不会影响其它位所代表的事件。
例如此时这一层的任务有两个事件SYS_EVENT_MSG与SERIALAPP_SEND_EVT(此事件是自定义的),那么传入的参数events值就是0x8001,执行完return (events ^ SYS_EVENT_MSG)之后值为0x0001,不会影响if ( events & SERIALAPP_SEND_EVT )的判断结果。当然,由于函数已经执行了返回值的操作,无法再执行后边的语句,SERIALAPP_SEND_EVT事件只能等到下一次执行GenericApp_ProcessEvent函数的时候,才有可能处理。
  再来看一下死循环osal_run_system中的任务处理相关语句:

    events = tasksEvents[idx];//提取需要处理的任务事件
    tasksEvents[idx] = 0;  // Clear the Events for this task.

    activeTaskID = idx;
    events = (tasksArr[idx])( idx, events );//通过指针调用处理函数,处理结束事件按位清零
    activeTaskID = TASK_NO_TASK;

    tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.

  关注events,先从tasksEvents中提取idx层中的所有事件(可能不是一个),然后作为参数传入(tasksArr[idx])( idx, events )中进行处理,处理函数在处理了一个事件之后会执行一个异或操作,消除已经处理了的一个事件,然后作为tasksArr[idx]的返回值重新赋值给events,再有events传值给tasksEvents[idx],如果这一层的任务中还有别的事件,那么就由主函数的下一次循环来处理。

  顺带提一下,占据二进制位的顺序越靠左,那么这个事件的优先级就越高。tasksEvents[idx]中idx的值越小,那么这一层任务的优先级也就越高。
以上

0
0
查看评论

谈谈OSAL

Z-Stack1.4.3及以后的版本中引入了一个OSAL(Operating System Abstraction Layer 操作系统抽象层)但在我们整个的ZigBee协议栈的结构图中我并没有能够发现这个层在哪个位置。但是整个的协议栈都要在OS的基础上才能运行。OSAL和我们通常所说的RTOS...
  • oHeXiWei
  • oHeXiWei
  • 2013-01-04 09:53
  • 840

不需要移植,在keil上打个勾就让stm32跑起操作系统

http://blog.csdn.net/ichamber/article/details/53113195      初识keil5,不得不说自动化配置的强大,建个新工程基本不需要各种粘贴复制文件夹,以前一直担心直接拷贝模板工程会同时拷贝很多垃圾文件,现...
  • android_lover2014
  • android_lover2014
  • 2017-02-11 13:17
  • 2135

OSAL系统移植

  • 2013-04-24 20:08
  • 3.50MB
  • 下载

任务处理表tasksEvents是怎么被改动的及zigbee协议栈分析

任务处理表taskEvents的处理有几种方式,记录下来完了可以来翻阅,哈哈。。。。 总的来说,添加任务都是通过OSAL.C》》uint8 osal_set_event( uint8 task_id, uint16 event_flag )添加的,那么在什么地方可以触发这个呢? 一、设置计时器,当其...
  • flying510723
  • flying510723
  • 2015-01-03 20:03
  • 542

ZStack OSAL的事件(event)与消息(message)——part1 & part2

ZStack OSAL的事件(event)与消息(message)——part1 本文转载自:http://blog.csdn.net/ceci_zhou/article/details/9787349 在zstack中,有两种方式在OSAL的任务(task)中添加自定义的功能:事件(eve...
  • qinpengtaiyuan
  • qinpengtaiyuan
  • 2014-03-11 09:02
  • 2062

TI蓝牙BLE 协议栈代码学习——OSAL(下)

接下来我们再看main()函数中另一个跟OSAL相关的函数——osal_start_system(),也位于OSAL.c中。 void osal_start_system( void ) { #if !defined ( ZBIT ) && !defined ( UBIT ) ...
  • doufuxian
  • doufuxian
  • 2015-09-06 15:58
  • 989

Zigbee协议栈中OSAL的运行机理

OSAL的运行机理       事件表 函数表 使用查表法来取得事件所对应函数      taskCnt  任务总数 taskEvents 指向事件表...
  • guomutian911
  • guomutian911
  • 2015-07-09 18:12
  • 1681

Zigbee协议栈--Z-Stack的使用

文章来自于百度文库:http://wenku.baidu.com/link?url=uiESmBOQ1hHnGX-MQQnRWpr93rOo6kdF8vVG_HA1JwzCg7kPYzbQ_YLww_AMjWIQ-9K87qDP6SFj5F1e99fRd6151zNPr4aaO6xlYSHQyOC ...
  • chenbang110
  • chenbang110
  • 2016-09-27 14:49
  • 3138

TI OSAL解析

TI OSAL 解析 先看看《OSAL操作系统-实验01 OSAL初探》中对osal的main函数的解析解析: int main(void) {   /*Initialize hardware */  HAL_BOARD_INIT();   ...
  • chengdong1314
  • chengdong1314
  • 2017-04-21 08:24
  • 633

Zstack OSAL详解

1. void osal_start_system( void ) 所有应用程序,无论是自己写的最简单的测试程序还是复杂的OSAL操作系统,都必须从main( )来入口。所谓的OS操作系统,我们不妨这样想像:自己写一个最简单的main( ),里面就一句打印“Hello, Wor
  • xiaolei05
  • xiaolei05
  • 2011-10-03 22:02
  • 912
    个人资料
    • 访问:83124次
    • 积分:1303
    • 等级:
    • 排名:千里之外
    • 原创:51篇
    • 转载:1篇
    • 译文:1篇
    • 评论:16条
    文章分类
    最新评论