從零開始學習UCOSII操作系統5--時間管理

從零開始學習UCOSII操作系統5--時間管理

1、UCOSII的定時中斷

(1)絕大多數的內核要求提供定時中斷,以實現延時與超時控制等功能。這個定時中斷叫做時鐘節拍。

(2)時鐘的中斷子程序ISR和時鐘節拍函數OSTimeTick()該函數用於通知UCOSII,發生了時鐘的節拍中斷。

2、UCOSII的5個關鍵的時鐘函數

(1)OSTimeDly();

後面的4個函數可以根據需要進行配置使用
(2)OSTimeHMSM();
(3)OSTimeDlyResume();
(4)OSTimeGet();
(5)OSTimeSet();

3、關鍵的時鐘延時函數的實現OSTimeDly()

(1)參數分析:
ticks:代表的是多少個時鐘週期節拍

(2)實現過程:
把相應任務的就緒表中的位圖的位置清零。
把需要執行的等待節拍進行處理。
最後進行任務調度,尋找下一個這個時刻最高優先級的任務。

(3)發出疑問?爲什麼我在OS_TCB的結構體當中的Ticks填寫相應的數字的時候可以實現把任務從就緒態變爲等待的狀態?

答案OSTimeTick()這個函數

void  OSTimeDly (INT32U ticks)
{
    INT8U      y;
#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0u;
#endif



    if (OSIntNesting > 0u) {                     /* See if trying to call from an ISR                  */
        return;
    }
    if (OSLockNesting > 0u) {                    /* See if called with scheduler locked                */
        return;
    }
    if (ticks > 0u) {                            /* 0 means no delay!                                  */
        OS_ENTER_CRITICAL();
        y            =  OSTCBCur->OSTCBY;        /* Delay current task                                 */
        OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
        if (OSRdyTbl[y] == 0u) {
            OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
        }
        OSTCBCur->OSTCBDly = ticks;              /* Load ticks in TCB                                  */
        OS_EXIT_CRITICAL();
        OS_Sched();                              /* Find next task to run!                             */
    }
}

實現任務等待時間的關鍵的函數:
PS:我以後都會把對理解無關緊要的代碼刪除。

(1)當任務是處於運行的狀態的時候。判斷OS現在處於的是什麼樣的狀態。

(2)所有的任務都是通過任務的鏈表鏈接到一起的,我們後面的一個while循環就是,從開始不斷的遍歷到最後的任務,也就是空閒任務。

(3)對延時的時間不斷的減1,當延時的dlyTick減少到0的時候,對OS_TCB任務控制塊的一些狀態進行修改,並且重新的把任務添加回就緒表中。

PS:這個函數應該是放置到中斷服務函數中的,整個時間片的不斷的觸發執行的。

void  OSTimeTick (void)
{
    OS_TCB    *ptcb;

    if (OSRunning == OS_TRUE) {
#if OS_TICK_STEP_EN > 0u
        switch (OSTickStepState) {                         /* Determine whether we need to process a tick  */
            case OS_TICK_STEP_DIS:                         /* Yes, stepping is disabled                    */
                 step = OS_TRUE;
                 break;

            case OS_TICK_STEP_WAIT:                        /* No,  waiting for uC/OS-View to set ...       */
                 step = OS_FALSE;                          /*      .. OSTickStepState to OS_TICK_STEP_ONCE */
                 break;

            case OS_TICK_STEP_ONCE:                        /* Yes, process tick once and wait for next ... */
                 step            = OS_TRUE;                /*      ... step command from uC/OS-View        */
                 OSTickStepState = OS_TICK_STEP_WAIT;
                 break;

            default:                                       /* Invalid case, correct situation              */
                 step            = OS_TRUE;
                 OSTickStepState = OS_TICK_STEP_DIS;
                 break;
        }
        if (step == OS_FALSE) {                            /* Return if waiting for step command           */
            return;
        }
#endif

//此處爲此任務運行的核心的代碼:

        ptcb = OSTCBList;                                  /* Point at first TCB in TCB list               */
        while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {     /* Go through all TCBs in TCB list              */
            OS_ENTER_CRITICAL();
            if (ptcb->OSTCBDly != 0u) {                    /* No, Delayed or waiting for event with TO     */
                ptcb->OSTCBDly--;                          /* Decrement nbr of ticks to end of delay       */
                if (ptcb->OSTCBDly == 0u) {                /* Check for timeout                            */

                    if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
                        ptcb->OSTCBStat  &= (INT8U)~(INT8U)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;
                    }
                }
            }
            ptcb = ptcb->OSTCBNext;                        /* Point at next TCB in TCB list                */
            OS_EXIT_CRITICAL();
        }
    }
}

OSTimeDlyHmSM
INT8U OSTimeDlyHMSM (INT8U hours, INT8U minutes, INT8U seconds, INT16U milli)

由於OSTimeDlyHMSM()的具體實現方法,用戶不能結束延時調用OSTimeDlyHMSM()要求延時超過65535個節拍的任務。換句話說,如果時鐘節拍的頻率是100Hz,用戶不能讓調用OSTimeDlyHMSM(0,10,55,350)或更長延遲時間的任務結束延時。

4、恢復延時的任務:OSTimeDlyResume()

裏面關鍵的操作就是把那個全局的時間計數器變量設置爲0

INT8U  OSTimeDlyResume (INT8U prio)
{
    OS_TCB    *ptcb;

    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 == 0u) {                                /* See if task is delayed               */
        OS_EXIT_CRITICAL();
        return (OS_ERR_TIME_NOT_DLY);                          /* Indicate that task was not delayed   */
    }

    ptcb->OSTCBDly = 0u;                                       /* 清除任務計數器       */
    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);
}

發佈了89 篇原創文章 · 獲贊 86 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章