OSAL调度机制

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
网络层中,事件处理函数 nwk_event_loop(),用来处理与网络层相关的各种事件。函数声明为
extern void nwk_event_loop(byte task_id, uint16 event_flag);
//event_flag 标志需要在网络层处理的事件
//-------------------------------------------------------------------------------------
} (2)设置事件发生标志 当协议栈中有任何事件发生时,我们可以通过设置 osalTaskRec_t 结构中的 events 来标记有事件发生,以便主循环函数能够及时加以处理。函数声明如下: extern byte osal_set_event(byte task_id,uint16 event_flag);
(二)时间管理 协议栈中的每层都会有很多不同的事件发生,这些事件发生的时间顺序各不相同。很多时候,事件并不要求立即得到处 理,而是经过一定的时间后再进行处理。OSAL 调度程序设计了与时间管理相关的函数,用来各种不同的要被处理的事 件。 对事件进行时间管理,OSAL 也采用了链表的方式进行,有时发生一个要被处理的事件,就启动一个逻辑上的定时器, 并将此定时器添加到链表当中。利用硬件定时器作为时间操作的基本单元。设置时间操作的最小精度为 1ms,每 1ms 硬 件定时器便产生一个时间中断,在时间中断处理程序中去更新定时器链表。每次更新,就将链表中的每一项时间计数减 1,如果发现定时器链表中有某一表项时间计数已减到 0,则将这个定时器从链表中删除,并设置相应的事件标志。这 样任务调度程序便可以根据事件标志进行相应的事件处理。具体参见关于“系统时钟”的记录。 时间管理函数: extern byte osal_start_timer(byte task_id, uint16 event_id, uint16 timeout_value); 这个函数为事件 event_id 设置超时等待时间 timeout_value。一旦等待结束,便为 task_id 所对应的任务设置相应的 事件发生标记,再对事件进行相应处理。 (三)原语通信 (原语只是一个理论层面上的术语,描述了服务层次的关系,以及两个通信的 N 用户和它们相连的 N 层(子层)对待协 议实体之间的关系。初学时总是想不通原语跟协议栈的代码有什么关系,后来才了解了原语只是规范里面的一个术语, 反映到协议栈代码里就是一个个具体的函数了!例如我们可以看到很多原语是以 request,confirm 等为后缀的,到了程 序里面就是相应的 request 请求函数,confirm 确认函数了。) 对请求(request)、响应(response)原语可以直接使用函数调用来实现 对确认(confirm)、指示(indication)原语则需采用间接处理机制来完成 一个原语的操作往往需要逐层调用下层函数并根据下层返回的结果来进行进一步的操作。在这种情况下,一个原主的操 作从发起到完成需要很长时间。因此,如果让程序一直等待下层返回的结果再进一步处理,会使微处理器大部分时间处 于循环等待之中,无法及时处理其它请求。 因此,与请求、响应原语操作相对应的函数,一旦调用了下层相关函数后,就立即返回。下层处理函数在操作结束后, 将结果以消息的形式发送到上层并产生一个系统事件,调度程序发现这个事件后就会调用相应的事件处理函数对它进行 处理。(调用就返回,而不管函数有没有处理完成。当函数处理完成后将结果以消息的形式发送到上层产生一个系统事 件)。 OSAL 调度程序用两个相关的函数来完成这个过程: 1、向目标任务发送消息的函数 这个函数主要用来将原语操作结果以消息的形式往上层任务发送,并产生一个系统事件来通知调度程序。函数声明如下: extern byte osal_msg_send(byte destination_task,byte *msg_ptr,byte len); 参数 destination_task 是目标任务的任务号,参数指针 msg_ptr 指向要被发送的消息,参数 len 为消息长度 2、消息提取函数 这个消息用来从内存空间中提取相应的消息。其中消息结构和函数声明如下: typedef struct { byte task_id; byte dst_task_id; byte send_len;
extern void nwkInit(byte task_id);
//task_id 表示为网络层任务分配的唯一任务号
//------------------------------------------------------------------------------------对于 pfnEventProcessor 是指向协议栈相关层的事件处理函数指针。比如:
链表中的每一项数据结构声明:
typedef void (*pTaskInitFn)(unsigned char task_id) ; //指向任务初始化函数 typedef void (*pTaskEventHandlerFn)(usigned char task_id unsigned short event_flag); //指向事件处理函数
摘要:
1、任务调度:osal 采用一个链表结构来管理协议栈各层相应任务。相关操作函数有,添加任务到链表中;获取下一个 活动任务;根据 taskID 查找下一个任务。osal 采用轮询任务调度队列(任务链表),通过两个函数:调度程序主循环 函数和设置事件发生标志函数。
2、时间管理:通过为事件设置超时等待时间,一旦等待时间结束,便为对应任务设置事件发生标志,从而达到对事件 进行延时处理目的。
//-------------------------------------------------------------------------------------
对于 pfnInit,是指向相关层Fra Baidu bibliotek务初始化函数的指针,比如:
网络层中,任务初始化函数为 nwkInit(),用来对网络层相关数据进行初始化操作。函数声明为
因此 Chipcon 公司为自己设计的 ZStack 协议栈中提供了一个名为操作系统抽象层 OSAL 的协议栈调度程序。
//-------------------------------------------------------------------------------------
二、下面分析下这个协议栈调度程序(OSAL)的调度机制。
目前 TinyOS 操作系统支持的平台有 ATMEL 公司的 AVR 系列、TI 公司的 MSP430 系列。由于 TinyOS 操作系统还没有对 Chipcon 公司(才知道 TI 把它收购了 )提供 CC2430 开发平台提供支持,因此,要在 CC2430 开发平台上使用 TinyOS
系统来开发 Zigbee 协议栈软件,就必须首先对 TinyOS 进行移植。灰常麻烦 ……
Extern osalTaskAdd(pTaskInitFn pfnInit,pTaskEventHandleFn pfnEventProcessor,byte task Priorty); (2)获取下一个活动任务 这个函数将根据 osalTaskRec_t 结构中的 events 标记来获取任务队列中下一个要 执行的任务。函数声明: Extern osalTaskRec_t *osalNextActiveTask(void) ; (3)根据 taskID 查找任务 这个函数将根据任务列表在建立过程中为协议栈中每个任务分配的任务号,来 查找对应任务。函数声明: Extern osalTaskRec_t *osalFindTask(byte taskID); 当任务链表建立成功后,系统便开始运行。如果在系统运行的过程中有事件发 生,系统就会通过调用相应的任务,即事件处理函数,对所发生的事件进行相 应处理。在整个运行过程中,调度程序(OSAL)始终不停地轮询任务队列链表, 以发现需要处理的事件。这个过程涉及两个函数操作: 1、调度程序主循环函数 2、设置事件发生标志函数 (1)系统主循环 这个函数始终不停地轮询队列链表,来处理系统发生的各种事件。函数声明和 部分实现如下: extern void osal_start_system(void); //无限循环 for(; ; ) { activeTask=osalNextActiveTask(); if(activeTask) { StoreDisableInts; events=activeTask—>events; activeTask—>events=0; if(events!=0) { (activeTask—>pfnEventProcessor)(activeTask—>taskID,events); RestoreInts; } }
上面记录的是链表中的每一项数据结构,与任务链表有关的主要操作有:添加 任务到列表中;获取下一个活动任务;根据 taskID 值查找相应的任务。
(1)在任务管理列表中添加任务
这个函数遍历整个任务队列链表,并按照优先级的高低将优先级高的任务插入 到优先级低的任务前面;否则,就将任务插入到链表的尾部。在这个过程中, 将为每个任务分配一个唯一的任务号。函数声明为:
三部分:1、任务调度
2、时间管理
3、原语通信
(一)任务调度
//每层任务=对应事件处理函数
//任务链表,任务按优先级插入 ZigBee 协议栈中的每一层都有很多原语操作要执行,因此对于整个协议栈来说,就会有很多并发操作要执行。协议栈 的每一层都设计了一个事件处理函数,用来处理与这一层操作相关的各种事件。这些事件处理函数可以看成是与协议栈 每一层相对应的任务,由 ZigBee 协议栈中调度程序 OSAL 来进行管理。这样,对于协议栈来说,无论何时发生了何种事 件,我们都可以通过调度协议栈相应层的任务,即事件处理函数来进行处理。这样,整个协议栈便会按照时间顺序有条
3、原语通信:请求响应原语操作:一旦调用了下层相关函数后,就立即返回。下层处理函数在操作结束后,将结果以 消息的形式发送到上层并产生一个系统事件,调度程序发现这个事件后就会调用相应的事件处理函数对它进行处理。两 个相关函数:向目标任务发送消息的函数;消息提取函数。
一、操作系统介绍 现有的嵌入式操作系统可以分为两类,即通用的多任务操作系统(General—purpose Multi-tasking OS)和事件驱动的 操作系统(Event-driven OS)。前者能够很好地支持多任务或者多线程,但是会随着内部任务切换频率的增加而产生很 大的开销,这类操作系统有:uC/OS-II、嵌入式 Linux、WinCE 等。后者支持数据流的高效并发,并且考虑了系统的低 功耗要求,在功耗、运行开销等方面具有优势。典型的代表如 TinyOSl291。
typedef struct osalTaskRec { struct osalTaskRec *next; //指向链表中下一个结构体 pTaskInitFn pfnInit; //指向相关层任务初始化函数 pTaskEventHandlerFn pfnEventProcessor; //指向相关层事件处理函数 byte taskID; //对应当前任务 ID byte taskPriority; //当前任务优先级 uint16 events; //需要被处理的事件,0 表示没有要被处理事件 } osalTaskRec_t; //链表中的每一项数据结构
不紊的运行。 ZigBee 协议栈的实时性要求并不高,因此在设计任务调度程序时,OSAL 只采用了轮询任务调度队列的方法来进行任务 调度管理。
OSAL 采用一个链表结构来管理协议栈各层相应的任务。链表中的每一项是一个结构体,用来记录链表中相关任务的基 本信息。链表的建立是按照任务优先级从高到低的顺序进行插入的。优先级高的任务将被插入到优先级低的任务前面。 如果俩任务优先级相同,则按照时间顺序加入到链表中。那么这个任务链表在系统启动的时候建立,一旦建立后便一直 存在于事个系统运行的过程中,直到系统关闭或硬件复位才被销毁。
相关文档
最新文档