μC/OSII中软件定时器的优缺点与改进
软件定时器创建函数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 结语
软件定时器改进后,定时器任务的执行时间确定,仅与同时完成定时的定时器数目有关,对处于就绪表中的定时器回调函数按优先级执行,使高优先级定时器的回调函数得到及时的执行,提高了系统的实时性。
- μC/OS-II下通用驱动框架的设计与实现(07-23)
- 基于μC/OS-II嵌入式系统的低功耗开发(07-08)
- 基于S3C44B0X+μcLinux的嵌入式以太网设计(07-08)
- 蓄电池化成控制系统中显示功能的实现(11-05)
- 嵌入式实时操作系统μC/OS-II 在P89V51RD2中的移植(04-09)
- LPC2292的伪中断与伪中断处理(03-25)