上一次我们谈到了任务管理,今天来讲一下uC/OS的时间管理。
大家初学单片机的时候都跑过流水灯这个例程吧,流水灯程序里一定有延时函数delay吧,想想那时候delay是怎么写的:让CPU空转!空转啊同学们,多么令人心疼的事,8051核这么经典的设计让你们用来空转啊(咳咳,当然了51跑多任务还是比较吃力的)。
那么说回来,uC/OS是如何处理眼是这个问题的呢?μC/OS需要用户提供周期性信号源,它利用这个信号源定义一个时钟节拍,用这个时钟节拍实现时间延时和确认超时。(时钟节拍率应在10到100Hz之间,时钟节拍率越高,系统的额外负荷就越重);
时钟节拍是一种特殊的中断,相当于操作系统的心脏起搏器。那么这个中断里做了什么事,我看了下这个ISR的伪代码
void OSTickISR(void)
{
(1)保存处理器寄存器的值;
(2)调用OSIntEnter()或将OSIntNesting加1;
(3)调用OSTimeTick(); /*检查每个任务的时间延时*/
(4)调用OSIntExit();
(5)恢复处理器寄存器的值;
(6)执行中断返回指令;
}
OSTimeTick()这个函数就是把每个任务的TCB块里的OSTCBDly变量减1,当OSTCBDly==0时则检查该任务是否被挂起,若没被挂起则将该任务列到就绪表,准备运行。同时把系统时间变量(UINT32)OSTime++。也就是说系统在2^32个系统节拍后从0开始重新计数,我们可以算一下,若时间节拍为100HZ也就是10ms,则我们的系统在497天后重新运行,呵呵这下好了,开机一年都没问题!
与时间管理的相关系统服务有
OSTimeDLY();//任务延时函数,申请该服务的任务可以延时一段时间, 调用OSTimeDLY后,任务进入等待状态
OSTimeDLYHMSM();//OSTimeDly()的另一个版本,即按时分秒延时函数;
OSTimeDlyResum();//让处在延时期的任务提前结束延时,进入就绪状态;
OK,如果现在我想运行流水灯程序,那么按照程序来,点亮一个灯。。。延时。。。点下一个灯。。。这时候就可以在WaterLight这个TASK里申请一个延时函数OSTimeDLY();任务让出CPU,进入等待状态,等待--OSTimeDly == 0。
CPU现在空下来了,好嘞,运行OSSched()进行任务调度。这样就充分利用了CPU的资源,压榨每一一个晶体管的劳动力哈哈!