1. 程式人生 > >uc/OS III任務的理解

uc/OS III任務的理解

任務的概念

在實際應用中一般是將工作拆分為多個任務的,並且每個任務都是可靠的。在使用uC/OS就可以很好的解決這個問題,任務又叫執行緒,在對於單個CPU來說,在任何時刻,都是隻能有有一個任務被執行。

uC/OS-III 支援多工且對任務數量沒有限制,任務數僅取決於處理器記憶體的大小(RAM)。多工排程是任務間佔用CPU 的過程。CPU 有根據演算法切換任務。多工排程讓人感覺到是有多個CPU在執行,並最大化利用CPU。多工呼叫有助於模組化應用,是最重要的功能之一,能幫助程式設計師管理複雜的實時性應用。它也使程式易於設計和維護。
任務用於監控輸入、更新輸出、計算、迴圈控制、顯示、讀按鈕和鍵盤、與其它系統交流等。有些應用中可能只包含少數任務,有些應用中也可能包含上百個任務。任務數多並不意味這設計有多好或者有多有效,這依賴於應用的需要。任務的功能也要根據應用設計。一個任務可能只需要工作幾微秒,然而有些任務可能就需要工作幾十毫秒了。
在大多數嵌入式系統中,任務通常是無限迴圈的。任務不能像C 函式那樣,它是不能return 的。

當任務第一次執行時,會傳入一個變數"p_arg"。這是一個指向void的指標。用於變數的地址、結構體地址、或者函式的地址等。只執行一次的任務結束時必須通過呼叫OSTaskDel()刪除自己。這樣可以使系統中的任務數減少。在任務體中,任務可以呼叫uC/OS-III提供的大部分函式幫助完成其所需要完成的功能。

uC/OS-III 需要通過呼叫函式OSTaskCreate() 建立任務。OSTaskCreate()函式的原型如下所示


關於建立任務的詳細引數,前面也有說過了建立一個任務時必須為其分配一個TCB(Task Control Block,會存放任務優先順序、任務名、任務狀態、內部訊息佇列、內部訊號量等),一個堆疊,一個優先順序和其它一些引數。

接下來, 會呼叫一些定義在OS_CPU_C.C 中的函式如OSTaskCreateHook(),TCB 中有指標指向這個函式,用於擴充套件應用。例如,可以列印最新建立的TCB 內容到某終端(利於除錯)。然後該任務被放到就緒列表(詳見第六章"就緒列表")。uC/OS-III呼叫排程器,並切換到優先順序最高的任務。

 一.任務優先順序的設定

有些時候任務的優先順序是顯而易見的,多數系統中,不是所有的任務都是重要的,不重要的任務應該被設定為低優先順序。

二.堆疊空間大小的確定

堆疊的大小取決於該任務的需求。設定堆疊大小時,就需要考慮:所有可能被堆疊呼叫的函式及其函式的巢狀層數,相關區域性變數的大小,中斷服務程式所需要的空間。另外,堆疊還需要存入CPU暫存器,如果處理浮點數單元FPU暫存器的話就還需要存入FPU暫存器。嵌入式系統的潛規則,避免寫遞迴函式
。在產品的開發和測試階段,通常在執行時用偵錯程式測量堆疊的使用情況。

三.檢測任務堆疊的溢位

比較複雜,後文再寫,因為不是很懂

四.任務管理服務

uC/OS-III 提供了很多與任務相關的函式。這些函式可以在OS_TASK.C 中找到,它們都以以OSTask***()形式命名的。如下
分組函式
普通的OSTaskCreate():建立人物
OSTaskDel():刪除任務
OSTaskChangePrio():修改任務優先順序
OSTaskRegSet():任務暫存器設定
OSTaskRegGet():獲取當前暫存器的值
OSTaskSuspend():取消任務
OSTaskResume():恢復任務
OSTaskTimeQuantaSet():更改任務時間片
OS_TaskInit():任務初始化
OS_TaskInitTCB():初始化堆疊的預設值
標記任務OSTaskSemPend():等待接收任務訊號量
OSTaskSemPost():表示等待任務的訊號
OSTaskSemPendAbort():終止等待任務訊號
OSTaskSemSet():設定清除訊號計數器
OSTaskStkChk():被用來檢測堆疊後剩餘記憶體量
給任務傳送訊息OSTaskQPend():等待接收一個訊息
OSTaskQPost():傳送資訊給任務
OSTaskQPendAbort():中止等待訊息
OSTaskQFlush():重新整理內部任務訊息佇列
OS_TaskResume():恢復一個已經移除的任務
在原始碼中,針對每個函式都有很詳細的解說是什麼,該怎麼用,這邊不再說明

五.內部任務管理

1任務狀態

從使用者的觀點來看,任務可以是有5 種狀態,如下。展示了任務狀態間的轉換關係。{休眠狀態,就緒狀態,執行狀態,掛起狀態,中斷狀態}


(1)處於休眠狀態的任務駐留於記憶體但未被uC/OS-III 使能。通過呼叫OSTaskCreate()函式uC/OS-III 建立任務。任務程式碼是存在於ROM 的。但需要用OSTaskCreate()函式通知uC/OS-III 關於任務的相關資訊。如果任務的使命完成了,就要呼叫OSTaskDel()刪除該任務。OSTaskDel()實際上不是刪除任務的程式碼,只是讓任務不再具有使用CPU 的資格而已。
(2)就緒狀態的任務根據優先順序有序地排列於就緒列表中。就緒列表中對就緒任務的個數沒有限制。
(3)正在執行的任務被置為執行狀態。在單CPU 中,任何時刻只能有一個任務被執行。當應用程式呼叫OSStart() 或者呼叫OSIntExit() 或者呼叫OS_TASK_SW()時uC/OS-III 從就緒佇列中選擇優先順序最高的任務去執行。正如前面所提到的,有些時候任務必須等待某些事件發生,若事件還未發生時,任務就會被設定為掛起狀態。(4)掛起狀態的任務被放置在掛起列表中以表明任務在等待某些事件的發生。等待的時候,任務是不會佔用CPU 的。事件發生時,該任務會被放到就緒佇列中。在這種情況下,正在執行的任務可能會被搶佔(被放回就緒列表),並由uC/OS-III 選擇優先順序最高的任務去執行。換句話說,如果新的任務優先順序最高,那麼它就會被立即執行。請注意,呼叫OSTaskSuspend()會任務無條件地停止執行。有些時候呼叫OSTaskSuspend()不是為了等待某個事件的發生,而是等待另一個任務呼叫OSTaskResume()函式恢復這個任務。(5)若中斷髮生,中斷會掛起正在執行的任務並去處理ISR。ISR中可能有某些任務等待的事件。一般來說,中斷用來通知任務某些事件的發生,並讓在任務級處理實際的響應操作。ISR 程式越短越好,實際響應中斷的操作應該被設定在任務級以便能讓uC/OS-III 管理這些操作。ISR 中只允許呼叫一些提交函式(OSFlagPost(),OSQPost()OSSemPost() , OSTaskQPost() , OSTaskSemPost()) , 除了OSMutexPost()。因為mutex 只允許在任務級被修改。大多數處理器支援中斷巢狀。然而,如果管理不當,中斷
巢狀是很容易引起堆疊溢位的。

uC/OS-III 一直追蹤著任務的狀態如下圖。事實上,這些都是以一個變數的形式儲存在每個任務的TCB 中。圖小括號中的數值表示著任務的狀態,每個任務都可以有8 種狀態。

(0)狀態0 表示任務已經就緒。每個任務在被執行之前都必須處於就緒狀態。
(1)任務可以通過呼叫OSTimeDly()或者OSTimeDlyHMSM()等待期滿。當期滿或者延時刪除時(通過呼叫OSTimeDlyResume()),任務會轉為就緒狀態。//////這是一天的程序,但為了章節比較好看,只能列為一個章節
(2)任務可以通過呼叫掛起函式(OSFlagPend(),OSMutexPend(),OSQPend,OSSemPend,OSTaskQPend(),OSTaskSemPend())等待某事件的發生。當事件發生時、該任務被刪除、或者被另一個任務取消等待時,等待停止。
(3)如前面所說,任務可以等待事件發生。但任務也可以被設定等待多少時間。如果在這段時間內事件沒有發生,任務也會被設為就緒狀態,並通知這個任務是等待超時而被掛起的。{掛起函式都有一個關於函式執行結果錯誤代號,可以檢視這個代號知道任務是因何被就緒的}
(4) 任務暫停自己或者被其他任務暫停( 通過呼叫OSTaskSuspend())。暫停中的任務只能通過呼叫OSTaskResume()被恢復。
(5)一個延時中的任務也可以被其它任務設定為停止。在這種情況下,效果會被疊加。換句話說,延時需被執行、停止狀態需被解除。該任務才會被執行。
(6)一個掛起狀態中的任務也可能被其它任務設定為停止。同樣的,效果會被疊加。事件發生且停止狀態被移除後,任務才會被執行。
(7)任務可以等待事件的發生,但可以給它設定一個期限。同樣的,它也可能被設為停止,效果是疊加的。除非移除停止狀態並事件發生或等待事件超時,任務才會被執行。

2 任務控制塊 TCB

任務控制塊是被uC/OS-III 用於維護任務的一個結構體。每個任務都必須有自己的TCB。uC/OS-III 在RAM 中分配TCB。當呼叫uC/OS-III 提供的與任務相關的函式(以OSTask???()形式命名)時,任務的TCB 地址需會被提供給該函式。TCB 的結構定義於OS.H 中,由於結構體太長,這邊不做截圖了,可以參見OS.H中struct os_tcb {}結構體,裡面有相對詳細的介紹。TCB 中的一些變數可以根據具體應用進行裁剪。使用者程式不應該訪問這些變數(尤其不能更改它們)。換句話說,TCB 中的變數只能被uC/OS-III 訪問
這邊要是解釋的話,需要太長的欄位,實在是意義不大,原始碼OS.H 檔案寫的還比較好理解。