μC/OS-Ⅱ的任務是一個無限循環,由於μC/OS-Ⅱ是可剝奪型內核,如果高優先級任務不主動掛起,低優先級任務就永遠無法取得運行權,最高優先級任務將獨佔CPU的使用權。因此,μC/OS-Ⅱ規定:除了永不掛起的空閒任務外,其它所有的任務都要在合適的時候調用系統服務函數,自我掛起,暫時放棄CPU使用權,使低優先權任務能夠得以運行。這種系統服務函數包括按節拍延時函數OSTimeDly()
和按時分秒毫秒延時函數OSTimeDlyHMSM()
。
OSTimeDly()
函數申請一個系統提供的延時,延時的單位是一個時鐘節拍,最大可延時65 535個時鐘節拍。 調用該函數後,若延時時間不爲0,則立即掛起當前任務,µC/OS-Ⅱ進行一次任務調度,並且執行下一個優先級最高的就緒態任務。任務調用OSTimeDly()
後,一旦規定的時間期滿或者有其它的任務通過調用OSTimeDlyResume()
取消了延時,該任務就會馬上進入就緒狀態。當然,只有當該任務在所有就緒任務中具有最高的優先級時,它纔會立即運行。- 在調用OSTimeDly()函數時必須注意以下事項:
- 時間的長短是用時鐘節拍的數目來確定的。
- 參數爲0,表明不進行延時操作,而立即返回調用者。
- 爲了確保設定的延時時間,建議設定的時鐘節拍數加1。
- 只能在任務中調用,無開關量。
void OSTimeDly (INT16U ticks)
{
INT8U y;
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
if (OSIntNesting > 0) { /* See if trying to call from an ISR */
return;
}
if (ticks > 0) { /* 0 means no delay! */
OS_ENTER_CRITICAL();
y = OSTCBCur->OSTCBY; /* Delay current task */
OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;
if (OSRdyTbl[y] == 0) {
OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
}
OSTCBCur->OSTCBDly = ticks; /* Load ticks in TCB */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next task to run! */
}
}
OSTimeDlyHMSM()
是以時、分、秒、毫秒爲單位進行延時。調用者只能是任務,調用後,如果延時時間不爲0,系統將立即掛起當前任務,並進行任務調度。μC/OS-Ⅱ可以將任務延時長達256個小時(接近11天)。µC/OS-Ⅱ支持的延時最長爲65 535個節拍。要想支持更長時間的延時,需採用一定的算法,一般的做法是將延時時鐘數分割爲兩部分:一部分是65536個節拍的整數倍;另一部分是總數減去這個整數倍節拍後剩下的節拍數,然後先算剩下的節拍數,再算這個整數倍節拍數。
-由於受到OSTimeDlyHMSM()
具體實現方法的限制,用戶不能用函數OSTime DlyResume()
結束延時調用OSTimeDlyHMSM()
要求延時超過65 535個節拍的任務。
INT8U OSTimeDlyHMSM (INT8U hours, INT8U minutes, INT8U seconds, INT16U ms)
{
INT32U ticks;
INT16U loops;
if (OSIntNesting > 0) { /* See if trying to call from an ISR */
return (OS_ERR_TIME_DLY_ISR);
}
#if OS_ARG_CHK_EN > 0
if (hours == 0) {
if (minutes == 0) {
if (seconds == 0) {
if (ms == 0) {
return (OS_ERR_TIME_ZERO_DLY);
}
}
}
}
if (minutes > 59) {
return (OS_ERR_TIME_INVALID_MINUTES); /* Validate arguments to be within range */
}
if (seconds > 59) {
return (OS_ERR_TIME_INVALID_SECONDS);
}
if (ms > 999) {
return (OS_ERR_TIME_INVALID_MS);
}
#endif
/* Compute the total number of clock ticks required.. */
/* .. (rounded to the nearest tick) */
ticks = ((INT32U)hours * 3600L + (INT32U)minutes * 60L + (INT32U)seconds) * OS_TICKS_PER_SEC
+ OS_TICKS_PER_SEC * ((INT32U)ms + 500L / OS_TICKS_PER_SEC) / 1000L;
loops = (INT16U)(ticks >> 16); /* Compute the integral number of 65536 tick delays */
ticks = ticks & 0xFFFFL; /* Obtain the fractional number of ticks */
OSTimeDly((INT16U)ticks);
while (loops > 0) {
OSTimeDly((INT16U)32768u);
OSTimeDly((INT16U)32768u);
loops--;
}
return (OS_ERR_NONE);
}
OSTimeDlyResume()
函數用於喚醒一個用OSTimeDly()
或OSTimeDlyHMSM()
函數延時的任務。正在延時的任務可以通過其它任務調用該函數取消延時來使自己處於就緒態,而不必等待延時期滿。該函數還可以喚醒正在等待事件的任務,但不推薦使用這種方法。
INT8U OSTimeDlyResume (INT8U prio)
{
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3 /* Storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
if (prio >= OS_LOWEST_PRIO) {
return (OS_ERR_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio]; /* Make sure that task exist */
if (ptcb == (OS_TCB *)0) {
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST); /* The task does not exist */
}
if (ptcb == OS_TCB_RESERVED) {
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST); /* The task does not exist */
}
if (ptcb->OSTCBDly == 0) { /* See if task is delayed */
OS_EXIT_CRITICAL();
return (OS_ERR_TIME_NOT_DLY); /* Indicate that task was not delayed */
}
ptcb->OSTCBDly = 0; /* Clear the time delay */
if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
ptcb->OSTCBStat &= ~OS_STAT_PEND_ANY; /* Yes, Clear status flag */
ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /* Indicate PEND timeout */
} else {
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
}
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? */
OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
OS_Sched(); /* See if this is new highest priority */
} else {
OS_EXIT_CRITICAL(); /* Task may be suspended */
}
return (OS_ERR_NONE);
}