uC OS II 初級程式設計師指南

2021-04-30 19:02:22 字數 4297 閱讀 1435

uc/os-ii 初級程式設計師指南

(一) uc/os-ii 簡介

uc/os-ii是一種基於優先順序的可搶先的硬實時核心。自從92年發布以來,在世界各地都獲得了廣泛的應用,它是一種專門為嵌入式裝置設計的核心,目前已經被移植到40多種不同結構的cpu上,執行在從8位到64位的各種系統之上。尤其值得一提的是,該系統自從2.51版本之後,就通過了美國faa認證,可以執行在諸如太空飛行器等對安全要求極為苛刻的系統之上。鑑於uc/os-ii可以免費獲得**,對於嵌入式rtos而言,選擇uc/os無疑是最經濟的選擇。

(二) uc/os-ii 應用程式基本結構

應用uc/os-ii,自然要為它開發應用程式,下面論述基於uc/os-ii的應用程式的基本結構以及注意事項。

每乙個uc/os-ii應用至少要有乙個任務。而每乙個任務必須被寫成無限迴圈的形式。以下是推薦的結構:

void task ( void* pdata )

}以上就是基本結構,至於為什麼要寫成無限迴圈的形式呢?那是因為系統會為每乙個任務保留乙個堆疊空間,由系統在任務切換的時候換恢復上下文,並執行一條reti 指令返回。如果允許任務執行到最後乙個花括號(那一般都意味著一條ret指令)的話,很可能會破壞系統堆疊空間從而使應用程式的執行不確定。換句話說,就是「跑飛」了。所以,每乙個任務必須被寫成無限迴圈的形式。程式設計師一定要相信,自己的任務是會放棄cpu使用權的,而不管是系統強制(通過isr)還是主動放棄(通過呼叫os api)。

現在來談論上面程式中的inittimer()函式,這個函式應該由系統提供,程式設計師有義務在優先順序最高的任務內呼叫它而且不能在for迴圈內呼叫。注意,這個函式是和所使用的cpu相關的,每種系統都有自己的timer初始化程式。在uc/os-ii的幫助手冊內,作者特地強調絕對不能在osinit()或者osstart()內呼叫timer初始化程式,那會破壞系統的可移植性同時帶來效能上的損失。所以,乙個折中的辦法就是象上面這樣,在優先順序最高的程式內呼叫,這樣可以保證當osstart()呼叫系統內部函式osstarthighrdy()開始多工後,首先執行的就是timer初始化程式。或者專門開乙個優先順序最高的任務,只做一件事情,那就是執行timer初始化,之後通過呼叫ostasksuspend()將自己掛起來,永遠不再執行。不過這樣會浪費乙個tcb空間。對於那些ram吃緊的系統來說,還是不用為好。

(三) 一些重要的uc/os-ii api介紹

任何乙個作業系統都會提供大量的api供程式設計師使用,uc/os-ii也不例外。由於uc/os-ii面向的是嵌入式開發,並不要求大而全,所以核心提供的api也就大多和多工息息相關。主要的有以下幾類:

1)任務類

2)訊息類

3)同步類

4)時間類

5)臨界區與事件類

我個人認為對於初級程式設計師而言,任務類和時間類是必須要首先掌握的兩種型別的api。下面我就來介紹比較重要的:

1) ostaskcreate函式

這個函式應該至少再main函式內呼叫一次,在osinit函式呼叫之後呼叫。作用就是建立乙個任務。目前有四個引數,分別是任務的入口位址,任務的引數,任務堆疊的首位址和任務的優先順序。呼叫本函式後,系統會首先從tcb空閒列表內申請乙個空的tcb指標,然後將會根據使用者給出引數初始化任務堆疊,並在內部的任務就緒表內標記該任務為就緒狀態。最後返回,這樣乙個任務就建立成功了。

2) ostasksuspend函式

這個函式很簡單,一看名字就該明白它的作用,它可以將指定的任務掛起。如果掛起的是當前任務的話,那麼還會引發系統執行任務切換先導函式osshed來進行一次任務切換。這個函式只有乙個引數,那就是指定任務的優先順序。那為什麼是優先順序呢?事實上在系統內部,優先順序除了表示乙個任務執行的先後次序外,還起著分別每乙個任務的作用,換句話說,優先順序也就是任務的id。所以uc/os-ii不允許出現相同優先順序的任務。

3) ostaskresume函式

這個函式和上面的函式正好相反,它用於將指定的已經掛起的函式恢復成就緒狀態。如果恢復任務的優先順序高於當前任務,那麼還為引發一次任務切換。其引數類似ostasksuspend函式,為指定任務的優先順序。需要特別說明是,本函式並不要求和ostasksuspend函式成對使用。

4) os_enter_critical巨集

很多人都以為它是個函式,其實不然,仔細分析一下os_cpu.h檔案,它和下面馬上要談到的os_exit_critical都是巨集。他們都是涉及特定cpu的實現。一般都被替換為一條或者幾條嵌入式彙編**。由於系統希望向上層程式設計師隱藏內部實現,故而一般都宣稱執行此條指令後系統進入臨界區。其實,它就是關個中斷而已。這樣,只要任務不主動放棄cpu使用權,別的任務就沒有占用cpu的機會了,相對這個任務而言,它就是獨佔了。所以說進入臨界區了。這個巨集能少用還是少用,因為它會破壞系統的一些服務,尤其是時間服務。並使系統對外界響應效能降低。

5) os_exit_critical巨集

這個是和上面介紹的巨集配套使用另乙個巨集,它在系統手冊裡的說明是退出臨界區。其實它就是重新開中斷。需要注意的是,它必須和上面的巨集成對出現,否則會帶來意想不到的後果。最壞的情況下,系統會崩潰。我們推薦程式設計師們盡量少使用這兩個巨集呼叫,因為他們的確會破壞系統的多工效能。

6) ostimedly函式

這應該程式設計師們呼叫最多的乙個函式了,這個函式完成功能很簡單,就是先掛起當起當前任務,然後進行任務切換,在指定的時間到來之後,將當前任務恢復為就緒狀態,但是並不一定執行,如果恢復後是優先順序最高就緒任務的話,那麼執行之。簡單點說,就是可以任務延時一定時間後再次執行它,或者說,暫時放棄cpu的使用權。乙個任務可以不顯式的呼叫這些可以導致放棄cpu使用權的api,但那樣多工效能會大大降低,因為此時僅僅依靠時鐘機制在進行任務切換。乙個好的任務應該在完成一些操作主動放棄使用權,好東西要大家分享嘛!

(四) uc/os-ii 多工實現機制分析

前面已經說過,uc/os-ii是一種基於優先順序的可搶先的多工核心。那麼,它的多工機制到底如何實現的呢?了解這些原理,可以幫助我們寫出更加健壯的**來。由於我們面向的初級程式設計師,本文不打算寫成又一篇uc/os-ii的原始碼分析,那樣的文章太多了,本文打算從實現原理的角度**這個問題。

首先我們來看看為什麼多工機制可以實現?其實在單一cpu的情況下,是不存在真正的多工機制的,存在的只有不同的任務輪流使用cpu,所以本質上還是單任務的。但由於cpu執行速度非常快,加上任務切換十分頻繁並且切換的很快,所以我們感覺好像有很多任務同時在執行一樣。這就是所謂的多工機制。

由上面的描述,不難發現,要實現多工機制,那麼目標cpu必須具備一種在執行期更改pc的途徑,否則無法做到切換。不幸的使,直接設定pc指標,目前還沒有哪個cpu支援這樣的指令。但是一般cpu都允許通過類似jmp,call這樣的指令來間接的修改pc。我們的多工機制的實現也正是基於這個出發點。事實上,我們使用call指令或者軟中斷指令來修改pc,主要是軟中斷。但在一些cpu上,並不存在軟中斷這樣的概念,所以,我們在那些cpu上,使用幾條push指令加上一條call指令來模擬一次軟中斷的發生。

回想一下你在微機原理課程上學過的知識,當發生中斷的時候,cpu儲存當前的pc和狀態暫存器的值到堆疊裡,然後將pc設定為中斷服務程式的入口位址,再下來乙個機器週期,就可以去執行中斷服務程式了。執行完畢之後,一般都是執行一條reti指令,這條指令會把當前堆疊裡的值彈出恢復到狀態暫存器和pc裡。這樣,系統就會回到中斷以前的地方繼續執行了。那麼設想一下?如果再中斷的時候,人為的更改了堆疊裡的值,那會發生什麼?或者通過更改當前堆疊指標的值,又會發生什麼呢?如果更改是隨意的,那麼結果是無法預料的錯誤。因為我們無法確定機器下一條會執行些什麼指令,但是如果更改是計畫好的,按照一定規則的話,那麼我們就可以實現多工機制。事實上,這就是目前幾乎所有的os的核心部分。不過他們的實現不像這樣簡單罷了。

下面,我們來看看uc/os-ii再這方面是怎麼處理的。再uc/os-ii裡,每個任務都有乙個任務控制塊(task control block),這是乙個比較複雜的資料結構。在任務控制快的偏移為0的地方,儲存著乙個指標,它記錄了所屬任務的專用堆疊位址。事實上,再uc/os-ii內,每個任務都有自己的專用堆疊,彼此之間不能侵犯。這點要求程式設計師再他們的程式中保證。一般的做法是把他們申明成靜態陣列。而且要申明成os_stk型別。當任務有了自己的堆疊,那麼就可以將每乙個任務堆疊再那裡記錄到前面談到的任務控制快偏移為0的地方。以後每當發生任務切換,系統必然會先進入乙個中斷,這一般是通過軟中斷或者時鐘中斷實現。然後系統會先把當前任務的堆疊位址儲存起來,僅接著恢復要切換的任務的堆疊位址。由於哪個任務的堆疊裡一定也存的是位址(還記得我們前面說過的,每當發生任務切換,系統必然會先進入乙個中斷,而一旦中斷cpu就會把位址壓入堆疊),這樣,就達到了修改pc為下乙個任務的位址的目的。

以上就是uc/os-ii的多工實現機制,我們在這裡大費筆墨談論這個問題,是希望我們的程式設計師們可以善加利用這個機制,寫出更健壯,更富有效率的**來。

ucos 初級程式設計師指南

本文面向首次接觸uc os ii 的程式設計師,為他們介紹一下這個系統的一些基本特徵和程式設計上的注意事項,並介紹幾個值得了解的api。本文作者已經成功的將uc os ii移植到幾種不同cpu之上。包括epson s1c33和sunplus unsp?等,積累了豐富的經驗,現在願意和朋友們分享這些經...

初級程式設計師規劃

在程式設計世界有些概念是基礎。大多數技術面試的目的都是為了發現你的問題解決技能以及看看你是否了解那些概念,所以除了掌握一門程式語言之外,你應該熟悉一些在程式設計師軍火庫中必須的一些概念。要想為編碼面試做好成功準備,你應該對以下領域有自信 演算法與資料結構 計算機組織 作業系統 編碼系統設計 這是程式...

程式設計師健康指南

程式設計師常見的健康問題與相應的解決方法 身體 腦子 長時間壓力用腦 解決 1 釋放壓力,放鬆自己,調整心態 2 按時按壓太陽穴,敲鼓 3 每天乙個雞蛋,核桃,維c水果 4 早睡早起 眼睛 長時間看電腦導致酸,乾澀,疲憊 解決 1 按時眼保健操,眺望遠方 2 放綠色植物 3 調整螢幕亮度,色度,貼保...