UC/OS-II功能介紹、要點記錄
通過不斷地學習和實驗UC/OS-II,終於在五一前在ARM平臺上實現了多任務的創建、調度運行、掛起,任務間信號量、互斥型信號量、郵箱、消息隊列和事件標識組方式下的通信機制,接下來則繼續學習UC/OS-II的移植方法,在此趁五一假期之際,我將UC/OS-II的特點用自己通俗的語言介紹一下,希望能讓大家在沒接觸UC/OS-II的情況下大概明白UC/OS-II的用處和特點,共同學習和進步,爲學習UC/OS-II的同學提供有用的資料。另外,如有錯誤和不當之處,還請指正和發表您的心得體會。
謝謝!
一.有關UC/OS-II實時系統
1)UC/OS-II的名稱
嵌入式實時操作系統UC/OS-II中文意爲“微控制器操作系統版本2”,
它是一個完整的、可移植、固化、裁剪的佔先式可剝奪型實時多任務內核。
2)UC/OS-II的用處
UC/OS-II多任務管理意在使多個需要處理器處理的事務在同時間段內同
步完成,通過充分利用處理器的處理資源,使處理器的處理效率到達更大
限度,UC/OS-II最多可實現同步管理64個任務
3)UC/OS-II多任務管理思想
用日常的例子打比方,比如處理器要完成一段程序就好比我們將做一頓飯,傳統的方法是流水線式(單線程)
可見總用時位各過程的總和,我們可以想象得出這樣的做法是很浪費時間的,我們任何人都不會這麼去做,採用UC/OS-II多任務管理思想則可以將此事務按照另一種方式完成,如圖Pic1.2中的多線程方式,由圖比較可以看出,整個事務在t5時刻完成,當菜炒好時飯也做好不久,這樣的方法使總用時減少了,分析原因,可以知道是我們在等飯做好的時候沒有光等,而是開始洗菜,炒菜去了。同樣的方式下,如果在等任何一件事務完成的過程中去做其他事情我們的做事效率是不是更快了呢,答案當然是肯定的。UC/OS-II支持最多同時64個任務的管理。
二.UC/OS-II實時系統中有關概念介紹
1)任務 也叫線程,是一個簡單的無限循環的程序,它是由一個大的
事務分割成多個小事務塊後得來的,這些小事務塊在時間上不衝 突,即可以同時進行,而在運行所有小事務塊過程中,依然和運行 完整大事務的效果相同。UC/OS-II中每個任務有自己的特定信息塊 (TCB)和獨有的優先級級別,處理器通過這些信息管理這些任務, 在多個任務上調度運行、掛起任務等操作。
需要注意的是因爲處理器在管理多任務過程中,任何時刻都有
且只能有一個任務在運行,故其它任務就出現了不同的狀態,在
UC/OS-II中任務有五種狀態,如下:
1.睡眠狀態任務 2.就緒狀態任務
3.運行狀態任務 4.等待狀態任務 5.被中斷狀態任務
任務還可以按圖Pic1.2理解,其中的任務就包括
Task_1: 洗米 Task_2 :燒飯 Task_3: 洗菜 Task_4: 炒菜
狀態 |
t0~t1 |
t1~t2 |
t2~t3 |
t3~t4 |
t4~t5 |
Task_1 |
運行態 |
·睡眠態 |
·睡眠態 |
·睡眠態 |
·睡眠態 |
Task_2 |
·睡眠態 |
運行態 |
等待態 |
等待態 |
·睡眠態 |
Task_3 |
·睡眠態 |
·睡眠態 |
運行態 |
·睡眠態 |
·睡眠態 |
Task_4 |
·睡眠態 |
·睡眠態 |
·睡眠態 |
運行態 |
運行態 |
表中加“·”符號的表示任務最可能處於的狀態
2)調度 (schedulers),它是內核的主要職責,就是決定該輪到那個任
務運行了,UC/OS-II依據任務的優先級別執行調度工作
任務的調度(切換)過程
因爲uc/os-ii總是運行進入就緒狀態的最高優先級的任務。所以, 確定哪個任務優先級最高,下面該哪個任務運行,這個工作就是由 調度器(scheduler)來完成的。
UC/OS-II中有產生調度有兩種方式,任務級的調度和中斷級調度。任務級的調度是由函數OSSched()完成的,而中斷級的調度是由函數OSIntExt()完成。對於OSSched(),它內部調用的是OS_TASK_SW()完成實際的調度(人爲模仿一次中斷);OSIntExt()內部調用的是OSCtxSw()實現調度。
任務切換其實很簡單,由如下2步完成:(1)將被掛起任務的處 理器寄存器推入自己的任務堆棧。(2)然後將進入就緒狀態的最高 優先級的任務的寄存器值從堆棧中恢復到寄存器中。
圖Pic1.2中t2時刻即產生任務級調度過程
3)任務控制塊(OS_TBC) 任務狀態存放於OS-TBC數據結構中;保存了任 務的狀態、優先級、斷點數據等,當任務得到CPU使用權後,任務 控制塊能確保任務能從被中斷點那一點絲毫不差地繼續執行。
每個任務都有自己的OS_TBC控制塊,OS_TBC的數量由 OS_MAX_TASK決定,任務數量少,當然OS_TBC佔用RAM的空 間就少。
任務一旦建立,任務控制塊OS_TBC將被賦值。
所有的任務控制塊OS_TBC都是放在任務控制塊列表數組 OSTCBTbl[]中。在ucos-ii初始化時,所有任務控制塊OS_TBC都被 鏈表連接成單向空任務鏈表。
注意:UC/OS-II每創建一個任務時就在RAM中建立一個相應的OS_TBC
三.UC/OS-II要點記錄
1.中斷服務所做的事應儘量少做,應把大部分工作留給任務去做。
2.OSIntExit()和OSSched()有點相似,但OSIntExit()使中斷nestiing減1,而重新調度的條件是:中斷nesting和鎖定nesting計算器(OSLockNesting)均爲0。
3.OS_TASK_SW()和OSCtxSw()的區別:後者使用於中斷服務程序中,中斷返回已經對cpu做了保存工作。而前者需要採用模仿軟中斷返回指令實現cpu保存。
4.時鐘節拍
(1)UC/OS-II需要提供週期性的信號源,用於實現時間延遲和確認超時。 節拍率應爲10~100Hz,時鐘節拍率越高,系統額外的負荷就越重。
(2)系統多任務啓動時候(調用OSStart())之後,第一件初始化事情就是 初始化定時中斷。
(3)UC/OS-II中的時鐘節拍服務是通過在中斷服務子程序(OSTickISR()) 中調用OSTimeTick()實現的。OSTimeTick()跟蹤所以任務的定時器和超 時時限。 時鐘節拍中斷服從一般中斷規則(含任務調度判斷)。
5.OSTCBList指向任務控制塊鏈表的開始,而且它總是指向最新建立的任務。
6.非常好的一個圖示:OSInt()之後的變量和數據結構。請參閱P112
7.啓動多任務時,執行OSStart()函數,OSStart()先從任務就緒表中找出用戶建立的優先級最高的任務的任務控制塊,而後調用了OSStartHighRdy(),此函數實質上是將任務堆棧中的保存內容返回到cpu寄存器中,然後執行一條中斷返回指令。
【信號量專題】
1. 信號量
(1)uc/os-ii的信號量是由兩個部分組成:一部分是16位的無符號整型信號量的計數值(0~65535);另一部分是等待該信號量的任務組成的等待任務表。(另外參考事件控制塊ECB)
(2)信號量可以是2值的變量(稱爲二值信號量),也可以是計數式的。根據信號量的值,內核跟蹤那些等待信號量的任務。
(3)建立信號量的工作必須在任務級代碼中或者多任務啓動之前完成。
(4)任務要得到信號量的問題。
想得到信號量的任務,必須執行等待操作(pend)。如果信號量有效(非0),則信號量減1,任務得以繼續運行。如果信號量無效,則等待信號量的任務就被列入等待信號量的任務表中。多少內核允許定義等待超時,當等待時間超過了設定值,該信號量還是無效,則等待該信號量的任務進入就緒態,準備運行,並返回出錯代碼(等待超時錯誤)。
(5)任務對信號量的釋放問題。
任務執行發信號(post)操作來釋放信號量。如果沒有任務等待信號量,那麼信號量的值僅是簡單的加1(則信號量大於0,有效);如果有任務等待該信號量,那麼就會有另一個任務進入就緒態,信號量的值就不加1。
之後,這個釋放的信號量給那個等待中的任務,要看內核如何調度的。收到信號量的任務可能如下:
◆等待任務中,優先級最高的;(uc/os-ii僅支持這種方式)。
◆等待任務中所有等待該信號量的任務
2. 信號量的有效與無效問題
信號量有效:信號量的計算器非0(.OSEventCnt!=0)。信號量有效表示任務對 資源可用。
信號量無效:信號量的計算器爲0。信號量無效表示任務對目前資源不可用,需 要等待其他另一個任務(或者中斷服務子程序)發出該信號量
3. 信號量的值(.OSEventCnt)大小表示什麼?
①二值信號量,表示任務可以獨佔共享資源。
②計數式信號量,用於某資源可同時爲N個任務所用。
4. 信號量有關的三個重要函數分析
◆OSSemCreate() 創建一個信號量 (注:由任務或啓動代碼操作)
創建工作必須在任務級代碼中或者多任務啓動之前完成。功能只要是先獲取一個事件控制塊ECB,寫入一些參數。其中調用了OS_EeventWaitListInt()函數,對事件控制塊的等待任務列表進行初始化。完成初始化工作後,返回一個該信號量的句柄(Handle)。
◆OSSemPend() 等待一個信號量 (注:只能由任務操作)
本函數應用於任務試圖獲得共享資源的使用權、任務需要與其他任務或中斷同步及任務需要等待特定事件發生的場合。
如果任務Task_A調用OSSemPend(),且信號量的值有效(非0),那麼OSSemPend()遞減信號量計數器(.OSEventCnt),並返回該值。換句話說,Task_A獲取到共享資源的使用權了,之後就執行該資源。
如果如果任務Task_A調用OSSemPend(),信號量無效(爲0),那麼OSSemPend()調用OS_EventTaskWait()函數,把Task_A放入等待列表中。(等待到什麼時候呢?要看OSSemPost()(或者等待超時情況),由它釋放信號量並檢查任務執行權,見下資料)
◆OSSemPost() 發出(釋放)一個信號量 (注:由任務或中斷操作)
本函數其中調用OS_EventTaskRdy()函數,把優先級最高的任務Task_A(在這假如是Task_A,另外假設當前調用OSSemPost()的任務是Task_B)從等待任務列表中去除,並使它進入就緒態。然後調用OSSched()進行任務調度。如果Task_A是當前就緒態中優先級最高的任務,則內核執行Task_A;否則,OSSched()直接返回,Task_B繼續執行。
【互斥型信號量專題】
1.互斥型信號量(mutex)
互斥型信號量具備uc/os-ii信號量的所有機制,但還具有其他一些特性。
任務可利用互斥型信號量來實現對共享資源的獨佔處理。
Mutex是二值信號量,1表示資源是可以使用的。
2.關於優先級反轉(PIP)
下面概述優先級反轉原理:
假設有三個任務,分別命名爲A,B,C;A的優先級最高,C的優先級最低。任務A和任務B處於掛起狀態(請注意這條件),等待某一事件的發生,任務C正在運行。當任務C等待到共享資源(命名爲S1)並使用後,如果任務A等待得事件到來之後,由於A的優先級最高,所以就會剝奪任務C的CPU使用權。運行過程中,任務A也要使用資源S1,但S1的信號量還被任務C佔用着,所有任務A只能進入掛起狀態,等待任務C對S1的信號量的釋放。此時任務C得以繼續運行。
同理,任務B的事件到來後,會剝奪任務C的CPU使用權。任務B把事情搞定以後,把CPU使用權歸還給任務B。任務B又得以繼續運行,任務B認真處理完畢資源S1後,終於可以釋放S1的信號量。而處於等待該信號量的任務A馬上得到信號量並開始處理共享資源S1。
綜述上面情況,任務C和任務A的優先級發生了反轉。而互斥型信號量就是具有解決優先級反轉問題的特性。
3.UC/OS-II的互斥型信號量由三個部分組成:
◆一個標誌,指示mutex是否可以使用(0或1)
◆一個優先級,準備一旦高優先級的任務需要這個mutex,賦予給佔有mutex的任務。
◆一個等待該mutex的任務列表。