uC/OSⅡ四篇

2024-08-27

uC/OSⅡ 篇1

uC/OS-II是JEAN J.LABROSSE编写的一个源码公开、可移植、可固化、可裁剪、抢占式的嵌入式实时操作系统。uC/OS-II能管理64个任务, 并提供任务调度与管理、内存管理、任务间同步与通信、时间管理和中断服务等功能, 具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点。但是与其他嵌入式内核相比, uC/OS-II没有设备管理功能。虽然JEAN J.LABROSSE针对嵌入式系统常见设备驱动另外编写了一本著作Embedded Systems Building Blocks (《嵌入式系统构件》) , 但还是没有为uC/OS-II构造一个完整的设备驱动体系。

在使用uC/OS-II进行驱动开发时, 由于没有规范的API函数, 驱动程序的可移植性和可读性明显下降, 这影响了uC/OS-II的推广和应用, 所以规划一个简单、稳定、规范的设备驱动体系结构非常必要。文献[3]中已经针对uC/OS-II设计了一个通用的驱动框架, 实现对系统设备的有效管理。但在该驱动框架下, 设备驱动程序和uC/OS-II内核是分别独立的, 在小型应用系统中, 程序太大, 不易于裁剪。本文根据uC/OS-II自身的结构特点, 设计了一个设备驱动框架, 将设备驱动程序设计为内核模块。这样在实际应用中, 通过对操作系统配置文件进行设置, 就能得到一个既满足需要, 又非常紧凑的应用软件系统。

(二) 设备驱动概述

设备管理即输入输出子系统, 可分为上下两部分:一部分是上层的, 与设备无关, 这部分根据输入输出请求, 通过特定的设备驱动程序接口来与设备进行通信。另一部分是下层的, 与设备有关, 常称为设备驱动程序, 它直接与相应设备打交道, 并且向上层提供一组访问接口。

设备管理的目标是对所有外接设备进行良好的读、写、控制等操作。由于用户希望能用同样的应用程序和命令来访问设备和普通文件。为此, LINUX中的设备管理应用了设备文件这个概念来统一设备的访问接口, 对设备进行操作的系统调用和对文件的类似, 主要包括open () 、read () 、write () 、ioctl () 、close () 等。

嵌入式系统将设备分成3类:字符设备、块设备及网络设备。其中字符设备和块设备与虚拟文件系统 (VFS) 相关, 并为操作系统提供了统一的操作接口。字符设备和块设备的主要区别是前者在读写设备时不需要缓冲区, 而后者需要。内核与网络设备驱动间的通信完全不同于与字符设备以及块设备驱动程序之间的通信, 而是采用了一套和数据报传输相关的函数, 如BSD的套接字 (socket) 接口。

(三) u C/OS-II的设备驱动框架

在《嵌入式系统构件》中, JEAN J.LABROSSE根据嵌入式系统的硬件结构框图, 将和设备操作相关的软件模块封装为不同的“任务”, 例如“键盘任务”、“显示任务”、“通信任务”等, 然后通过信号量来实现任务之间的“行为同步”。考虑到uC/OS-II的结构特点, 为了增强内核的灵活性和为了方便, 本文设计了设备驱动框架模型, 如图1所示:

在这个设备驱动框架中, API层只为应用程序提供了3个API函数:DeviceOpen () 、DeviceClose () 、CreateDevice () ;而逻辑块层实现了对核心数据结构和通用设备的操作函数的封装。下面是核心数据结构和相关函数:

1.借鉴uC/OS-II中的管理事件控制块方法, 定义一个设备控制块的数据结构。设备控制块的定义如下:

在uC/OS-II初始化时, 在初始化函数OSInit () 中按应用程序使用设备总数OS_MAX_DEVICE, 创建OS_MAX_DEVICE个设备控制块, 并借用成员OSDevPtr作为链接指针, 把这些空设备控制块链成一个单向链表。

2.设备的操作句柄函数列表包括:设备安装、读出、写入;写入和读出其实质是写和读各个设备的缓冲区;而控制应包括设备参数的设置、起动和停止三部分。设备打开和关闭主要解决设备的共享和分配。

3.设备打开的过程是从有效的设备控制块链表中找到指定ID的设备控制块, 审请信号理, 如果审请通过则返回该设备的操作句柄。

该函数以任务独占方式打开一个设备文件, 当一个设备被占用时其它任务只有等待, 直到占有设备的任务调用关闭设备文件函数释放该设备。

(四) 设备驱动程序开发流程

1.对设备进行初始化。初始化的目的是使设备处于某种工作状态。以便应用程序访问该设备。串口初始化包括设置串口波特率、数据位、奇偶校验位、停止位等。以及把相关的驱动程序 (读/写、中断服务函数等) , 注册到设备控制列表中, 以便系统对其管理及使用。

2.从设备上接收数据并提交给系统。这项功能通常就是所说的读操作, 接收部传输来的数据。

3.把数据从主机上发送给设备。这项功能对应通常的写操作, 把主机上的数据传送给外界。

4.对设备进行控制操作。在使用设备过程中, 有时根据应用的需要对设备进行控制。例如, 在使用串口过程中, 有时需要改变串口波特率的设置。

4.编写设备驱动程序的注册函数。这个函数的功能主要是创建设备, 从空闲设备控制块列表中取得一个控制块, 同时调用操作系统的创建互斥信号量函数初始化device_sem。初始化设备操作函数列表指针, 最后将该控制块链接到有效设备控制块链表中。

5.编写设备驱动程序的卸载函数。当系统不需要使用某设备时, 为了节省资源开销, 需要把当初分配给被卸载设备的设备控制块从设备控制块链表中删除, 并归还给空设备控制块链表。

(五) 结束语

uC/OS-II仅是一个实时内核, 它只提供了任务管理、任务的通信同步和简单的存储管理三项基本服务, 因此在实际应用中需要对uC/OS-II进行功能扩展。本文为uC/OS-II设计的设备驱动框架, 在为上层应用程序提供了良好的设备访问接口的基础上, 充分利用uC/OS-II已有的功能。同时, 该设备驱动框架没有破坏uC/OS-II易于移植、裁剪的特点, 极大地方便了用户开发设备驱动程序。

摘要:针对uC/OS-Ⅱ没有提供一个完整的设备驱动框架, 文章根据uC/OS-Ⅱ自身的结构特点, 借鉴其中任务间通信手段, 设计了一个设备驱动框架, 通过该驱动框架为设备建立驱动程序并规范相应的API函数。最后探讨了uC/OS-Ⅱ下设备驱动程序具体开发流程。

关键词:嵌入式实时操作系统,uC/OS-Ⅱ,设备驱动,API函数

参考文献

[1]JEAN J.LABROSSE.嵌入式实时操作系统uC/OS-II (第二版) [M].邵贝贝, 译.北京:北京航空航天大学出版社.2003.

[2]JEAN J.LABROSSE.嵌入式系统构件[M].袁勤勇, 等译.北京:机械工业出版社, 2002.

[3]吴绍根.uC/OS-II下通用驱动框架的设计与实现[J].微计算机信息, 2006.

[4]Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman.Linux设备驱动程序 (第三版) [M].魏永明, 等译.北京:中国电力出版社, 2006.

uC/OSⅡ 篇2

uC/OS-II是一个实时内核, 主要提供任务管理功能。它是由林uC/OS升级而来的, 并且做了很大的改进。uC/OS-II的使用对象是嵌入式系统, 并且很容易移植到不同构架的微处理器上。

二、移植目标微处理器

一般来说, 选用处理器的时候要考虑性能、开发难易程度、开发成本、相关资料公开性等因素。很多微处理器体系结构各有特点, 以适应应用在不同领域。S3C2410是Samsung公司设计的一款低功耗高性能的、基于ARM920T的、精简指令系统的32位高速处理器, 主要适用于手持设备和普通应用。从研究可行性出发, 本设计采用了ARM体系结构的ARM920T内核。

三、uC/OS-II在ARM上的移植

绝大部分uC/OS-II的源代码使用移植性很强的ANSI C写的, 这样写的原因就是为了便于uC/OS-II移植到不同的微处理器上。所谓移植, 是指使一个实时操作系统能够在某个微处理器平台上运行。

1. 移植条件

虽然uC/OS-II的大部分源代码都是用C语言写的, 但是仍需要用C语言和汇编语言完成一些与处理器相关的代码。例如, uC/OS-II在读写处理器、寄存器时只能通过汇编语言实现。不过因为u C/OS-II在设计时就已经充分考虑了可移植性, 所以uC/OS-II的移植相对还是比较容易的。

要使uC/OS-II可以正常工作, 处理器必须满足如下要求:

(1) 处理器的C编译器能产生可重入代码。

可重入代码指的是一段代码 (如一个函数) 可以被多个任务同时调用, 而不必担心会破坏数据。也就是说, 可重入型函数在任何时候都可以被中断执行, 过一段时间以后又可以继续运行, 而不会因为在函数中断的时候被其他的任务重新调用, 影响函数中的数据。

(2) 重可以打开或者关闭中断

在u C/OS-II中定义了两个宏 (macro) 来关闭或者打开中断, 以避开不同c编译器厂商选择不同的方法来处理关中断和开中断。这两个宏分别是:OS_ENTER_CRITICAL () 和OS_EXIT_CRITICAL () 。在ARM920T核的处理器上, 可以通过设置相应的寄存器来关闭和打开系统所有的中断。

(3) 处理器支持中断, 并且能产生定时中断 (通常在10—1OOOHz之间) uC/OS-II需要通过处理器产生的定时器中断来实现多任务之间的调度在ARM920T处理器上可以产生定时中断。

(4) 处理器支持能够容纳一定量数据的硬件堆栈

(5) 处理器有将堆栈指针和其它CPU寄存器读出和存储到堆栈或内存中的指令。uC/OS-II进行任务调度的时候, 会把当前任务的CPU寄存器存放到此任务的堆栈中, 然后再从另一个任务的堆栈中恢复原来的工作寄存器, 继续运行另一个任务。所以, 寄存器的入栈和出栈是uC/OS-II多任务调度的基础。

ARM920T处理器完全满足上述要求, 所以u C/OS-II完全可以移植到Samsung公司的ARM920T的嵌入式微处理器S3C2410上。

2. uC/OS-II在S3c2410上的移植

由于设计uC/OS-II时就考虑到了在不同处理器上移植, 因而移植u C/OS-II实际上需要修改的代码量很小。整个嵌入式系统的结构如图1, 其中需要修改的部分只是与处理器相关部分的文件。

(1) 修改OS_CPU.H

OS_CPU.H中包含两部分的代码, 数据类型定义代码和与处理器相关的代码。其中数据类型重定义代码是由于C语言中short、int、long等, 数据类型是与特定的处理器相关的, 因此在uC/OS-II重新定义为移植性很强的定义方式。举例如下, 定义布尔变量的格式和8位无符号整型变量的格式分别如下:

typedef unsigned char BOOLEAN;布尔变量

typedef unsigned char INT8U;无符号8位整型变量

在OS_CPU.H剩下的部分是移植必须定义底层函数的声明。在S3C2410的移植中为了使底层接口函数与处理器的状态无关, 同时使任务调用相应的函数不需要知道函数的位置。在本移植中使用软中断指令SWI作为底层接口, 使用不同的功能号来区分各函数。调用这些底层函数, 只需要使用一条SWI指令并跟上一个功能号来区别你要调用那个函数就可以了。

(2) 修改OS_CPU_C.C

OS_CPU_C.C中主要是软中断的实现和底层函数的实现及初始化任务堆栈函数的实现, 其代码如下:

任务堆栈初始化函数

OS_STK*OSTaskStkInit (void (*task) (void*pd) , void*pdata, OS_STK*ptos, INT16U opt) 定义任务堆栈;

使用满栈递减方式初始化任务堆栈结构;

返回堆栈结构;

软中断实现void SWI_Exception (int SWI_Num, int*Regs)

根据不同的Num值跳转到不同的底层服务函数函数地址

如:case 0x00:任务切换函数OS_TASK_SW

其它函数具体的定义参考文献

参考文献

[1]Jean J1Labrosse1邵贝贝等, 译1嵌入式实时操作系统uC/OS-II (第2版) [M]1北京:北京航天航空大学出版社, 20031.

[2]周立功, 等1ARM微控制器基础与实战[M]1北京:北京航天航空大学出版社, 20031.

uC/OSⅡ 篇3

摘要:讲述嵌入式操作系统μC/OS-II在电力监控仪表中的应用;通过实时多任务系统对所有任务的调度管理,解决在单任务系统中难以处理的实时性差的问题,同时增强系统工作的可靠性;较详细地给出系统软件的整体设计思路,以及软件中各任务的具体运行过程。

关键词:嵌入式系统 内核 任务 消息阵列

引言

随着各种电子系统在各领域中应用的不断深入,对电子系统本身的各方面性能提出了越来越高的要求,使应用软件朝着系统化方向加速发展。传统的嵌入式系统设计中,大多采用单任务的顺序机制。应用程序是一个无限的大循环,所有的事件都得按顺序执行,与时间相关性较强的事件靠定时中断来保证。这种方式编程的优势在于程序较为直观,但由此带来一个重要的问题,那就是系统的稳定性、实时性较差。尤其当系统功能较复杂,同时对实时性要求较严格时,这种单任务机制的弱点使暴露无遗。

在配电监测终端软件的设计中,笔者将买时操作系统μC/OS-II用于TMS320F206的程序设计;将系统所要的功能细化成为几个核心任务,由μC/OS-II实时内核进行调度,实现了多任务的并行执行,系统的可靠性和实时性得到大幅提升。ΜC/OS-II是免费的、源代码公开的、微内核嵌入式实时操作系统,其实时性能和内核的健壮性早已经在大量的实际应用中得到了证实。

1 系统概述

在电力系统中,对电子设备的要求是比较高的。配电监测终端是监测电网运行状况的一种重要设备,主要完成以下功能:对电压、电流信号进行采样,A/D转换;对所采集到的数据进行计算分析,得出各种监测指标参数;对所有指标参数进行统计分析,处理液晶显示和键盘扫描,响应按键命令,进行数据通信处理。在对电压、电流模拟通道信号的采样和A/D转换过程中,为保证严格的等时间间隔,将这部分事件处理放到实时器中断中进行。数字信号分析处理作为一个程序模块,完成数据的分析运行。键盘扫描和液晶显示处理部分程序,作为人机交换信息最直接的通道。它的设计是否合理,直接影响到用户使用的满意程序。在单任务系统中,程序循环的周期不确定,因此键盘扫描周期无法确定。当程序运算量较大时,容易造成明显的键盘响应迟钝。键盘扫描周期很大程序上受到主程序循环时序的影响,而且,当主程序中某个程序模块出现问题时,将出现程序卡住,直到看门狗复位为止。

(本网网收集整理)

在多任务系统中,这些问题可以得到很好的解决。利用嵌入式实时操作系统内核对所有“任务”进行统一调度和管理,使CPU的使用权在建立的“任务”间切换;同时,在多任务机制下,使应用程序模块化,使开发任务层次化。

整个系统的设计可以分为三个层次:最底层为硬件平台是,包含微处理器系统及相关应用电路,第二层为任务层,包含电路驱动程序和应用程序;最高一层为μC/OS-II操作系统层,是整个系统的管理核心,如图1所示。

2 硬件描述

配电监测终端的设计采用定点DSP TMS320F206作为处理器。它是采用先进的改进型哈佛结构、多级流水高速设计,具有极其强大的数据处理能力和管理能力。该终端从功能上可分为数据采集部分,液晶显示及键盘阵列部分,数据存储、通信部分及微处理器小系统部分。数据采集部分用来对电压、电流信号进行采样和A/D转换;液晶显示和键盘阵列为人机信息交换硬件接口;数据存储部分存储大量历史统计数据,采用掉电保护设计,在系统掉电情况下数据不会丢失。

3 系统软件设计

按系统所要求实现的功能,将整个系统划分为几个并行存在的任务层。占先式操作系统对任务的调度是按优先权的高低进行的,将系统的几个任务按其优先级从高到低顺序排列依次是:系统监视任务、键盘扫描和液晶显示任务、通信任务、数据运算统计处理任务。数据采集部分放到定时器中断程序中执行。其中,系统监视任务是用来监视除系统监视任务外其它任务的。当被监视任务在执行过程中出现差错时,系统监视任务将按照预先设定的处理表对其进行处理,使出现差错的任务恢复正常运行,提高系统运行的可靠性。优先权的设置是按照整个系统运行的时序来确定的,对系统安全运行较重要和对实时性要求较严格的任务,设成较高的优先级。一般而言,在系统运行过程中,各任务的`优先级是固定不变的。

μC/OS-II控制下的任务可以分为休眠态、就绪态、运行态、中断态和挂起态。在嵌入式系统中,为节省存储器空间不会保留休眠态的任务。当某个任务正在占用CPU的使用权时,该任务处于运行态。处于运行态任务的优先权一定高于其它所有就绪态任务的优先权。当系统运行致使某一就绪态任务优先权高于运行态任务的优先权时,调用调度函数,运行态任务将转入挂起态等待某一消息或信号量,或者转入就绪态;而那个拥有较高优先权的任务将占有CPU的使用权而转为运行态。某一时刻只有个任务占有CPU的使用权,也就是说,某一时刻只有一个任务处于运行状态。挂起态的任务在所规定的时间内,如果得到所期待的数据(可能是消息阵列,也可能是信号量),就自动转为就绪态;如果等待超时,就被时间管理函数强制转化为就绪态,等待任务调度。中断发生时,系

统将强行剥夺运行态任务对CPU的使用权,将它转入中断态,保存相关数据到堆栈区之后,执行中断服务程序。在中断返回时,系统返回函数将重新进行任务调度,将优先权最高的就绪态任务转为运行态。

在实际系统中,每个任务都是一个无限循环的,分别实现某一特定的功能,由μC/OS-II内核来进行调度。电力行业中对设备可靠性的要求是很高的。对于监测设备,由于在启外运行,所受的电力谐波干扰相当大,有时会引起程序跑飞、死机现象,直到看门狗复位可使系统恢复正常;但在看门狗复位这段时间内,设备对电流、电压的采样不能正常进行,相关采样数据就会丢失,直接影响到电能量计算的准确度,同时会影响到数据通信。笔者利用软件狗的原理设计了一个系统监视任务,用来对其它任务进行监视。在系统运行中,当发现某一个任务运行出现异常时,该任务将按相关步骤做出相应处理。具体做法是:系统监视任务在正常运行情况下处于挂起状态,在某一时间范围内,等待每个被监视任务向它发送代表该被监视任务正常运行的消息。每个被监视的任务在运行状态下向系统监视任务发送这一消息,用以说明本任务运转正常。系统监视任务等待这一消息的时间范围按每个任务执行所需时间的最大值设定。系统监视任务在等待时间范围内收到消息,说明被监视任务运转正常,否则,系统内核自动将系统监视任务由挂起态转为就绪态。由于系统监视任务优先权最高,所它将取得CPU使用权,系统监视任务将出错任务的运行任务堆栈改为该任务的起始地址,并将其置为就绪态,挂起自身。如此,刚才出错的任务以重新开始执行,避免看门狗复位。

系统运行时,首先进行系统初始化操作,初始化所有数据结构,分别堆栈空间,然后建立任务间通信的信号量或者消息队列,进行任务建立,并且分配任务优先权。所有新建任务被置为就绪态,系统程序从优先权最高的任务开始执行。

该配电监测终端软件中,系统监视任务优先权最高,最先进入运行态。该任务分别查询每一个被监视的任务是否向其发送消息。如果没有,则该任务进入挂起态。按优先权级别顺序,键盘扫描和液晶显示任务将由就绪态转为运行态。在该任务将要执行完毕时,向系统监视任务发送消息,然后执行延时函数将自身转为挂起态,交出CPU使用权让其它任务得以执行。此时系统监视任务得到消息转为运行态,继续查询其它被监视任务的运行消息。如果没有,则进入挂起态,再次等待其它被监视任务的运行消息,系统按任务优先级继续执行优先级高的就绪态任务等等,依此类推。当键盘扫描和液晶显示任务延时时间到时,系统内核自动将它再次转为就绪态。一般键盘扫描和液晶显示任务延时时间按人手触摸按键反应时间而定,大约在100ms。在正常情况下,由于系统监视任务只是查询消息量,程序执行时间很短,甚至可以忽略,同时键盘扫描和液晶显示任务优先权排在第二。所以,只要键盘扫描和液晶显示任务进入就绪态就可以得到及时响应,能够很好地满足键盘扫描和液晶显示的实时性,解决在单任务环境下很难解决的键盘查询处理的实时性问题;同时,数据分析处理任务和通信任务可以在键盘扫描和液晶显示任务延时时间间隔内执行。由于TMS320F206处理器速度足够快,所有任务得以在满足时序的前提下顺利执行。

当系统响应定时中断时,中断程序将占据CPU的使用权进行电流和电压采样,设置下一次中断时间。在退出中断时,内核将重新进行任务调度。

结语

uC/OSⅡ 篇4

uC/OS-III的非必须功能均具有可裁剪性,用户需在OS_CFG.H文件中设置OS_CFG_TASK_Q_EN为1,任务内建消息队列才会被分配到任务控制块中,否则任务内建消息队列部分就会被裁剪而失效。

1 uC/OS-III消息队列的结构

1.1 外建消息队列

外建消息队列主要由五个部分组成:

1)结构体标识部分:存放消息队列的标识数据,是操作系统识别此结构体为消息队列的依据。

2)消息队列命名部分:存放该消息队列的名字,可直接访问该地址并查看该队列名字相对应的ASCII码或者通过uC/Probe查看其相对应的字符串。该命名功能主要应用于产品设计时的调试,区分各个消息队列。

3)消息挂起部分:该部分由指针HeadPtr、TailPtr和计数变量NbrEntries组成,指针指向的是内建于任务控制块的os_pend_data结构体,多个结构体与上述两个指针一起构成了消息挂起队列,等待该消息的任务都以链的形式存放在该队列中。

当任务被添加进挂起队列中,uC/OS-III会根据该任务的优先级、相等优先级时依据添加顺序进行重新排列,以保证当消息到来时最先获得消息的是队列中优先级最高的任务。计数变量记录了当前该挂起队列中所存放的任务个数。

4)功能调试部分:当配置宏OS_CFG_DBG_EN为1时,便使能了uC/OS-III提供的专用于调试的代码,其作用是将所有的内建和外建消息队列按照创建时的顺序以队列的形式展现给用户,方便用户调试时查看所有消息队列及其数据。

5)消息存储部分:该部分由指针InPtr、OutPtr和计数变量NbrEntriesSize、NbrEntries、NbrEntriesMax组成。指针InPtr、OutPtr指向的是os_msg消息结构体,多个该类型结构体与上述两指针一起构成了消息存储队列,该队列为环形队列,环的大小为NbrEntriesSize所设置的数值。

当消息挂起队列中无任务被挂起时,被提交的消息会存储在消息存储队列中直到该队列所允许的上限后,被提交的消息将不能再存储进该消息存储队列中,此时,欲提交该消息的函数会返回相应的错误代号以告知用户该消息队列存储消息已满,该消息将溢出。

变量NbrEntriesSize记录了该队列存放消息的上限个数,变量NbrEntries记录了该队列当前时刻存放的消息数,变量NbrEntriesSizeMax记录了到当前时刻为止该队列存放消息数的峰值。

1.2 任务内建消息队列

内建的消息队列仅包括上述的消息存储部分。

在uC/OS-II中,消息队列均为外建消息队列,可实现任务间的互相通信,中断服务程序ISR对消息队列的通信(注意这是单向的,ISR不能被挂起等待消息,否则会因为调度的混乱而导致系统崩溃)。

考虑到某些应用中一种消息只为一个任务服务等简单的通信操作时,没必要再为这个任务创建单独的一个外建消息队列,因而在uC/OS-III中新添了任务内建消息队列的功能。内建的消息队列仅包括上述的消息存储部分,不仅降低的存储空间的要求,同时也使消息能直接传递给任务而无需通过外建消息队列等媒介,提高了实时系统的效率。

2 消息队列接口函数

2.1 外建消息队列的接口函数

uC/OS-III为外建消息队列提供了6个接口函数,如图3所示,任务可以通过接口函数往消息队列中发送消息、接收消息。但中断服务程序却只能往消息队列中发送数据,这是因为若中断服务程序等待消息的到来,那么此中断嵌套将一直被挂起,CPU不能够绕过此中断嵌套以恢复该中断前的状态,从而导致系统的崩溃。

OSQCreate():用于创建外建消息队列,调用该函数前必须定义一个消息队列的结构体,并将该结构体的地址作为参数传递给该函数,该函数的参数同时也定义了消息队列所能存放的消息数。

OSQDel():用于删除不再使用的消息队列,使用该函数时需非常谨慎,最好是先删除与该消息队列相关的所有任务,或者事先解除那些任务与该消息队列间的联系,不然会导致这些任务的失效。如果失效的任务是系统或应用中的关键任务,后果将不堪设想,因此,使用该函数时应当非常慎重。

OSQFlush():清空该消息队列中的所有消息,该功能主要用于批量的消息更替,比如ISR从串口接收到一系列的新数据需更替掉原先的旧数据时,该函数相当有效。

OSQPend():任务调用该函数后将被挂起,有两种挂起方式,OS_OPT_PEND_BLOCKING方式:消息队列中没有消息时,任务等待直到消息队列中有消息分配给它或者所设定的等待期限满而该函数返回个错误代号。OS_OPT_PEND_NON_BLOCKING方式:消息队列中没有消息时,任务不进行等待,该函数直接返回个错误代号。

该函数的其中一个重要参数是设置任务等待消息的时间期限,若超过这个时间期限任务也未能接收到其所等待的消息时,函数便返回一个相应的错误代号。当该参数设置为0时,表示该任务永久地等待消息的到来。

OSQPendAbort():使该消息队列中的等待任务取消挂起,有两种取消方式,OS_OPT_PEND_ABORT_1:使该消息队列中优先级最高的一个任务取消挂起,OS_OPT_PEND_ABORT_ALL:该消息队列中的所有任务均取消挂起。取消任务挂起后,uC/OS-III会自动执行调度。若应用中不需其在取消任务后实现调度,可在上述两种方式后或操作宏OS_OPT_POST_NO_SCHED。

OSQPost():提交消息到对应的消息队列,消息的提交方式有三种,OS_OPT_POST_FIFO:先进先出方式,OS_OPT_POST_LIFO:后进先出方式,OS_OPT_POST_ALL:该消息将传递给所有在消息队列中挂起的任务。同样,或操作宏OS_OPT_POST_NO_SCHED可避免调度。

该函数的另外两个关键参数是所要被传输消息数据的首地址及其数据的大小,数据的大小以字节为单位。

在此需说明的技巧是:当同时提交多个消息时,可先失能提交后的调度,待到最后一个消息被提交时,再使能调度。从而避免了需提交几个消息就得执行几次调度的尴尬局面,提高了系统的实时性。

2.2 任务内建消息队列的接口函数

在uC/OS-III中,任务内建消息队列共有3个接口函数,该3个函数几乎是外建消息队列接口函数的精简版。

OSTaskQPend():任务调用该函数后被挂起,不同于外建消息队列的是,任务被挂起的信息不是存放在消息队列中,而是直接由uC/OS-III内核直接管理。

OSTaskQPendAbort():调用该函数后任务被取消挂起,由于目标任务为调用该函数的任务本身,取消方式仅为一种,OS_OPT_POST_NONE:取消该任务的挂起。同样,或操作宏OS_OPT_POST_NO_SCHED可避免调度。

OSTaskQPost():提交消息到任务内建消息队列,消息的提交方式有两种:OS_OPT_POST_FIFO,OS_OPT_POST_LIFO。同样,或操作宏OS_OPT_POST_NO_SCHED可避免调度。

3 结束语

消息队列为任务间提供了异步的通信协议,消息的发送者和接收者均可在适当的时候与消息进行信息的交互。作为媒介,消息队列传递的仅是数据的存放地址以及数据的大小,这使得信息的传递变得非常简单、高效。

作为对时间要求非常严格的嵌入式实时系统,u C/OS-III引入了任务内建消息机制,降低了消息队列占用的存储空间、提高消息与任务间的通信效率、实现了消息与任务的相互对应,从而进一步提高了系统的微型性、实时性和健壮性。

参考文献

[1]邵贝贝.嵌入式实时操作系统μCOS-Ⅱ[M].北京:北京航空航天大学出版社,2003:56-89

[2]王田苗.嵌入式系统设计与实例开发--基于ARM微处理器与uc/OS-II实时操作系统[M].北京:清华大学出版社,2003:103-135.

[3]任哲.嵌入式操作系统基础uc/os-II和Linux[M].北京:北京航空航天大学出版社,2006:52.

【uC/OSⅡ】推荐阅读:

uC/OS-Ⅲ05-13

模式Ⅱ06-13

Ⅱ级培训05-20

肺泡Ⅱ型06-02

全国卷Ⅱ07-02

Zn(Ⅱ)07-02

毕罗Ⅱ式07-03

Ⅱ优3008-09

《功夫熊猫Ⅱ》08-24

ERPⅡ09-15

上一篇:卧床老年病人论文下一篇:医护人员工作倦怠