引言
目前电子产品开发广泛采用以微处理器为核心的电子系统。开发以微处理器为核心的电子系统(以下简称微处理器系统)采用传统的无限循环函数模式,产品的开发周期和稳定性都无法保障,因此,在微处理器系统开发中引入嵌入式实时操作系统RTOS。RTOS的引入消耗了部分系统资源。这部分系统资源对于高档微处理器系统影响不大;对于中小规模微处理器系统,特别是单片机系统,由于RTOS资源的占用,使用户可用资源大大减少,严重影响系统的实时性,甚至系统功能无法完成。市场上虽然有一些专用于单片机的RTOS,如应用于51系列单片机RTX51 tiny,但由于功能相对薄弱,无太大实用价值;另外也有一些功能较强的RTOS可移植到单片机系统,但由于占用资源较多,需扩展大量的RAM和ROM,并且产时性差。本文介绍一种适用于小容量存储器单片机(如PIC系列)系统且功能强大的RTOS—Salvo。
1 Salvo特点
嵌入式实时操作系统Salvo有两大特点:①占用系统资源少;②功能强大。
(1)Salvo占用的系统资源
Salvo最大的特点是占用系统资源少,特别是占用存储器资源极少。它不但适用于51系列单片机,也适用于存储器资源更少的PIC系列单片机。Salvo占用ROM资源取决于用户调用的系统函数,占用RAM取决于用户定义的变量、任务和事件的数量。以PIC16系列单片机为例,每个全局变量占10B,任务点5B,事件占3B。
(2)Salvo功能和性能
Salvo是一个基于优先级任务切换,支持事件驱动的多任务嵌入式实时操作系统。Salvo共支持16个任务优先级。且多个任务可以共用一个优先级,任务按优先级高低切换,对于多个同一优先级的任务,以时间片循环方式 (round-robin)切换。Salvo支持任务和事件的数量不限,取决于RAM的大小。(Salvo默认支持255个任务、255个事件和255个消息队列)
Salvo内核主要提供以下几类函数供用户应用程序引用:
①任务管理—提供任务建立、任务撤消等功能;
②时间管理—提供任务延时函数等功能;
③信号管理—提供信号量建立、删除、等待、发出等功能;
④消息管理—提供消息建立、删除、等待、发出等功能。
2 Salvo的内核分析
(1)任务状态及状态转移
Salvo的用户任务具有以下几种状态:
①运行状态。任务占用系统资源正在运行中,任务一时刻只能有一个任务可以处于运行状态;
②就绪状态。由于任务的优先级不是最高优先级,任务正在等待运行;
③延时状态。任务先前已运行过,现在暂停运行等待延时时间到达,一旦延时时间到达,任务处于就绪状态;
④停止状态。任务先前已运行过,现在由于某种确定原因暂停运行,直到RTOS再次启动该任务;
⑤等待状态。任务暂停运行,直到它的等待事件发生。
Salvo的任务状态转移图如图1所示。
(2)任务同步和通信
为保证应用系统各任务的协调和信息传输,嵌入式操作系统需要同步和通信机制。一般采用信号量、事件标志、消息和消息队列实现任务间的同步和通信。
信号量(semaphores)分二进制信号量和计数式信号量,用于表示事件的发生或对共享资源的访问。信号量使用前应先采用OSCreateSem()函数产生,信号量接收的任务在处理中用OS_WaitSem()函数等待事件发生而挂起。一旦信号量发送,任务根据事件的发送情况用OSSignalSem()函数设置信号量,挂起的信号量接收任务继续运行。对于二进制信号量,Salvo提供OSCreateBinSem()、OS_WaitBinSem()、OSSignalBinSem()等函数用于二进制信号量的产生、等待和设置等功能。
事件标志(event flags)用于某任务与多个事件的同步。任务与多个事件的同步可以是独立同步(逻辑或关系),也可以是关联同步(逻辑与关系)。Salvo提供OSCreateEFlag()、OS_WaitEFlag、OSSignalEFlag()等函数用于事件标志的产生、等待和设置等功能。
信号量和事件标志只能用于传递事件的发生或对共享事件的访问,任务间其它信息的传递通过消息(messages)实现。消息可以传递各种信息,包括数值、字符、数组、函数、指针等。任务间传递的并非消息本身,而是指向消息的指针,消息内容的含义由发送和接收消息的任务约定。Salvo提供OSCreateMsg()、OS_WaitMsg()、OSSignalMsg()等函数用于消息的产生、等待和设置等功能。消息队列实际是消息阵列,用于任务或中断服务程序(ISR)向一个或多个任务发送消息,队列中的消息按先进选出(FIFO)原则被任务读取。Salvo提供OSCreateMsgQ()、OS_WaitMsg()、OSSignalMsgQ()等函数用于消息的产生、等待和设置等功能。
(3)任务调度和任务控制块
Salvo是基于优先级的嵌入式实时操作系统,Salvo总是运行就绪任务表中优先级最高的任务。(Salvo允许2个以上任务处于同一优先级,同一优先级任务按时间片轮转调度)Salvo由函数OSSched()实现任务调度。
在任务切换过程中,被剥夺CPU使用权的任务必须保存该任务的当前运行状态,如CPU内寄存器的值;而获得CPU使用权的任务必须恢复前一次被剥夺CPU使用权时的运行状态,继续运行。为完成这些功能,Salvo为每一个建立的任务建立一个任务控制埠(TCB)。任务控制埠是一个数据结构,当任务的CPU使用权被剥夺时,Salvo用它来保存该任务的运行状态;当任务重新获得CPU使用权时,任务控制块能确保任务从当时被中断处继续运行。
3 Salvo的配置
当了成功地编译Salvo应用程序,并使编译后的目标代码小,系统运行时占用RAM空间少,在编译Salvo应用程序时,需要对Salvo进行配置。
(1)目标代码建立方式
Salvo应用程序目标代码建立方式有两种:基于库的建立和基于源泉代码的建立。
在基于库的目标代码建立中,Salvo提供的用户函数包含在预编译的Salvo库文件中,Salvo应用程序从用户程序源代码(包括C语言和汇编语言)、Salvo库和Salvo的mem.c建立而成。由于Salvo库是预先编译的,应用程序编译时的配置文件对Salvo库,即用户函数无效。基于库的目标代码建立过程如图2所示。
在基于源代码的目标代码建立中,Salvo提供用户函数的源代码。Salvo应用程序从用户程序源代码、Salvo用户函数源代码(包括C语言和汇编语言)和Salvo的mem.c建立而成。由于Salvo用户函数是源代码形式,Salvo应用程序编译时的配置文件对Salvo的用户函数有效。基于源代码的目标代码建立过程如图3所示。
相对于基于库的建立方式,基于源代码的目标代码建立配置文件作用范围更大,生成的目标代码更贴近应用系统。即目标代码更小,运行时占用RAM更少。
(2)Salvo配置
Salvo的配置信息保存在应用程序同一目标的salvocfg.h文件中,文件以文本形式,每项配置操作通过C语言的#define语句实现。Salvo的配置主要有以下几类操作:
①任务和事件—配置任务数,开启/关闭信号量、消息和消息队列;
②大小指定—配置延时RAM、计数器、事件标志、标记的位数;
③定时和标记—开启/关闭定时器;
④优化操作—优化运行速度、消息队列、全局变量等;
⑤监视和调试—配置指针、延时、任务、事件的监视;
⑥错误检查—开启/关闭用户函数错误检查;
⑦存储器定位—配置Salvo对象在RAM中的位置。
典型的配置文件格式如下:
#define OSBYTES_OF_DELAYS 1
//设置延时RAM长度
#define OSENABLE_MESSAGES TRUE
//开启消息处理功能
#define OSEVENTS 1
//设置应用系统中事件数
#define OSTASKS 3
//设置应用程序系统中任务数
4 结论
以上分析可知,嵌入式实时操作系统Salvo以其功能强大、内核简洁高效、占用资源少、可配置性强等特点,非常适合于资源较少,特别是存储器资源少的单片机系统使用。在单片机系统中嵌入实时操作系统Salvo,可大大缩短产品开发周期,提高可靠性,增强产品市场竞争力。