uC/OS-II的任務調度和時鐘

uC/OS-II的任務調度機制(在文件OS_CORE.C中)

      uC/OS-II有兩種任務調度器:任務級的調度器和中斷級的調度器。任務級的調度器由函數OSSched()來實現;中斷級的調度器由函數OSIntExit()來實現。

      調度器OSSched()的前半部分叫調度部分,其職責就是尋找優先級別最高的就緒任務作爲待運行任務。

if ((OSLockNesting | OSIntNesting) == 0)

在中斷服務程序中不允許進行任務調度,所以每當進入中斷服務程序就要把變量OSIntNesting加1,而當中斷返回前則要把OSIntNesting減1,這樣調度器就不會在中斷服務程序中進行調度工作了

調度器是否存在調度禁區(調度死區)以及這個禁區有多大,是直接影響內核實時性的一個重要因素。因爲在一般操作系統中,是禁止在系統調用中進行調度的,而uC/OS-II則無此限制。因此調度禁區更小,可剝奪性也就顯得更爲強硬。

      任務級調度器獲得了最高級就緒任務的任務控制塊指針之後,任務切換的工作是由宏OSCtxSw()來執行。(OSCtxSw()在文件OS_CPU_A.ASM中,由彙編編寫)。中斷級的調度器任務切換工作是由OSIntCtxSw()來完成的,通常也是用彙編語言來完成的(在文件OS_CPU_A.ASM中)

      只有就緒任務表的內容發生變化時才需要調度uC/OS-II應在所有系統調用函數的末尾及中斷服務程序結束之前調用調度器OSSched()。

uC/OS-II的初始化:void        OSInit(void);

uC/OS-II的啓動:void        OSStart(void);

這兩個函數在OS_CORE.C

      需要注意的是OSIntNesting是一個記錄中斷嵌套層數的計數器變量,所以只有當其值爲0的時候才允許調度。因此,儘管在嵌套中斷中每個中斷服務程序都調用了中斷退出函數OSIntExit(),但並非每個嵌套中斷結束前都會發生調度,而只有當變量OSIntNesting爲0時纔會發生調度。

 

臨界段

      處理器只有在開放中斷期間才能響應中斷請求,而在其他時間是不能響應中斷請求的。因爲在應用程序中經常有一些代碼段必須不受任何干擾地連續運行,這樣的代碼段較臨界段。因此爲了使臨界段在運行時不受中斷所打斷,在臨界段代碼前必須使處理器屏蔽中斷請求,而在臨界段代碼後重新接觸屏蔽,使處理器可以響應中斷請求。

      uC/OS-II中用OS_ENTER_CRITICAL()OS_EXIT_CRITICAL()這兩個宏來實現中斷的開放和關閉。而把與系統硬件相關的關中斷和開中斷的指令分別封裝在這兩個宏中

      uC/OS-II提示,不要再臨界段調用uC/OS-II提供的功能函數,以免系統崩潰。因爲在功能函數中通常也會用到這兩個宏,而處理器的開中斷和關中斷質量是不能嵌套使用的。

     

uC/OS-II的時鐘

      uC/OS-II與大多數計算機系統一樣,用硬件定時器產生一個週期爲毫秒(ms)級的週期性中斷來實現系統時鐘。最小的時鐘單位就是兩次中斷之間的間隔的時間,這個最小時鐘單位叫做時鐘節拍。

      硬件定時器以時鐘節拍爲週期定時地產生中斷,該中斷的中斷服務程序叫_OSTickISR()(在文件OS_CPU_A.ASM中用匯編編寫)。中斷服務程序通過調用函數OSTimeTick()來完成系統在每個時鐘節拍需要完成的工作。

      void OSTimeTick (void)

{

    OS_TCB *ptcb;

 

    OSTimeTickHook();                                      /* Call user definable hook                 */

    ptcb = OSTCBList;                                      /* Point at first TCB in TCB list           */

    while (ptcb->OSTCBPrio != OS_IDLE_PRIO) {              /* Go through all TCBs in TCB list          */

        OS_ENTER_CRITICAL();

        if (ptcb->OSTCBDly != 0) {                         /* Delayed or waiting for event with TO     */

            if (--ptcb->OSTCBDly == 0) {                   /* Decrement nbr of ticks to end of delay   */

                if (!(ptcb->OSTCBStat & OS_STAT_SUSPEND)) {    /* Is task suspended?                   */

                    OSRdyGrp               |= ptcb->OSTCBBitY; /* No,  Make task Rdy to Run (timed out)*/

                    OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;

                } else {                                       /* Yes, Leave 1 tick to prevent ...     */

                    ptcb->OSTCBDly = 1;                        /* ... loosing the task when the ...    */

                }                                              /* ... suspension is removed.           */

            }

        }

        ptcb = ptcb->OSTCBNext;                            /* Point at next TCB in TCB list            */

        OS_EXIT_CRITICAL();

    }

    OS_ENTER_CRITICAL();                                   /* Update the 32-bit tick counter           */

    OSTime++;

    OS_EXIT_CRITICAL();

}

      uC/OS-II在每次響應定時中斷時調用OSTimeTick()做了兩件事情:一是把用來記錄時間進程的計數器OSTime1;二是遍歷任務控制塊鏈表中的所有任務控制塊,把各個任務控制塊中用來存放任務延時時限的OSTCBDly變量減1,並使該項爲0,同時又不是被掛起的任務(即延時時間已到的任務)進入就緒狀態

      OSTimeTick()是系統調用函數,爲了使應用程序設計人員能在系統調用的函數中插入一些自己的工作,uC/OS-II提供了時鐘節拍服務函數的OSTimeTickHook()鉤子函數。以供用戶在系統調用函數中書寫自己的代碼。

 

uC/OS-II的時間管理(在文件OS_TIME.C中)

      uC/OS-II在時間管理上,主要是在任務的延時取消延時設置和獲取系統時間等方面提供服務。

      uC/OS-II規定:除了空閒任務之外的所有任務,必須在任務中的合適位置暫停運行一段時間,以給其他任務提供獲取處理器的機會。也就是說,高優先級的任務要以延時運行的手段,自願地出讓處理器使用權

uC/OS-II提供了任務延時函數

void OSTimeDly (INT16U ticks)和

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

 

void OSTimeDly (INT16U ticks)

{

    if (ticks > 0) {                                                      /* 0 means no delay!         */

        OS_ENTER_CRITICAL();

        if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) {  /* Delay current task        */

            OSRdyGrp &= ~OSTCBCur->OSTCBBitY;

        }

        OSTCBCur->OSTCBDly = ticks;                                       /* Load ticks in TCB         */

        OS_EXIT_CRITICAL();

        OSSched();                                                        /* Find next task to run!    */

    }

}

在延時函數中,會取消任務的就緒狀態而進入延時等待狀態,調用OSSched()函數實現任務的調度,實現處理器使用權的讓出。

取消任務的延時

      INT8U OSTimeDlyResume (INT8U prio)

獲取和設置系統時間

      INT32U OSTimeGet (void)

      void OSTimeSet (INT32U ticks)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章