1. 程式人生 > >ucosiii學習(3)——任務排程和時間片輪轉

ucosiii學習(3)——任務排程和時間片輪轉

1.任務級排程器 OSSched()

系統初始化後會自動建立幾個任務,可以看到所呼叫的建立任務函式OSTaskCreate的最後都會呼叫OSSched()函式(任務級排程器)。

Description: This function is called by other uC/OS-III services to determine whether a new, high priority task has been made ready to run.  This function is invoked by TASK level code and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling).

該函式定義在os_core.c中,可以看到 該函式體中依次執行

CPU_INT_DIS();

OSPrioHighRdy   = OS_PrioGetHighest(); 

CPU_INT_DIS();        //  cpu_sr = CPU_SR_Save(); 關閉中斷
OSPrioHighRdy   = OS_PrioGetHighest();    //獲取就緒任務的最高優先順序
if (OS_CFG_TASK_IDLE_EN == DEF_ENABLED)
    OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr; //獲取優先順序最高的就緒任務
if (OSTCBHighRdyPtr == OSTCBCurPtr)    //優先順序最高的就緒任務為當前任務
   {                       
        CPU_INT_EN();                 //CPU_SR_Restore(cpu_sr); 開啟中斷                     
        return;
    }

 OS_TASK_SW();           //判斷沒有中斷和被鎖住後,呼叫該彙編程式碼                                 
 CPU_INT_EN();

2.中斷級排程器 OSIntExit()

Description: This function is used to notify uC/OS-III that you have completed servicing an ISR.  When the last nested ISR has completed, uC/OS-III will call the scheduler to determine whether a new, high-priority task, is ready to run.

在中斷級排程器中真正完成任務切換的就是中斷級任務切換函式OSIntCtxSW()

,與任務級切換函式OSCtxSW()不同的是,由於進入中斷的時候現場已經儲存過了,所以OSIntCtxSW()不需要像OSCtxSW()一樣先儲存當前任務現場,只需要做OSCtxSW()的後半部分工作,也就是從將要執行的任務堆疊中恢復CPU暫存器的值。

其中:OSIntNestingCtr為中斷巢狀計數器,進入中斷服務函式後我們要呼叫OSIntEnter()函式,在這個函式中會將OSIntNestingCtr加1,用來記錄中斷巢狀的次數。而OSIntExit()是在退出中斷服務函式時呼叫的,因此中斷巢狀計數器要減1。如果減1之後,OSIntNestingCtr還大於0,說明還有其他的中斷髮生,那麼就跳回到中斷服務程式中,不需要做任務切換。

任務排程點:
1、釋放訊號量或者傳送訊息,也可通過配置相應的引數不發生任務排程。 
2、使用延時函式OSTimeDly()或者OSTimeDlyHMSM()。 
3、任務等待的事情還沒發生(等待訊號量,訊息佇列等)。 
4、任務取消等待。 
5、建立任務。 
6、刪除任務。 
7、刪除一個核心物件。 
8、任務改變自身的優先順序或者其他任務的優先順序。 
9、任務通過呼叫OSTaskSuspend()將自身掛起。 
10、任務解掛某個掛起的任務。 
11、退出所有的巢狀中斷。 
12、通過OSSchedUnlock()給排程器解鎖。 
13、任務呼叫OSSchedRoundRobinYield()放棄其執行時間片。 
14、使用者呼叫OSSched()。
有時候我們並不希望發生任務排程,因為始終有一些程式碼的執行過程是不能被打斷的。此時我們就可以使用函式OSSchedLock()對排程器加鎖,當我們想要恢復任務排程的時候就可以使用函式OSSchedUnlock()給已經上鎖的任務排程器解鎖

3.時間片輪轉排程器OS_SchedRoundRobin()

UCOSIII允許一個優先順序下有多個任務,每個任務可以執行指定的時間(時間片),然後輪到下一個任務,這個過程就是時間片輪轉排程,當一個任務不想在執行的時候就可以放棄其時間片。 
如果某一優先順序下有多個任務話,這些任務是如何被排程和執行的:先判斷該任務的時間片是否有剩餘,如果有就直接返回不切換;如果沒有,就進行切換。每次任務切換後執行的都是處於就緒任務列表OSRdyList[ ]連結串列頭的任務,當這個任務的時間片用完後這個任務就會被放到連結串列尾,然後再執行新的連結串列頭的任務。