天天看點

将uC/OS-II RTOS移植到STC8H單片機上

作者:楊為民

前 言

μC/OS-II由Micrium公司提供,是一個可移植、可固化的、可裁剪的、占先式多任務實時核心,它适用于多種微處理器,微控制器和數字處理晶片(已經移植到超過100種以上的微處理器應用中)。同時,該系統源代碼開放、整潔、一緻,注釋詳盡,适合系統開發。(摘自百度)

自uC/OS-II引入中國,20多年過去了,國内單片機技術不斷發展和單片機應用不斷普及,已經非昔日可比了。目前STC推出了一系列的供學生和程式員學習的實驗箱和開發闆,其中最精簡的一套組合的價格不超過30元:采用STC8H8K64U晶片的打狗棒開發闆+USB轉2序列槽兼燒錄器,是學習單片機的最佳入門硬體基礎。下圖是這套組合開發系統的實物照片:

将uC/OS-II RTOS移植到STC8H單片機上

使用RTOS程式設計是單片機開發的最高層次,而這套開發系統完全能夠滿足RTOS的入門和理論學習的硬體要求了。本文介紹如何移植uC/OS-II RTOS系統核心到這個STC8H系統上,使得學習者有一套可靠的原汁原味的uC/OS-II作為學習RTOS的出發點。

一、原汁原味的移植源

(1)uC/OS-II RTOS軟體本身的結構非常嚴謹全面,而由發明人親自撰寫的《嵌入式實時作業系統 uC/OS-II》一書也從理論到實作詳細地介紹了RTOS的方方面面。下圖為該書第2版(2006年3月第5次印刷)的封面:

将uC/OS-II RTOS移植到STC8H單片機上

該書附帶了CD光牒,以開源的形式給出了在PC機上運作的範例和全套軟體。自2001年該書翻譯到中國以來就成了許多高校研究所學生和程式員學習、研究和應用RTOS的最佳軟體和教材。

(2)移植RTOS有兩種類型,一種是将RTOS移植到CPU架構(指令集)完全不同的目标機上,比如從采用80x86架構 CPU的PC機版本移植到8051架構CPU的單片機上,另一種是在CPU架構(指令集)相同但是結構體系不一樣的單片機之間的移植。前一種移植的難度要大,對移植者的理論和實踐水準要求很高。後一種難度較低,隻要求移植者有該架構CPU的單片機的程式設計經驗就行,适合想學習RTOS的入門者。本文是後一種移植方法,為RTOS的初學者提供一個入門的單元教程。

(3)本文的uC/OS-II程式移植源來自陳是知編著的《uC/OS-II核心分析、移植與驅動程式開發》(人民郵電出版社,2007年)一書的CD光牒,下圖為該書封面:

将uC/OS-II RTOS移植到STC8H單片機上

(4)可能是作者成功地将uC/OS-II從PC機版本移植到了8051架構單片機上,該書是筆者所讀過的涉及uC/OS-II移植的書中最好的一本。

在該書中作者首先介紹了原來PC版的uC/OS-II範例,這些範例是運作在DOS環境下,用鍵盤控制在螢幕上顯示各個任務的資訊字元串,下圖是第一個範例的開始任務部分:

将uC/OS-II RTOS移植到STC8H單片機上
将uC/OS-II RTOS移植到STC8H單片機上

該書對uC/OS-II的範例和關鍵部分進行了逐行注釋,特别适合入門者學習。

然後介紹了Keil的Cx51語言和編譯器,最後給出了uC/OS-II核心的移植以及在8051單片機上編寫uC/OS-II驅動程式的例子。

(5)移植源。本文的移植源取自該書第6章範例,放在本文程式附件的“01_原始版本_第6章”目錄下。移植源有以下檔案:

将uC/OS-II RTOS移植到STC8H單片機上

其中那些2005年的檔案是該書沒有移植的原始檔案,2006年與2007年的檔案是當初作者進行第一種類移植時建立的檔案。

“252.Uv2”是移植項目檔案,打開該項目時可以看到下圖:

将uC/OS-II RTOS移植到STC8H單片機上

表明移植源的目标為“Winbond”公司的“W78E58B”單片機,這是一種早期的8051架構核心的單片機,其中在定時器0的中斷裡還需要每次都重新設定TH0和TL0。移植源項目使用Keil的C51編譯器。

二、移植uC/OS-II核心到STC8H單片機上的關鍵點

(6)建立新的空項目。Keil的項目檔案包含了許多單片機的具體編譯資訊,是以即使是同種架構CPU的單片機移植也要重新按照移植目标單片機建立項目,不建議用原來的項目進行改造。

新的空項目除了項目檔案外,還要包含“STARTUP.A51”啟動檔案。附件中的“02_uCOSII_STC8H_空項目”給出了新的空項目程式。

下面是建立新的空項目的幾個關鍵點:

1)選擇單片機型号為STC8H8K64U系列:

将uC/OS-II RTOS移植到STC8H單片機上

2)添加啟動檔案“STARTUP.A51”,選擇“是”:

将uC/OS-II RTOS移植到STC8H單片機上

3)建立好的空項目如下圖:

将uC/OS-II RTOS移植到STC8H單片機上

(7)建立ST8H單片機uC/OS-II的系統項目。建立好空項目後,下一步就是對項目進行必要的設定和導入有效的和完整的uC/OS-II全部源程式檔案。

1)設定RAM模式為大模式。記憶體選項見下圖:

将uC/OS-II RTOS移植到STC8H單片機上

由于在C51中預設的重入函數空間由上面頁籤的“Memory Model”決定。由于IDATA空間隻有256個位元組,同時還是系統堆棧空間,是以不适合作為多任務的重入函數空間,多任務的重入函數空間應該建立在XDATA中。

本次移植的目标單片機STC8H8K64U有8KB的片上XDATA,是以選擇将每個實時任務的堆棧空間建立XDATA空間,是以記憶體模式需要選擇大模式,每個需要重入的函數隻要加“reentrant”的關鍵字就行了。

2)複制要移植的uC/OS-II源檔案。源檔案包括以“.C”為字尾的C語言檔案、以“.H”為字尾的C語言頭檔案和以“.ASM”為字尾的彙編語言檔案。原項目中的“STARTUP.A51”、“C51BFPC.LIB”和“C51L.LIB”為老版本Keil編譯器的檔案,不需要複制到新項目中。

3)設定有内嵌彙編的C語言檔案的屬性選項。 “serial.c” 源檔案中的程式包含有内嵌彙編語言,是以該檔案的彙編語言選項要打鈎,如下圖所示:

将uC/OS-II RTOS移植到STC8H單片機上

(8)進行初次文法測試。新項目建立後,要先進行編譯,進行檔案的完整性和文法檢查。如果一切順利,可以編譯成功,生成HEX檔案。效果見下圖:

将uC/OS-II RTOS移植到STC8H單片機上

當然,把這時的HEX燒錄到STC8H單片機上是沒有反應的。

(9)硬體系統測試。

為了判斷将來在移植中出現的問題是軟體還是硬體的問題,對于移植目标開發闆首先要測試其硬體系統是否工作正常。下面是運作打狗棒開發闆的跑馬燈範例的視訊:

視訊加載中...

(10)簡化移植程式。本次移植的原程式中的多任務是以序列槽輸出字元串為例子的,筆者認為作為移植的範例,應該越簡單越直覺越好,是以采用LED燈閃爍作為多任務運作訓示。為此首先要從項目中删去兩個序列槽驅動檔案“serial.c”和“serial.h”,以及注釋掉多任務程式中有關序列槽的語句。

(11)STC8H單片機的初始化和靜态測試。移植目标STC8H單片機加電後所有的端口呈現高阻狀态,必須要初始化後才能驅動LED燈。是以就用前面LED跑馬燈範例中的程式來進行初始化和進行靜态測試(多任務排程沒有啟動)。初始化和測試程式如下:

将uC/OS-II RTOS移植到STC8H單片機上

靜态測試效果視訊如下:

視訊加載中...

(12)任務排程與動态測試。靜态測試成功後,就可以進行任務排程的動态測試。打狗棒的P0到P3四個端口都連接配接有下拉的LED燈,是以可以用不同端口的LED燈閃爍代表不同的任務。下圖是移植範例中三個任務的程式:

将uC/OS-II RTOS移植到STC8H單片機上

任務A是P0端口燈閃爍,任務B是P1端口燈閃爍,任務C是P2端口燈閃爍,下面是多任務開始運作的效果視訊:

視訊加載中...

(13)系統中斷設定與中斷服務程式。在uC/OS-II RTOS中使用一個定時器中斷來産生節拍,在每個節拍裡系統就會進行任務排程。本次移植的uC/OS-II系統中斷為50Hz,STC8H工作頻率為33.1776MHz,是以要修改定時器0的設定,具體見下圖:

将uC/OS-II RTOS移植到STC8H單片機上

同時,移植換了單片機,中斷服務程式也要做相應的調整,具體的見下圖:

将uC/OS-II RTOS移植到STC8H單片機上

原程式中的第423到426行應該注釋掉,STC8H系列定時器有自動重裝功能,不需要每次中斷重新設定。

另外第435行開始的序列槽中斷服務程式,也應該被注釋掉。

三、移植要點說明

經過上面步驟,uC/OS-II核心就算移植成功了,移植的結果見附件中的“09_uCOSII_LED燈閃爍_系統中斷”子目錄。

(14)移植中需要修改的系統檔案。uC/OS-II是一個精心設計的系統,核心源程式用C語言編寫,适合移植到各種目标機。

按照該系統的程式結構設計,在進行移植過程中需要移植者重寫或者修改三個系統檔案和兩個使用者檔案:“OS_CPU.H”、“OS_CPU.C”和“OS_CPU_A.ASM”,以及單片機引導程式“STARTUP.A51”和C語言主函數檔案“main”。

(15)OS_CPU.H檔案。這個頭檔案定義了臨界區保護的方法、堆棧的生長方向和任務切換函數。這個檔案筆者沒有對陳是知的程式做修改,直接保留了它:

将uC/OS-II RTOS移植到STC8H單片機上

(16)OS-CPU.C。這個檔案包含兩個主要内容,一個是對任務堆棧結構的定義和初始化,另一個是對系統中斷的初始化。

由于移植前後的單片機不同,筆者僅改變了對系統中斷定時器0的初始化函數,将主頻提高到33.1776MHz,具體見“(13)系統中斷設定…”一節。

(17)OS_CPU_A.ASM。在這個彙編語言檔案中,筆者僅删除了定時器0中斷服務程式中對定時器的再設定部分和序列槽中斷部分。

(18)單片機啟動檔案“STARTUP.A51”對于不同型号的單片機是不同的。筆者根據STC8H8K64型号單片機的規格修改了它。

(19)主函數“main”,筆者修改了系統硬體初始化程式和多任務的定義。

四、uC/OS-II程式設計架構

每個程式員的程式設計風格不同,通常在移植成功後,移植者會根據自己的了解給出一個程式設計架構,指導使用者進行實際應用。筆者也按自己的程式風格給出了進行RTOS程式設計的架構範例。範例程式見附件中“10_uCOSII_STC8H_程式設計範例”子目錄,下面對其中的“main.c”函數進行解讀。

(20)系統定義部分,見下圖。

将uC/OS-II RTOS移植到STC8H單片機上

第17行程式是系統定義。uC/OS-II将核心功能所有的頭檔案集中在一起,包括單片機的頭檔案,一般使用者程式隻要包含它就行了。

第20行到第22行是實時任務函數預定義,第25行到第27行是實時任務堆棧定義。

uC/OS-II有兩種建立任務的方式:基本的與擴充的。由于移植源隻處理了基本的建立任務的方式,是以所有任務的堆棧都隻能是同樣長度的,這個長度“MaxStkSize”是一個宏定義,定義為900個位元組。見下圖:

将uC/OS-II RTOS移植到STC8H單片機上

如果使用者定義任務堆棧的長度大于“MaxStkSize”,則會産生XDATA空間浪費,如果小于“MaxStkSize”,則會産生任務堆棧錯位,造成程式跑飛。

由于STC8H單片機采用的一次燒錄運作的方式,且8KB的RAM記憶體資源較少,難以像PC機DOS程式可以在運作中建立和删除任務,并且在STC8H單片機上即使删除了任務,該任務占用的CODE空間Keil的C51編譯器也沒有辦法再複用。是以本範例采用建立靜态任務的方法,先預定義任務函數和靜态堆棧,然後在主函數“main”中建立任務。

(21)主函數部分,見下圖。

将uC/OS-II RTOS移植到STC8H單片機上

第33行到第40行是端口初始化程式。STC8H單片機端口的準雙向口模式最為接近傳統8051單片機的端口特性,一般在老8051單片機運作的程式都能通過。

第43行是對系統中斷定時器0的初始化。第46行是關閉定時器0的計數,禁止任務排程。

将uC/OS-II移植到8051單片機上,一般都選擇進入臨界區保護的方法是關閉中斷,退出臨界區保護的方法是打開中斷。在設定系統中斷定時器之後,如果調用了那些有臨界區保護的(像建立任務等)uC/OS-II核心函數,則系統中斷會被打開,如果這時RTOS系統沒有正确配置好,定時器0的中斷就會啟動,繼續執行程式就可能産生預料不到的後果,是以隻能馬上關閉定時器0的計數功能,來避免系統中斷的産生,直到RTOS系統正确配置好,然後在第一個任務中打開計數,啟動任務排程功能。

第49行進行RTOS系統初始化,初始化各種表格和建立初始化的運作狀态。

第52到54行建立了三個使用者實時任務。使用者任務的建立與建立次序沒有關系,隻是要注意建立任務函數的最後一個參數是該任務的優先級數,優先級數越小,優先級越高。

第57行是啟動任務排程程式,從此就将CPU的執行權交給使用者的任務了。即使所有的使用者任務都沒有就緒,CPU執行權也會交給“空閑任務”來執行,并且uC/OS-II采用特殊的程式結構,保證“空閑任務”永遠不會被退出。是以第57行程式應該是“main”函數的最後一行程式,其後面的程式永遠不會被執行。

(22)三個使用者實時任務程式見下圖:

将uC/OS-II RTOS移植到STC8H單片機上

從程式結構上看,每個任務都包含一個無限循環,在循環前有一個前置部分,這與單片機平常程式的“main”主函數結構一樣。每個任務第一次得到CPU控制權時從任務函數開始的地方開始執行,直到被任務排程暫停或者任務程式控制暫停,然後下一次任務再得到CPU控制權的時候,程式從暫停的地方開始執行。是以從任務函數開始到無限循環“Main_Loop”之間的程式隻會被執行一次。

第61到74行是任務A函數,由于它的優先級數是2,優先級最高,是以它肯定最先得到執行。

任務A的第65行程式打開定時器0的計數,系統中斷計數随即産生,任務排程程式開始執行,自此RTOS系統開始正常運作。

為了加強範例程式的示範效果,本範例任務A是LED燈交替閃爍,任務B是LED燈左右閃爍,任務C是跑馬燈。

在這些任務程式裡,uC/OS-II系統函數“OSTimeDly”是讓任務以系統節拍(20毫秒)為機關休眠指定的時間(從任務的角度叫延時Delay,從系統的角度叫休眠Sleep),休眠結束後繼續執行任務後面的程式。

下面為本範例的示範效果視訊:

視訊加載中...

繼續閱讀