μC/OS-II的时间管理
为从任务中获得一些反馈行为(如减少计数器, 清除LED等等)经常是很不错的事。
但是,如果用户确实需要延时长时间的话,μC/OS-Ⅱ可以将任务延时长达256个小时(接近11天)。
OSTimeDlyHMSM()一开始先要检验用户是否为参数定义了有效的值[L5.2(1)]。与OSTimeDly()一样,即使用户没有定义延时,OSTimeDlyHMSM()也是存在的[L5.2(9)]。因为μC/OS-Ⅱ只知道节拍,所以节拍总数是从指定的时间中计算出来的[L5.2(3)]。很明显,程序清单L5.2中的程序并不是十分有效的。笔者只是用这种方法告诉大家一个公式,这样用户就可以知道怎样计算总的节拍数了。真正有意义的只是OS_TICKS_PER_SEC。[L5.2(3)]决定了最接近需要延迟的时间的时钟节拍总数。500/OS_TICKS_PER_SECOND的值基本上与0.5个节拍对应的毫秒数相同。例如,若将时钟频率(OS_TICKS_PER_SEC)设置成100Hz(10ms),4ms的延时不会产生任何延时!而5ms的延时就等于延时10ms。
μC/OS-Ⅱ支持的延时最长为65,535个节拍。要想支持更长时间的延时,如L5.2(2)所示,OSTimeDlyHMSM()确定了用户想延时多少次超过65,535个节拍的数目[L5.2(4)]和剩下的节拍数[L5.2(5)]。例如,若OS_TICKS_PER_SEC的值为100,用户想延时15分钟,则OSTimeDlyHMSM()会延时15x60x100=90,000个时钟。这个延时会被分割成两次32,768个节拍的延时(因为用户只能延时65,535个节拍而不是65536个节拍)和一次24,464个节拍的延时。在这种情况下,OSTimeDlyHMSM()首先考虑剩下的节拍,然后是超过65,535的节拍数[L5.2(7)和(8)](即两个32,768个节拍延时)。
程序清单 L5.2 OSTimeDlyHMSM().
INT8UOSTimeDlyHMSM(INT8Uhours,INT8Uminutes,INT8Useconds,INT16U
milli)
{
INT32Uticks;
INT16Uloops;
if(hours>0|| minutes>0|| seconds>0|| milli>0){(1)
if(minutes>59){
return(OS_TIME_INVALID_MINUTES);
}
if(seconds>59){
return(OS_TIME_INVALID_SECONDS);
}
If(milli>999){
return(OS_TIME_INVALID_MILLI);
}
ticks=(INT32U)hours*3600L*OS_TICKS_PER_SEC(2)
+(INT32U)minutes*60L*OS_TICKS_PER_SEC
+(INT32U)seconds*OS_TICKS_PER_SEC
+OS_TICKS_PER_SEC*((INT32U)milli
+500L/OS_TICKS_PER_SEC)/1000L;(3)
loops=ticks/65536L;(4)
ticks=ticks%65536L;(5)
OSTimeDly(ticks);(6)
while(loops>0){(7)
OSTimeDly(32768);(8)
OSTimeDly(32768);
loops--;
}
return(OS_NO_ERR);
}else{
return(OS_TIME_ZERO_DLY);(9)
}
}
由于OSTimeDlyHMSM()的具体实现方法,用户不能结束延时调用OSTimeDlyHMSM()要求延时超过65535个节拍的任务。换句话说,如果时钟节拍的频率是100Hz,用户不能让调用OSTimeDlyHMSM(0,10,55,350)或更长延迟时间的任务结束延时。
5.2让处在延时期的任务结束延时,OSTimeDlyResume()
μC/OS-Ⅱ允许用户结束延时正处于延时期的任务。延时的任务可以不等待延时期满,而是通过其它任务取消延时来使自己处于就绪态。这可以通过调用OSTimeDlyResume()和指定要恢复的任务的优先级来完成。实际上,OSTimeDlyResume()也可以唤醒正在等待事件(参看第六章——任务间的通讯和同步)的任务,虽然这一点并没有提到过。在这种情况下,等待事件发生的任务会考虑是否终止等待事件。
OSTimeDlyResume()的代码如程序清单L5.3所示,它首先要确保指定的任务优先级有效[L5.3(1)]。 接着, OSTimeDlyResume()要确认要结束延时的任务是确实存在的[L5.3(2)]。
如果任务存在, OSTimeDlyResume()会检验任务是否在等待延时期满[L5.3(3)]。 只要OS_TCB
域中的OSTCBDly包含非0值就表明任务正在等待延时期满,因为任务调用了OSTimeDly(),OSTimeDlyHMSM()或其它在第六章中所描述的PEND函数。然后延时就可以通过强制命令OSTCBDly为0来取消[L5.3(4)]。延时的任务有可能已被挂起了,这样的话,任务只有在没有被挂起的情况下才能处于就绪状态[L5.3(5)]。当上面的条件都满足后,任务就会被放在就绪表中[L5.3(6)]。这时,OSTimeDlyResume()会调用任务调度程序来看被恢复的任务是否拥有比当前任务更高的优先级[L5.3(7)]。这会导致任务的切换。
程序清单 L5.3 恢复正在延时的任务
INT8UOSTimeDlyResume(INT8Uprio)
{
OS_TCB*ptcb;
if(prio>=OS_LOWEST_PRIO){(1)
return(OS_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
ptcb=(OS_TCB*)OSTCBPrioTbl[prio];
if(ptcb!=(OS_TCB*)0){(2)
if(ptcb->OSTCBDly!=0){(3)
ptcb->OSTCBDly=0;(4)
if(!(ptcb->OSTCBStatOS_STAT_SUSPEND)){(5)
OS
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
