在 3.10节时钟节拍中曾说到,μC/OS-Ⅱ(其它内核也相同)要求用户供给守时中止来完成延时与超时操控等功能。这个守时中止叫做时钟节拍,它应该每秒发生10至100次。时钟节拍的实践频率是由用户的使用程序决议的。时钟节拍的频率越高,体系的负荷就越重。
3.10 节评论了时钟的中止服务子程序和节时钟节函数 OSTimeTIck——该函数用于告知μC/OS-Ⅱ发生了时钟节拍中止。本章首要叙述五个与时钟节拍有关的体系服务:
z OSTimeDly()
z OSTimeDlyHMSM()
z OSTimeDlyResume()
z OSTimeGet()
z OSTimeSet()
本章所说到的函数能够在OS_TIME.C文件中找到。
5.0使命延时函数,OSTimeDly()
μC/OS-Ⅱ供给了这样一个体系服务:请求该服务的使命能够延时一段时刻,这段时刻的长短是用时钟节拍的数目来确认的。完成这个体系服务的函数叫做OSTimeDly()。调用该函数会使μC/OS-Ⅱ进行一次使命调度,而且履行下一个优先级最高的安排妥当态使命。使命调用OSTimeDly()后,一旦规则的时刻期满或许有其它的使命经过调用OSTimeDlyResume()取消了延时,它就会立刻进入安排妥当状况。留意,只有当该使命在所有安排妥当使命中具有最高的优先级时,它才会当即运转。
程序清单L5.1所示的是使命延时函数OSTimeDly()的代码。用户的使用程序是经过供给延时的时钟节拍数——一个1到65535之间的数,来调用该函数的。假设用户指定0值[L5.1(1)],则标明用户不想延时使命,函数会当即返回到调用者。非0值会使得使命延时函数OSTimeDly()将当前使命从安排妥当表中移除[L5.1(2)]。接着,这个延时节拍数会被保存在当前使命的OS_TCB中[L5.1(3)],而且经过OSTimeTick()每隔一个时钟节拍就削减一个延时节拍数。最终,已然使命现已不再处于安排妥当状况,使命调度程序会履行下一个优先级最高的安排妥当使命。
程序清单 L5.1 OSTimeDly().
voidOSTimeDly(INT16Uticks)
{
if(ticks>0){(1)
OS_ENTER_CRITICAL();
if((OSRdyTbl[OSTCBCur->OSTCBY]=~OSTCBCur->OSTCBBitX)==0)
{(2)
OSRdyGrp=~OSTCBCur->OSTCBBitY;
}
OSTCBCur->OSTCBDly=ticks;(3)
OS_EXIT_CRITICAL();
OSSched();(4)
}
}
清楚地知道0到一个节拍之间的延时进程是非常重要的。换句话说,假设用户只想延时一个时钟节拍,而实践上是在0到一个节拍之间完毕延时。即便用户的处理器的负荷不是很重,这种状况依然是存在的。图F5.1具体说明晰整个进程。体系每隔10ms发生一次时钟节拍中止[F5.1(1)]。假设用户没有履行其它的中止而且此刻的中止是开着的,时钟节拍中止服务就会发生[F5.1(2)]。或许用户有好几个高优先级的使命(HPT)在等候延时期满,它们会接着履行[F5.1(3)]。接下来,图5.1中所示的低优先级使命(LPT)会得到履行的时机,该使命在履行完后立刻调用[F5.1(4)]所示的 OSTimeDly(1)。 μC/OS-Ⅱ会使该使命处于休眠状况直至下一个节拍的到来。当下一个节拍到来后,时钟节拍中止服务子程序会履行[F5.1(5)],可是这一次由于没有高优先级的使命被履行,μC/OS-Ⅱ会当即履行请求延时一个时钟节拍的使命[F5.1(6)]。正如用户所看到的,该使命实践的延时少于一个节拍!在负荷很重的体系中,使命甚至有或许会在时钟中止行将发生时调用OSTimeDly(1),在这种状况下,使命简直就没有得到任何延时,由于使命立刻又被从头调度了。假设用户的使用程序至少得延时一个节拍,必需求调用OSTimeDly(2),指定延时两个节拍!
Figure5.1DelayresolutiON.
5.1准时分秒延时函数 OSTimeDlyHMSM()
OSTimeDly()虽然是一个非常有用的函数,但用户的使用程序需求知道延时时刻对应的时钟节拍的数目。用户能够运用界说大局常数OS_TICKS_PER_SEC(参看OS_CFG.H)的办法将时刻转换成时钟段,但这种办法有时显得比较愚笨。笔者增加了OSTimeDlyHMSM()函数后,用户就能够按小时(H)、分(M)、秒(S)和毫秒(m)来界说时刻了,这样会显得更天然些。与OSTimeDly()相同,调用OSTimeDlyHMSM()函数也会使μC/OS-Ⅱ进行一次使命调度,而且履行下一个优先级最高的安排妥当态使命。使命调用OSTimeDlyHMSM()后,一旦规则的时刻期满或许有其它的使命经过调用OSTimeDlyResume()取消了延时(参看5.02,康复延时的使命OSTimeDlyResume()),它就会立刻处于安排妥当态。相同,只有当该使命在所有安排妥当态使命中具有最高的优先级时,它才会当即运转。
程序清单L5.2所示的是OSTimeDlyHMSM()的代码。从中能够看出,使用程序是经过用小时、分、秒和毫秒指定延时来调用该函数的。在实践使用中,用户应防止使使命延时过长的时刻, 由于从使命中取得一些反应行为(如削减计数器, 铲除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_T%&&&&&%KS_PER_SEC的值为100,用户想延时15分钟,则OSTimeDlyHMSM()会延时15x60x100=90,000个时钟。这个延时会被分割成两次32,768个节拍的延时(由于用户只能延时65,535个节拍而不是65536个节拍)和一次24,464个节拍的延时。在这种状况下,OSTimeDlyHMSM()首要考虑剩余的节拍,然后是超越65,535的节拍数[L5.2(7)和(8)](即两个32,768个节拍延时)。