μC/OSII中软件定时器的优缺点与改进

μc/osii具有小巧、性能稳定、开源等众多优点,并且μc/osii大部分用ansi c语言编写,系统的移植非常容易。在μc/osii i2.81及以后的版本中[2],加入了对软件定时器的支持,使得μc/osii操作系统更加完善。
μc/osii是一种基于优先级的抢占式操作系统,实时性很强。而系统中软件定时器没有优先级,回调函数顺序执行,这样就降低了系统的实时性。因此,本文对软件定时器进行改进,定时器中加入优先级,回调函数按优先级执行,从而提高系统的实时性。
1 对软件定时器的介绍
μc/osii系统中的时间管理功能包括任务延时与软件定时器,而软件定时器的主要作用是,对函数周期性或者一次性执行的定时,利用软件定时器控制块与“定时器轮”管理软件定时器。定时器控制块的结构如同任务控制块,创建一个定时器时,从空闲定时器控制块链表中得到一个空闲控制块,并对其赋值。
软件定时器也需要一个时钟节拍驱动,而这个驱动一般是硬件实现的,一般使用μc/osii操作系统中任务延时的时钟节拍来驱动软件定时器。每个时钟节拍ostmrctr(全局变量,初始值为0)增1, 当ostmrctr的值等于为os_ticks_per_sec /os_tmr_cfg_ticks_per_sec(此两者的商决定软件定时器的频率)时,调用函数ostmrsignal(),此函数发送信号量ostmrsemsignal(初始值为0,决定软件定时器扫描任务ostmr_task的运行)。也就是说,对定时器的处理不在时钟节拍中断函数中进行,而是以发生信号量的方式激活任务ostmr_task(具有很高的优先级)。任务ostmr_task对定时器进行检测处理,包括定时器定时完成的判断、回调函数的执行。
μc/osii 2.86中与软件定时器相关的函数包括:
① 软件定时器内部静态函数。获取与释放定时器控制块函数ostmr_alloc()、ostmr_free();定时器插入相应“时间轮”组函数ostmr_link();从相应“时间轮”组中删除定时器函数ostmr_unlink();软件定时器任务初始化函数ostmr_inittask();定时器扫描任务ostmr_task;定时器上锁与解锁函数ostmr_lock()与ostmr_unlock()(在μc/osii 2.91中,此两函数被任务调度锁定与解锁函数代替)。
② 定时器外部接口函数。定时器创建与删除函数ostmrcreate()、ostmrdel();定时器启动与停止函数ostmrstart()、ostmrstop();定时器剩余时间与当前状态查询函数ostmrremainget()、ostmrstateget();软件定时器的初始化ostmr_init();发送信号量ostmrsemsignal函数ostmrsignal();定时器名称查询函数ostmrnameget()。
由于软件定时器的回调函数的执行都是在任务ostmr_task中执行,如果多个定时器同时定时完成,则在定时器任务中执行多个定时器的回调函数,因此定时器任务的执行时间不确定。而且定时器回调函数是顺序执行的,如果某个定时器回调函数需要尽快执行以实现精确定时,就难以实现了。由于各个定时器没有优先级,因此了影响系统的实时性。
2 对软件定时器的改进
为提高软件定时器回调函数执行的实时性,给每个定时器赋予一个优先级。当定时完成时,并且定时器的回调函数不为空,则把定时器的优先级写于软件定时器就绪表中。任务ostmr_task对相应“时间轮”检查结束后,如果在扫描各个定时器前软件定时器就绪表为零而扫描之后不为零,则发送信号量激活回调函数任务ostmr_taskcallback。在此任务中,回调函数根据软件定时器就绪表中的优先级执行相应的回调函数,这样就提高了系统的实时性。
2.1 对软件定时器相关数据结构改进
① 定义结构体os_tmr_call,存储定时器的回调函数、函数的参数、定时器指针,形式如下:
typedefstructos_tmr_call {
os_tmr_callbackostmrcallback; /*回调函数*/
void *ostmrcallbackarg;/*回调函数指针*/
os_tmr *ostmr; /*定时器指针*/
} os_tmr_call;
在头文件ucos_ii.h中,定义ostmrcallbacktbl[os_tmr_cfg_max],os_tmr_cfg_max表示系统中配置的软件定时器数量。
② 在软件定时器控制块中加入成员变量ostmrprio(定时器优先级),删去变量ostmrcallback(回调函数)、ostmrcallbackarg(回调函数参数),为了测试的方便,可暂不删除这两个变量。
③ 定义定时器就绪表:
int8uostmrrdygrp;
int8uostmrrdytbl[os_tmr_cfg_max/8 + 1];
当定时器定时完成时,把定时器优先级写入就绪表,回调函数任务根据优先级执行回调函数。
④ 定义信号量ostmrsemcallback(初始值0 ),当定时完成后,发送此信号量,激活回调函数任务,以执行回调函数。
2.2 与软件定时器相关的函数函数与任务的改进
2.2.1 软件定时器创建函数ostmrcreate
在创建函数ostmrcreate的参数中加入优先级参数prio。调用创建函数时,对定时器控制块中的成员变量赋值,并给回调函数数组的相应单元赋值,形式如下:
ostmrcallbacktbl [prio].ostmrcallback = callback;
ostmrcallbacktbl [prio].ostmrcallbackarg = callback_arg;
ostmrcallbacktbl [prio].ostmr = ptmr;
2.2.2 对定时器任务ostmr_task的改进
当有定时器定时完成,把定时器优先级写入软件定时器就绪表中,并根据就绪表前后的值判断时候发送信号量ostmrsemsignal,以激活回调函数任务。任务ostmr_task的流程如图1所示。
图1 ostmr_task的流程
把定时器优先级写入定时器就绪表的代码如下所示:
if (ostmrtime == ptmr>ostmrmatch) {
prio = ptmr>ostmrprio;
pfnct =ostmrcall[prio].ostmrcallback;
if (pfnct != (os_tmr_callback)0) { /*加入定时器回调函数就绪表*/
ostmrrdygrp|= (int8u)(1 《 (int8u)(prio 》 0x03));
ostmrrdytbl[prio >> 0x03]|= (int8u)(1 《 (int8u)(prio & 0x07));
}
}
2.2.3 对定时器停止函数ostmrstop()的修改
函数ostmrstop只需修改与回调函数执行相关的部分即可,例如,case os_tmr_opt_callback_arg: 部分的代码如下:
case os_tmr_opt_callback_arg:
prio = ptmr>ostmrprio;
pfnct = ostmrcall[prio].ostmrcallback;
if (pfnct != (os_tmr_callback)0) {
……/*prio加入定时器就绪表*/
ostmrcall[prio].ostmrcallbackarg =(void *)callback_arg;
ossempost(ostmrsemcallback); /*发送回调函数执行信号量*/
}else {
*perr = os_err_tmr_no_callback;
}
而case os_tmr_opt_callback:部分的代码同上,只是回调函数的参数不需要重新赋值。
2.2.4 回调函数任务ostmr_taskcallback()
在源文件tmr.c中加入回调函数任务ostmr_taskcallback(),根据定时器就绪表中的优先级执行相应回调函数,回调函数任务的结构如下所示:
static voidostmr_taskcallback(void *p_arg) {……/*变量定义*/
for (;;){//请求信号量ostmrsemcallback
ossempend(ostmrsemcallback, 0, &err);
ostmr_lock();/*定时器上锁*/
while (ostmrrdygrp) {
……/*从定时器就绪表中得到最高优先级的定时器回调函数*/
……/*删除就绪表中的占有位*/
ostmr_unlock(); /*定时器上锁*/
pfnct = ostmrcall[prio].ostmrcallback;
(*pfnct)((void *)(ostmrcall[prio].ostmr),ostmrcall[prio].ostmrcallbackarg); /*执行回调函数*/
ostmr_lock(); /*定时器上锁*/
}
ostmr_unlock();/*定时器解锁*/
}
}
由以上代码可知,访问就绪表时定时器上锁,而执行回调函数时处于定时器解锁状态。如果回调函数执行时间较长,在下一个软件定时器节拍到来时,定时器扫描任务可以得到及时的执行,当前回调函数执行完成后,可以及时得执行就绪表中最高优先级定时器的回调函数。由此可以看出,高优先级定时器的回调函数得到及时执行,系统的实时性提高。
实验测试发现,在回调函数任务ostmr_taskcallback中,使用任务调度上锁与解锁比使用定时器上锁与解锁(即信号量的请求)执行速度快一些。毕竟回调函数任务的优先级很高(一般仅次于定时器扫描任务ostmr_task的优先级),所以使用任务调度锁定比定时器锁定要好一些。当然,还可以使用开关中断的方式对就绪表进行访问,可以根据实际情况选择使用哪种方式。
3 实验测试
本次实验使用软件开发环境iar 5.30,以基于cortexm3内核的路虎lpc1768开发板作为硬件实验平台[6],对实时操作系统μc/osii 2.86进行改进。
对改进后的操作系统进行测试,在主函数中创建一个启动任务,在启动任务中创建4个周期定时器(系统中“时间轮”数设为4),赋予不同优先级与定时值,每个定时器控制一个led的闪烁,启动这4个定时器。在启动函数中创建4个任务,每个任务也是控制一个led灯的闪烁(利用任务延时),之后启动任务挂起。利用μc/osii cspy插件观察各定时器的运行情况,如图2所示。
图2 软件定时器运行界面
经实验测试,系统运行正常,定时器回调函数得到及时的执行,系统实时性得到很大的提高。
4 结语
软件定时器改进后,定时器任务的执行时间确定,仅与同时完成定时的定时器数目有关,对处于就绪表中的定时器回调函数按优先级执行,使高优先级定时器的回调函数得到及时的执行,提高了系统的实时性。

Molex推出新型Lite-Trapä SMT线对板连接器系统 高度仅为 4.20mm
曙光云助力天津市教育管理信息系统迁移上云
智能工业-产品外观瑕疵质检
什么 悍马居然变成了一台纯电动皮卡
面向CAN总线初学者的教程分享
μC/OSII中软件定时器的优缺点与改进
Ubuntu 20.04 LTS最后一个Beta测试版本发布 带来最新GNOME 3.36版桌面环境
三星GalaxyS11采用新电池技术,可容纳5000毫安时大电池
如何解决人工智能推理引擎新型基础设施的自身漏洞?
规模庞大的动力电池市场将催生电池回收行业的机遇
符合功能安全要求的动态测试工具-TESSY
图库四种常见操作的HarmonyOS图像编解码开发
理想三大核心风险,李想曝光!
全球机器人消费市场高度集中,新加坡和韩国装机密度领先全球
“新四化”推动汽车存储需求,西部数据引领车载存储革新
基于MAXREFDES220的心率和 SpO2 血氧传感器的医疗监测电路设计
每日公告:奥普光电、弘信电子、兴森科技、中微公司、至纯科技
车联网的定义及概念解析
大数据无处不在,安全性需要得到重视
Moto X(2017)上手图曝光 坐等发布