uC/OS-II內核架構解析(3)---uC/OS-II系統核心

主要包含在C源文件OS_CORE.C中。

1. uC/OS-II任務調度

(1) uC/OS-II調度算法

     uC/OS-II採用基於優先級的調度算法,總是選擇當前處於就緒狀態的優先級最高的任務進行調度。uC/OS-II是可搶佔性的強實時性OS,在完成中斷後允許進行新的任務調度。

     uC/OS-II有兩種調度方式:任務級任務調度、中斷級任務調度。

(2) 任務就緒表

     INT8U const OSUnMapTbl[256] = {…};

     OS_EXT INT8U OSRdyGrp;

     OS_EXT INT8U OSRdyTbl[OS_RDY_TBL_SIZE];

  • 添加就緒任務至就緒表;

  • 從就緒表刪除就緒任務;

  • 查找最高優先級就緒任務OS_SchedNew();

(3) 任務級任務調度

     指在非中斷返回時進行任務調度,一般發生在當前任務因時間延遲或等待某事件而阻塞或被掛起,或有更高優先級的任務處於就緒狀態。

     任務的基本信息:

  • CPU的PC寄存器:任務當前執行的位置;

  • CPU的通用寄存器:任務當前執行涉及的臨時數據;

  • CPU的狀態寄存器:存儲當前CPU的狀態。

     任務級任務切換:從一個任務直接切換至另一個任務,不涉及CPU狀態的切換,OS_TASK_SW()既保存當前任務上下文,又恢復新任務上下文。

     過程:OS_Sched() -> OS_SchedNew() -> OS_TASK_SW()


2010051114524015.jpg


(4) 中斷級任務調度

2010051114534579.jpg


2010051114544972.jpg


2010051114553389.jpg


     中斷級任務切換:在中斷處理完成後,通過OSIntExit()判斷是否有更高優先級就緒任務。如果有,調用OSIntCtxSW()恢復新任務上下文。注意:在中斷處理中,已經保存了被中斷任務的上下文,所以這裏僅僅恢復。

     過程:OSIntExt() –> OSIntEnter() -> ISR –> OSIntExit() -> OSIntCtxSW()

(5) 調度器上鎖與解鎖

     uC/OS-II提供調度器鎖定功能,在鎖定期間不能進行任務調度。uC/OS-II使用全局變量OSLockNesting標識是否鎖定了任務調度器。

  • OS_EXT INT8U OSLockNesting;

  • void OSSchedLock(void);

  • void OSSchedUnlock(void);

(6) 中斷管理函數

     在中斷處理中,不允許進行任務管理、事件管理及任務調度等操作。uC/OS-II通過全局變量OSIntNesting標識當前是否處於中斷狀態。在所有任務及事件管理的程序中,都有對OSIntNesting進行判斷的語句。

  • void OSIntEnter(void);

  • void OSIntExit(void);

2010051114575875.jpg

(7) 中斷相關問題

  • OS_ENTER_CRITICAL()

  • OS_EXIT_CRITICAL()

   關中斷使得uC/OS-II能夠同時避免有其他任務或中斷服務進入臨界代碼段。調用uC/OS-II功能函數時,中斷總應當是開着的。

  • uC/OS-II如何禁止調度?

  • 在中斷中允許調度嗎?爲什麼?

  • uC/OS-II如何屏蔽中斷?

2. uC/OS-II系統啓動

     uC/OS-II首先調用OSInit()進行初始化,然後創建任務(此時還未啓動系統,僅僅爲其分配資源),然後調用OSStart()啓動系統,將CPU控制權交給uC/OS-II,OS根據任務優先級選擇由哪個任務開始執行,或創建新的任務。

(1) 初始化函數OSInit()

     OSInit()主要完成初始化操作,包括初始化全局變量(在OS_InitMisc()中)、任務就緒表、TCB、ECB、FCB、內存單元、消息隊列,並創建空閒任務。如果有必要,創建統計任務。

  • OS_InitMisc();                  //初始化部分全局變量

  • OS_InitRdyList();             //初始化任務就緒表

  • OS_InitTCBList();            //初始化空閒TCB鏈表

  • OS_InitEventList();          //初始化ECB鏈表

  • OS_FlagInit();                  //初始化事件組標誌結構

  • OS_MemInit();                 //初始化內存管理

  • OS_QInit();                      //初始化消息隊列

  • OS_InitTaskIdle();            //創建空閒任務

  • OS_InitTaskStat();            //創建統計任務

2010051115002566.jpg


     uC/OS-II初始化了5個空的數據結構緩衝區,每個緩衝區都是單向鏈表,允許uC/OS-II從緩衝區中迅速取得或釋放一個緩衝區中的元素。 2010051115024586.jpg


    uC/OS-II調用OSInit()後的變量與數據結構如下圖所示:


2010051116014561.jpg

(2) 啓動函數OSStart()

     OSStart()在一切準備就緒且需要首先創建的任務都被創建後,啓動uC/OS-II。它從就緒表中查找最高優先級就緒任務,並恢復其上下文開始執行。

     過程:OSStart() -> OS_SchedNew() -> OSStartHighRdy()

     問題:任務第一次被調用時,哪來的上下文供其恢復呢?創建任務時,調用了OSTaskStkInit()初始化任務堆棧,可此函數中沒有涉及任務的上下文呀?

     uC/OS-II調用OSStart()後的變量和數據結構如下圖所示:

2010051116040057.jpg

(3) 統計任務OSTaskStat

     OSTaskStat用於計算CPU利用率。設置OS_CFG.H中的OS_TASK_STAT_EN爲1,創建統計任務,在系統啓動後一直處於就緒狀態。剛開始時,空閒任務運行1S,爲計算CPU利用率提供一個基準值,並保存在統計任務的堆棧中,這個值不會改變除非重新啓動CPU。此後空閒任每次被其它任務搶去CPU時,它裏面的計數器就會直接記錄下CPU空閒的時間。

3. uC/OS-II系統時鐘

     任何實時系統的時鐘硬件設備每隔一段時間(一個系統tick)產生一個硬件中斷,OS接收到該中斷後,更新時間計數器,更新所有對時鐘依賴的程序代碼,從而維持系統有序穩定的運行。

     主要包含在C源文件OS_TIME.C中。

  • #define OS_TICKS_PER_SEC 100     //系統時鐘中斷間隔

  • OS_EXT volatile INT32U OSTime;      //系統運行的時間值


  • void OSTimeTick(void);                         //時鐘中斷服務程序

  • void OSTimeDly(INT16U ticks);           //延遲指定時鐘節拍

  • INT8U OSTimeDlyHMSM(…);             //延遲指定時間長度

  • INT8U OSTimeDlyResume(prio);  //恢復等待(時延/阻塞)任務

  • INT32U OSTimeGet(void);                   //讀取當前時間

  • void OSTimeSet(INT32U ticks);            //設置當前時間

4. uC/OS-II事件管理

(1)   事件控制塊

  • INT8U OSEventType;                           //事件類型

  • void *OSEventPtr;                                //指向MBox或Queue

  • INT16U OSEventCnt;                           //信號量計數器(注:Mutex)

  • INT8U OSEventGrp;                            //事件等待組標誌

  • INT8U OSEventTbl[];                          //時間任務等待表

  • INT8U OSEventName[];                      //時間名稱

(2) ECB管理機制

  • OS_EXT OS_EVENT *OSEventFreeList;   //空閒ECB鏈表指針

  • OS_EXT OS_EVENT OSEventTbl[];       //ECB結構體數組

(3) ECB管理函數

  • OS_InitEventList():初始化ECB;

  • OS_EventWaitListInit():在創建事件時調用,初始化ECB任務等待表;

  • OS_EventTaskRdy():在事件發生時調用,修改此事件中最高優先級任務的TCB成員變量,在任務就緒表中添加此任務,將相應信息傳遞給該任務TCB,並將此任務從事件的任務等代表中刪除;

  • OS_EventTaskWait():在申請資源失敗而暫停當前任務時被調用,將任務從任務就緒表中刪除,並添加到事件的任務等代表中;

  • OS_EventTO():在事件等待超時時調用,將此任務從事件的任務等代表中刪除,並修改該任務的TCB成員變量;


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