ucos ii的特點(diǎn)
1.ucos ii是由Labrosse先生編寫的一個開放式內(nèi)核,,最主要的特點(diǎn)就是源碼公開,。這一點(diǎn)對于用戶來說可謂利弊各半,好處在于,,一方面它是免費(fèi)的,,另一方面用戶可以根據(jù)自己的需要對它進(jìn)行修改。缺點(diǎn)在于它缺乏必要的支持,,沒有功能強(qiáng)大的軟件包,,用戶通常需要自己編寫驅(qū)動程序,特別是如果用戶使用的是不太常用的單片機(jī),,還必須自己編寫移植程序,。
2.ucos ii是一個占先式的內(nèi)核,即已經(jīng)準(zhǔn)備就緒的高優(yōu)先級任務(wù)可以剝奪正在運(yùn)行的低優(yōu)先級任務(wù)的CPU使用權(quán)。這個特點(diǎn)使得它的實(shí)時性比非占先式的內(nèi)核要好,。通常我們都是在中斷服務(wù)程序中使高優(yōu)先級任務(wù)進(jìn)入就緒態(tài)(例如發(fā)信號),,這樣退出中斷服務(wù)程序后,將進(jìn)行任務(wù)切換,,高優(yōu)先級任務(wù)將被執(zhí)行,。拿51單片機(jī)為例,比較一下就可以發(fā)現(xiàn)這樣做的好處,。假如需要用中斷方式采集一批數(shù)據(jù)并進(jìn)行處理,,在傳統(tǒng)的編程方法中不能在中斷服務(wù)程序中進(jìn)行復(fù)雜的數(shù)據(jù)處理,因?yàn)檫@會使得關(guān)中斷時間過長,。所以經(jīng)常采用的方法是置一標(biāo)志位,,然后退出中斷。由于主程序是循環(huán)執(zhí)行的,,所以它總有機(jī)會檢測到這一標(biāo)志并轉(zhuǎn)到數(shù)據(jù)處理程序中去,。但是因?yàn)闊o法確定發(fā)生中斷時程序到底執(zhí)行到了什么地方,也就無法判斷要經(jīng)過多長時間數(shù)據(jù)處理程序才會執(zhí)行,,中斷響應(yīng)時間無法確定,,系統(tǒng)的實(shí)時性不強(qiáng)。如果使用μC/OS-II的話,,只要把數(shù)據(jù)處理程序的優(yōu)先級設(shè)定得高一些,,并在中斷服務(wù)程序中使它進(jìn)入就緒態(tài),中斷結(jié)束后數(shù)據(jù)處理程序就會被立即執(zhí)行,。這樣可以把中斷響應(yīng)時間限制在一定的范圍內(nèi),。對于一些對中斷響應(yīng)時間有嚴(yán)格要求的系統(tǒng),這是必不可少的,。但應(yīng)該指出的是如果數(shù)據(jù)處理程序簡單,,這樣做就未必合適。因?yàn)閡cos ii要求在中斷服務(wù)程序末尾使用OSINTEXIT函數(shù)以判斷是否進(jìn)行任務(wù)切換,,這需要花費(fèi)一定的時間,。
3.ucos ii和大家所熟知的Linux等分時操作系統(tǒng)不同,它不支持時間片輪轉(zhuǎn)法,。ucos ii是一個基于優(yōu)先級的實(shí)時操作系統(tǒng),,每個任務(wù)的優(yōu)先級必須不同,分析它的源碼會發(fā)現(xiàn),,ucos ii把任務(wù)的優(yōu)先級當(dāng)做任務(wù)的標(biāo)識來使用,,如果優(yōu)先級相同,任務(wù)將無法區(qū)分,。進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù)首先得到CPU的使用權(quán),,只有等它交出CPU的使用權(quán)后,,其他任務(wù)才可以被執(zhí)行,。所以它只能說是多任務(wù),,不能說是多進(jìn)程,至少不是我們所熟悉的那種多進(jìn)程,。顯而易見,,如果只考慮實(shí)時性,它當(dāng)然比分時系統(tǒng)好,,它可以保證重要任務(wù)總是優(yōu)先占有CPU,。但是在系統(tǒng)中,重要任務(wù)畢竟是有限的,,這就使得劃分其他任務(wù)的優(yōu)先權(quán)變成了一個讓人費(fèi)神的問題,。另外,有些任務(wù)交替執(zhí)行反而對用戶更有利,。例如,,用單片機(jī)控制兩小塊顯示屏?xí)r,,無論是編程者還是使用者肯定希望它們同時工作,,而不是顯示完一塊顯示屏的信息以后再顯示另一塊顯示屏的信息,。這時候,,要是ucos ii即支持優(yōu)先級法又支持時間片輪轉(zhuǎn)法就更合適了,。
4.ucos ii對共享資源提供了保護(hù)機(jī)制,。正如上文所提到的,,ucos ii是一個支持多任務(wù)的操作系統(tǒng),。一個完整的程序可以劃分成幾個任務(wù),,不同的任務(wù)執(zhí)行不同的功能,。這樣,一個任務(wù)就相當(dāng)于模塊化設(shè)計(jì)中的一個子模塊,。在任務(wù)中添加代碼時,,只要不是共享資源就不必?fù)?dān)心互相之間有影響。而對于共享資源(比如串口),,ucos ii也提供了很好的解決辦法,。一般情況下使用的是信號量的方法。簡單地說,,先創(chuàng)建一個信號量并對它進(jìn)行初始化,。當(dāng)一個任務(wù)需要使用一個共享資源時,它必須先申請得到這個信號量,,而一旦得到了此信號量,,那就只有等使用完了該資源,信號量才會被釋放,。在這個過程中即使有優(yōu)先權(quán)更高的任務(wù)進(jìn)入了就緒態(tài),,因?yàn)闊o法得到此信號量,也不能使用該資源。這個特點(diǎn)的好處顯而易見,,例如當(dāng)顯示屏正在顯示信息的時候,,外部產(chǎn)生了一個中斷,而在中斷服務(wù)程序中需要顯示屏顯示其他信息,。這樣,,退出中斷服務(wù)程序后,原有的信息就可能被破壞了,。而在μC/OS-II中采用信號量的方法時,,只有顯示屏把原有信息顯示完畢后才可以顯示新信息,從而可以避免這個現(xiàn)象,。不過,,采用這種方法是以犧牲系統(tǒng)的實(shí)時性為代價的。如果顯示原有信息需要耗費(fèi)大量時間,,系統(tǒng)只好等待,。從結(jié)果上看,等于延長了中斷響應(yīng)時間,,這對于未顯示信息是報(bào)警信息的情況,,無疑是致命的。發(fā)生這種情況,,在μC/OS-II中稱為優(yōu)先級反轉(zhuǎn),,就是高優(yōu)先級任務(wù)必須等待低優(yōu)先級任務(wù)的完成。在上述情況下,,在兩個任務(wù)之間發(fā)生優(yōu)先級反轉(zhuǎn)是無法避免的,。所以在使用ucos ii時,必須對所開發(fā)的系統(tǒng)了解清楚,,才能決定對于某種共享資源是否使用信號量,。
ucos ii在單片機(jī)使用中的一些特點(diǎn)
1.在單片機(jī)系統(tǒng)中嵌入ucos ii將增強(qiáng)系統(tǒng)的可靠性,并使得調(diào)試程序變得簡單,。以往傳統(tǒng)的單片機(jī)開發(fā)工作中經(jīng)常遇到程序跑飛或是陷入死循環(huán),。可以用看門狗解決程序跑飛問題,,而對于后一種情況,,尤其是其中牽扯到復(fù)雜數(shù)學(xué)計(jì)算的話,只有設(shè)置斷點(diǎn),,耗費(fèi)大量時間來慢慢分析,。如果在系統(tǒng)中嵌入 ucos ii的話,事情就簡單多了,??梢园颜麄€程序分成許多任務(wù),,每個任務(wù)相對獨(dú)立,然后在每個任務(wù)中設(shè)置超時函數(shù),,時間用完以后,,任務(wù)必須交出 CPU的使用權(quán)。即使一個任務(wù)發(fā)生問題,,也不會影響其他任務(wù)的運(yùn)行。這樣既提高了系統(tǒng)的可靠性,,同時也使得調(diào)試程序變得容易,。
2.在單片機(jī)系統(tǒng)中嵌入ucos ii將增加系統(tǒng)的開銷。現(xiàn)在所使用的51單片機(jī),,一般是指87C51或者89C51,,其片內(nèi)都帶有一定的RAM和 ROM。對于一些簡單的程序,,如果采用傳統(tǒng)的編程方法,,已經(jīng)不需要外擴(kuò)存儲器了。如果在其中嵌入ucos ii的話,,在只需要使用任務(wù)調(diào)度,、任務(wù)切換、信號量處理,、延時或超時服務(wù)的情況下,,也不需要外擴(kuò)ROM了,但是外擴(kuò)RAM是必須的,。由于ucos ii是可裁減的操作系統(tǒng),,其所需要的RAM大小就取決于操作系統(tǒng)功能的多少。舉例來說,,μC/OS-II允許用戶定義最大任務(wù)數(shù),。由于每建立一個任務(wù),都要產(chǎn)生一個與之相對應(yīng)的數(shù)據(jù)結(jié)構(gòu)TCB,,該數(shù)據(jù)結(jié)構(gòu)要占用很大一部分內(nèi)存空間,。所以在定義最大任務(wù)數(shù)時,一定要考慮實(shí)際情況的需要,。如果定得過大,,勢必會造成不必要的浪費(fèi)。嵌入ucos ii以后,,總的RAM需求可以由如下表達(dá)式得出:
RAM總需求=應(yīng)用程序的RAM需求+內(nèi)核數(shù)據(jù)區(qū)的RAM需求+(任務(wù)棧需求+最大中斷嵌套棧需求)·任務(wù)數(shù)
所幸的是,,μC/OS-II可以對每個任務(wù)分別定義堆棧空間的大小,,開發(fā)人員可根據(jù)任務(wù)的實(shí)際需求來進(jìn)行??臻g的分配,。但在RAM容量有限的情況下,還是應(yīng)該注意一下對大型數(shù)組,、數(shù)據(jù)結(jié)構(gòu)和函數(shù)的使用,,別忘了,函數(shù)的形參也是要推入堆棧的,。
3.ucos ii的移植也是一件需要值得注意的工作,。如果沒有現(xiàn)成的移植實(shí)例的話,就必須自己來編寫移植代碼,。雖然只需要改動兩個文件,,但仍需要對相應(yīng)的微處理器比較熟悉才行,最好參照已有的移植實(shí)例,。另外,,即使有移植實(shí)例,在編程前最好也要閱讀一下,,因?yàn)槔锩鏍砍兜蕉褩2僮?。在編寫中斷服?wù)程序時,把寄存器推入堆棧的順序必須與移植代碼中的順序相對應(yīng),。
4.和其他一些著名的嵌入式操作系統(tǒng)不同,,ucos ii在單片機(jī)系統(tǒng)中的啟動過程比較簡單,不像有些操作系統(tǒng)那樣,,需要把內(nèi)核編譯成一個映像文件寫入ROM中,,上電復(fù)位后,再從ROM中把文件加載到RAM中去,,然后再運(yùn)行應(yīng)用程序,。ucos ii的內(nèi)核是和應(yīng)用程序放在一起編譯成一個文件的,使用者只需要把這個文件轉(zhuǎn)換成HEX格式,,寫入ROM中就可以了,,上電后,會像普通的單片機(jī)程序一樣運(yùn)行,。
結(jié)語
由以上介紹可以看出,,ucos ii具有免費(fèi)、使用簡單,、可靠性高,、實(shí)時性好等優(yōu)點(diǎn),但也有移植困難,、缺乏必要的技術(shù)支持等缺點(diǎn),,尤其不像商用嵌入式系統(tǒng)那樣得到廣泛使用和持續(xù)的研究更新。但開放性又使得開發(fā)人員可以自行裁減和添加所需的功能,,在許多應(yīng)用領(lǐng)域發(fā)揮著獨(dú)特的作用,。當(dāng)然,,是否在單片機(jī)系統(tǒng)中嵌入ucos ii應(yīng)視所開發(fā)的項(xiàng)目而定,對于一些簡單的,、低成本的項(xiàng)目來說,,就沒必要使用嵌入式操作系統(tǒng)了。
--摘自INTERNET
44B0下ucos-ii的移植
要保證ucos Ⅱ移植到微處理器后能正確運(yùn)行,;處理器需具備如下特性:
1) 處理器的c編譯器支持可重入函數(shù)
可重入的代碼指的是一段代碼(如一個函數(shù))可以被多個任務(wù)同時調(diào)用,,而不必?fù)?dān)心會破壞數(shù)據(jù)。也就是說,,可重入型函數(shù)在任何時候都可以被中斷執(zhí)行,,過一段時間以后又可以繼續(xù)運(yùn)行,而不會因?yàn)樵诤瘮?shù)中斷的時候被其他的任務(wù)重新調(diào)用,,影響函數(shù)中的數(shù)據(jù)。下面的兩個例子可以比較可重入型函數(shù)和非可重入型函數(shù):
程序1:可重入型函數(shù)
void swap(int *x,, int *y)
int temp;
temp=*x;
*x=*y;
*y=temp;
程序2:非可重入型函數(shù)
int temp;
void swap(int *x,, int *y)
temp=*x;
*x=*y;
*y=temp;
程序1 中使用的是局部變量temp 作為變量。通常的C 編譯器,,把局部變量分配在棧中,。
所以,多次調(diào)用同一個函數(shù),,可以保證每次的temp 互不受影響,。而程序2 中temp 定義的是全局變量,多次調(diào)用函數(shù)的時候,,必然受到影響,。代碼的可重入性是保證完成多任務(wù)的基礎(chǔ),除了在C 程序中使用局部變量以外,,還需要C 編譯器的支持,。筆者使用的是ARM SDT 以及ADS 的集成開發(fā)環(huán)境,均可以生成可重入的代碼,。
2)在程序中可以打開和關(guān)閉中斷
在ucos Ⅱ中,,可以通過OS_ENTER_CRITICAL()或者OS_EXIT_CRITICAL()宏來控制
系統(tǒng)關(guān)閉或者打開中斷。這需要處理器的支持,,在ARM7TDMI 的處理器上,,可以設(shè)置相應(yīng)的寄存器來關(guān)閉或者打開系統(tǒng)的所有中斷。
3)處理器支持中斷,,并且能產(chǎn)生定時器中斷(ucos Ⅱ是通過定時器中斷來實(shí)現(xiàn)多任務(wù)的調(diào)度,,即時間片的產(chǎn)生 )ucos Ⅱ 是通過處理器產(chǎn)生的定時器的中斷來實(shí)現(xiàn)多任務(wù)之間的調(diào)度的。在ARM7TDMI 的處理器上可以產(chǎn)生定時器中斷,。
4)處理器要具有一定的硬件堆棧數(shù)量
5)處理器要有將堆棧指針和其他cpu寄存器存儲和讀出堆棧(或者內(nèi)存)的指令(如51的pop,,push指令),。
ucos Ⅱ進(jìn)行任務(wù)調(diào)度的時候,會把當(dāng)前任務(wù)的CPU 寄存器存放到此任務(wù)的堆棧中,,然后,,再從另一個任務(wù)的堆棧中恢復(fù)原來的工作寄存器,繼續(xù)運(yùn)行另一個任務(wù),。所以,,寄存器的入棧和出棧是ucos Ⅱ多任務(wù)調(diào)度的基礎(chǔ)。
ARM7TDMI 處理器完全滿足上述要求,。
ucos ii的特點(diǎn)
1.ucos ii是由Labrosse先生編寫的一個開放式內(nèi)核,,最主要的特點(diǎn)就是源碼公開。這一點(diǎn)對于用戶來說可謂利弊各半,,好處在于,,一方面它是免費(fèi)的,另一方面用戶可以根據(jù)自己的需要對它進(jìn)行修改,。缺點(diǎn)在于它缺乏必要的支持,,沒有功能強(qiáng)大的軟件包,用戶通常需要自己編寫驅(qū)動程序,,特別是如果用戶使用的是不太常用的單片機(jī),,還必須自己編寫移植程序。
2.ucos ii是一個占先式的內(nèi)核,,即已經(jīng)準(zhǔn)備就緒的高優(yōu)先級任務(wù)可以剝奪正在運(yùn)行的低優(yōu)先級任務(wù)的CPU使用權(quán),。這個特點(diǎn)使得它的實(shí)時性比非占先式的內(nèi)核要好。通常我們都是在中斷服務(wù)程序中使高優(yōu)先級任務(wù)進(jìn)入就緒態(tài)(例如發(fā)信號),,這樣退出中斷服務(wù)程序后,,將進(jìn)行任務(wù)切換,高優(yōu)先級任務(wù)將被執(zhí)行,。拿51單片機(jī)為例,,比較一下就可以發(fā)現(xiàn)這樣做的好處。假如需要用中斷方式采集一批數(shù)據(jù)并進(jìn)行處理,,在傳統(tǒng)的編程方法中不能在中斷服務(wù)程序中進(jìn)行復(fù)雜的數(shù)據(jù)處理,,因?yàn)檫@會使得關(guān)中斷時間過長。所以經(jīng)常采用的方法是置一標(biāo)志位,,然后退出中斷,。由于主程序是循環(huán)執(zhí)行的,所以它總有機(jī)會檢測到這一標(biāo)志并轉(zhuǎn)到數(shù)據(jù)處理程序中去,。但是因?yàn)闊o法確定發(fā)生中斷時程序到底執(zhí)行到了什么地方,,也就無法判斷要經(jīng)過多長時間數(shù)據(jù)處理程序才會執(zhí)行,中斷響應(yīng)時間無法確定,,系統(tǒng)的實(shí)時性不強(qiáng),。如果使用μC/OS-II的話,,只要把數(shù)據(jù)處理程序的優(yōu)先級設(shè)定得高一些,并在中斷服務(wù)程序中使它進(jìn)入就緒態(tài),,中斷結(jié)束后數(shù)據(jù)處理程序就會被立即執(zhí)行,。這樣可以把中斷響應(yīng)時間限制在一定的范圍內(nèi)。對于一些對中斷響應(yīng)時間有嚴(yán)格要求的系統(tǒng),,這是必不可少的,。但應(yīng)該指出的是如果數(shù)據(jù)處理程序簡單,這樣做就未必合適,。因?yàn)閡cos ii要求在中斷服務(wù)程序末尾使用OSINTEXIT函數(shù)以判斷是否進(jìn)行任務(wù)切換,,這需要花費(fèi)一定的時間。
3.ucos ii和大家所熟知的Linux等分時操作系統(tǒng)不同,,它不支持時間片輪轉(zhuǎn)法,。ucos ii是一個基于優(yōu)先級的實(shí)時操作系統(tǒng),每個任務(wù)的優(yōu)先級必須不同,,分析它的源碼會發(fā)現(xiàn),,ucos ii把任務(wù)的優(yōu)先級當(dāng)做任務(wù)的標(biāo)識來使用,如果優(yōu)先級相同,,任務(wù)將無法區(qū)分,。進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù)首先得到CPU的使用權(quán),,只有等它交出CPU的使用權(quán)后,,其他任務(wù)才可以被執(zhí)行。所以它只能說是多任務(wù),,不能說是多進(jìn)程,,至少不是我們所熟悉的那種多進(jìn)程。顯而易見,,如果只考慮實(shí)時性,,它當(dāng)然比分時系統(tǒng)好,它可以保證重要任務(wù)總是優(yōu)先占有CPU,。但是在系統(tǒng)中,,重要任務(wù)畢竟是有限的,這就使得劃分其他任務(wù)的優(yōu)先權(quán)變成了一個讓人費(fèi)神的問題,。另外,,有些任務(wù)交替執(zhí)行反而對用戶更有利。例如,,用單片機(jī)控制兩小塊顯示屏?xí)r,,無論是編程者還是使用者肯定希望它們同時工作,而不是顯示完一塊顯示屏的信息以后再顯示另一塊顯示屏的信息,。這時候,,要是ucos ii即支持優(yōu)先級法又支持時間片輪轉(zhuǎn)法就更合適了,。
4.ucos ii對共享資源提供了保護(hù)機(jī)制。正如上文所提到的,,ucos ii是一個支持多任務(wù)的操作系統(tǒng),。一個完整的程序可以劃分成幾個任務(wù),不同的任務(wù)執(zhí)行不同的功能,。這樣,,一個任務(wù)就相當(dāng)于模塊化設(shè)計(jì)中的一個子模塊。在任務(wù)中添加代碼時,,只要不是共享資源就不必?fù)?dān)心互相之間有影響,。而對于共享資源(比如串口),ucos ii也提供了很好的解決辦法,。一般情況下使用的是信號量的方法,。簡單地說,先創(chuàng)建一個信號量并對它進(jìn)行初始化,。當(dāng)一個任務(wù)需要使用一個共享資源時,,它必須先申請得到這個信號量,而一旦得到了此信號量,,那就只有等使用完了該資源,,信號量才會被釋放。在這個過程中即使有優(yōu)先權(quán)更高的任務(wù)進(jìn)入了就緒態(tài),,因?yàn)闊o法得到此信號量,,也不能使用該資源。這個特點(diǎn)的好處顯而易見,,例如當(dāng)顯示屏正在顯示信息的時候,,外部產(chǎn)生了一個中斷,而在中斷服務(wù)程序中需要顯示屏顯示其他信息,。這樣,,退出中斷服務(wù)程序后,原有的信息就可能被破壞了,。而在μC/OS-II中采用信號量的方法時,,只有顯示屏把原有信息顯示完畢后才可以顯示新信息,從而可以避免這個現(xiàn)象,。不過,,采用這種方法是以犧牲系統(tǒng)的實(shí)時性為代價的。如果顯示原有信息需要耗費(fèi)大量時間,,系統(tǒng)只好等待,。從結(jié)果上看,等于延長了中斷響應(yīng)時間,這對于未顯示信息是報(bào)警信息的情況,,無疑是致命的,。發(fā)生這種情況,在μC/OS-II中稱為優(yōu)先級反轉(zhuǎn),,就是高優(yōu)先級任務(wù)必須等待低優(yōu)先級任務(wù)的完成,。在上述情況下,在兩個任務(wù)之間發(fā)生優(yōu)先級反轉(zhuǎn)是無法避免的,。所以在使用ucos ii時,,必須對所開發(fā)的系統(tǒng)了解清楚,才能決定對于某種共享資源是否使用信號量,。
ucos ii在單片機(jī)使用中的一些特點(diǎn)
1.在單片機(jī)系統(tǒng)中嵌入ucos ii將增強(qiáng)系統(tǒng)的可靠性,,并使得調(diào)試程序變得簡單。以往傳統(tǒng)的單片機(jī)開發(fā)工作中經(jīng)常遇到程序跑飛或是陷入死循環(huán),??梢杂每撮T狗解決程序跑飛問題,而對于后一種情況,,尤其是其中牽扯到復(fù)雜數(shù)學(xué)計(jì)算的話,,只有設(shè)置斷點(diǎn),耗費(fèi)大量時間來慢慢分析,。如果在系統(tǒng)中嵌入 ucos ii的話,,事情就簡單多了??梢园颜麄€程序分成許多任務(wù),,每個任務(wù)相對獨(dú)立,然后在每個任務(wù)中設(shè)置超時函數(shù),,時間用完以后,,任務(wù)必須交出 CPU的使用權(quán),。即使一個任務(wù)發(fā)生問題,,也不會影響其他任務(wù)的運(yùn)行。這樣既提高了系統(tǒng)的可靠性,,同時也使得調(diào)試程序變得容易,。
2.在單片機(jī)系統(tǒng)中嵌入ucos ii將增加系統(tǒng)的開銷。現(xiàn)在所使用的51單片機(jī),,一般是指87C51或者89C51,,其片內(nèi)都帶有一定的RAM和 ROM。對于一些簡單的程序,,如果采用傳統(tǒng)的編程方法,,已經(jīng)不需要外擴(kuò)存儲器了。如果在其中嵌入ucos ii的話,在只需要使用任務(wù)調(diào)度,、任務(wù)切換,、信號量處理、延時或超時服務(wù)的情況下,,也不需要外擴(kuò)ROM了,,但是外擴(kuò)RAM是必須的。由于ucos ii是可裁減的操作系統(tǒng),,其所需要的RAM大小就取決于操作系統(tǒng)功能的多少,。舉例來說,μC/OS-II允許用戶定義最大任務(wù)數(shù),。由于每建立一個任務(wù),,都要產(chǎn)生一個與之相對應(yīng)的數(shù)據(jù)結(jié)構(gòu)TCB,該數(shù)據(jù)結(jié)構(gòu)要占用很大一部分內(nèi)存空間,。所以在定義最大任務(wù)數(shù)時,,一定要考慮實(shí)際情況的需要。如果定得過大,,勢必會造成不必要的浪費(fèi),。嵌入ucos ii以后,總的RAM需求可以由如下表達(dá)式得出:
RAM總需求=應(yīng)用程序的RAM需求+內(nèi)核數(shù)據(jù)區(qū)的RAM需求+(任務(wù)棧需求+最大中斷嵌套棧需求)·任務(wù)數(shù)
所幸的是,,μC/OS-II可以對每個任務(wù)分別定義堆??臻g的大小,開發(fā)人員可根據(jù)任務(wù)的實(shí)際需求來進(jìn)行??臻g的分配,。但在RAM容量有限的情況下,還是應(yīng)該注意一下對大型數(shù)組,、數(shù)據(jù)結(jié)構(gòu)和函數(shù)的使用,,別忘了,函數(shù)的形參也是要推入堆棧的,。
3.ucos ii的移植也是一件需要值得注意的工作,。如果沒有現(xiàn)成的移植實(shí)例的話,就必須自己來編寫移植代碼,。雖然只需要改動兩個文件,,但仍需要對相應(yīng)的微處理器比較熟悉才行,最好參照已有的移植實(shí)例,。另外,,即使有移植實(shí)例,在編程前最好也要閱讀一下,,因?yàn)槔锩鏍砍兜蕉褩2僮?。在編寫中斷服?wù)程序時,,把寄存器推入堆棧的順序必須與移植代碼中的順序相對應(yīng)。
4.和其他一些著名的嵌入式操作系統(tǒng)不同,,ucos ii在單片機(jī)系統(tǒng)中的啟動過程比較簡單,,不像有些操作系統(tǒng)那樣,需要把內(nèi)核編譯成一個映像文件寫入ROM中,,上電復(fù)位后,,再從ROM中把文件加載到RAM中去,然后再運(yùn)行應(yīng)用程序,。ucos ii的內(nèi)核是和應(yīng)用程序放在一起編譯成一個文件的,,使用者只需要把這個文件轉(zhuǎn)換成HEX格式,寫入ROM中就可以了,,上電后,,會像普通的單片機(jī)程序一樣運(yùn)行。
結(jié)語
由以上介紹可以看出,,ucos ii具有免費(fèi),、使用簡單、可靠性高,、實(shí)時性好等優(yōu)點(diǎn),,但也有移植困難、缺乏必要的技術(shù)支持等缺點(diǎn),,尤其不像商用嵌入式系統(tǒng)那樣得到廣泛使用和持續(xù)的研究更新,。但開放性又使得開發(fā)人員可以自行裁減和添加所需的功能,在許多應(yīng)用領(lǐng)域發(fā)揮著獨(dú)特的作用,。當(dāng)然,,是否在單片機(jī)系統(tǒng)中嵌入ucos ii應(yīng)視所開發(fā)的項(xiàng)目而定,對于一些簡單的,、低成本的項(xiàng)目來說,,就沒必要使用嵌入式操作系統(tǒng)了。
--摘自INTERNET
44B0下ucos-ii的移植
要保證ucos Ⅱ移植到微處理器后能正確運(yùn)行,;處理器需具備如下特性:
1) 處理器的c編譯器支持可重入函數(shù)
可重入的代碼指的是一段代碼(如一個函數(shù))可以被多個任務(wù)同時調(diào)用,,而不必?fù)?dān)心會破壞數(shù)據(jù)。也就是說,,可重入型函數(shù)在任何時候都可以被中斷執(zhí)行,,過一段時間以后又可以繼續(xù)運(yùn)行,,而不會因?yàn)樵诤瘮?shù)中斷的時候被其他的任務(wù)重新調(diào)用,,影響函數(shù)中的數(shù)據(jù)。下面的兩個例子可以比較可重入型函數(shù)和非可重入型函數(shù):
程序1:可重入型函數(shù)
void swap(int *x,, int *y)
int temp;
temp=*x;
*x=*y;
*y=temp;
程序2:非可重入型函數(shù)
int temp;
void swap(int *x,, int *y)
temp=*x;
*x=*y;
*y=temp;
程序1 中使用的是局部變量temp 作為變量。通常的C 編譯器,把局部變量分配在棧中,。
所以,,多次調(diào)用同一個函數(shù),可以保證每次的temp 互不受影響,。而程序2 中temp 定義的是全局變量,,多次調(diào)用函數(shù)的時候,必然受到影響,。代碼的可重入性是保證完成多任務(wù)的基礎(chǔ),,除了在C 程序中使用局部變量以外,還需要C 編譯器的支持,。筆者使用的是ARM SDT 以及ADS 的集成開發(fā)環(huán)境,,均可以生成可重入的代碼。
2)在程序中可以打開和關(guān)閉中斷
在ucos Ⅱ中,,可以通過OS_ENTER_CRITICAL()或者OS_EXIT_CRITICAL()宏來控制
系統(tǒng)關(guān)閉或者打開中斷,。這需要處理器的支持,在ARM7TDMI 的處理器上,,可以設(shè)置相應(yīng)的寄存器來關(guān)閉或者打開系統(tǒng)的所有中斷,。
3)處理器支持中斷,并且能產(chǎn)生定時器中斷(ucos Ⅱ是通過定時器中斷來實(shí)現(xiàn)多任務(wù)的調(diào)度,,即時間片的產(chǎn)生 )ucos Ⅱ 是通過處理器產(chǎn)生的定時器的中斷來實(shí)現(xiàn)多任務(wù)之間的調(diào)度的,。在ARM7TDMI 的處理器上可以產(chǎn)生定時器中斷。
4)處理器要具有一定的硬件堆棧數(shù)量
5)處理器要有將堆棧指針和其他cpu寄存器存儲和讀出堆棧(或者內(nèi)存)的指令(如51的pop,,push指令),。
ucos Ⅱ進(jìn)行任務(wù)調(diào)度的時候,會把當(dāng)前任務(wù)的CPU 寄存器存放到此任務(wù)的堆棧中,,然后,,再從另一個任務(wù)的堆棧中恢復(fù)原來的工作寄存器,繼續(xù)運(yùn)行另一個任務(wù),。所以,,寄存器的入棧和出棧是ucos Ⅱ多任務(wù)調(diào)度的基礎(chǔ)。
ARM7TDMI 處理器完全滿足上述要求,。
接下來將介紹如何把ucos Ⅱ移植到Samsung公司的一款A(yù)RM7TDMI 的嵌入式處理器——S3C44B0X 上,。
ucos Ⅱ中與處理器有關(guān)的代碼:os_cpu.h os_cpu_a.asm os_cpu_c.c
ucos Ⅱ的設(shè)置 : os_cfg.h inludes.h
ucos Ⅱ在44b0上的移植
1)設(shè)置inludes.h中與處理器及編譯器有關(guān)的代碼
FORADS
#include “os_cpu.h”
#include “os_cfg.h”
#include “ucos_ii.h”
這里未做處理 取默認(rèn)的數(shù)據(jù)類型。
FOR SDT
#include 》stdio.h《
#include 》stdlib.h《
#include 》string.h《
#include “os_cpu.h”
#include “os_cfg.h”
#include “ucos_ii.h”
#ifdef EX3_GLOBALS
#define EX3_EXT
#else
#define EX3_EXT extern
#endif
typedef struct {
char TaskName[30];
INT16U TaskCtr;
INT16U TaskExecTime;
INT32U TaskTotExecTime;
} TASK_USER_DATA;
EX3_EXT TASK_USER_DATA TaskUserData[10];
void DispTaskStat(INT8U id);
********************************************************************************
其他人的應(yīng)用修改事例:
#define INT8U unsigned char
#define INT16U unsigned short
#define INT32U unsigned long
#define OS_STK unsigned long
#define BOOLEAN int
#define OS_CPU_SR unsigned long
#define INT8S char
extern int INTS_OFF(void);
extern void INTS_ON(void);
#define OS_ENTER_CRITICAL() { cpu_sr = INTS_OFF(); }
#define OS_EXIT_CRITICAL() { if(cpu_sr == 0) INTS_ON(); }
#define OS_STK_GROWTH 1
#define STACKSIZE 256
因?yàn)椴煌奈⑻幚砥饔胁煌淖珠L,,所以ucos Ⅱ的移植包括了一系列的類型定義以確
保其可移植性,。尤其是ucos Ⅱ代碼從不使用C 的short,int 和long 等數(shù)據(jù)類型,,因?yàn)樗鼈兪桥c編譯器相關(guān)的,,不可移植,。相反的,我們定義的整形數(shù)據(jù)結(jié)構(gòu)既是可移植的又是直觀的,。為了方便,,雖然ucos Ⅱ不是用浮點(diǎn)數(shù)據(jù),但我們還是定義了浮點(diǎn)數(shù)據(jù)類型,。
例如,,INT16U 數(shù)據(jù)類型總是代表16 位的無符號整數(shù)。現(xiàn)在,,ucos Ⅱ和用戶的應(yīng)用程序就可以估計(jì)出聲明為該數(shù)據(jù)類型的變量的取值范圍是0~65535,。將ucos Ⅱ移植到32 位的處理器上也就意味著INT16U 實(shí)際被聲明為無符號短整形數(shù)據(jù)結(jié)構(gòu)而不是無符號整數(shù)數(shù)據(jù)結(jié)構(gòu)。但是,,μC/OS-Ⅱ所處理的仍然是INT16U,。用戶必須將任務(wù)堆棧的數(shù)據(jù)類型告訴給μC/OS-Ⅱ。這個過程是通過為OS_STK 聲明正確的C 數(shù)據(jù)類型來完成的,。我們的處理器上的堆棧成員是16 位的,,所以將OS_TSK 聲明為無符號整形數(shù)據(jù)類型。所有的任務(wù)堆棧都必須用OS_TSK 聲明數(shù)據(jù)類型,。
2)OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()
與所有的實(shí)時內(nèi)核一樣,,μC/OS-Ⅱ需要先禁止中斷再訪問代碼的臨界區(qū),并且在訪問完
畢后重新允許中斷,。這就使得μC/OS-Ⅱ能夠保護(hù)臨界區(qū)代碼免受多任務(wù)或中斷服務(wù)例程
?。↖SR)的破壞。在S3C44B0X 上是通過兩個函數(shù)(OS_CPU_A.S)實(shí)現(xiàn)開關(guān)中斷的,。
INTS_OFF
mrs r0,, cpsr ; 當(dāng)前CSR
mov r1, r0 ; 復(fù)制屏蔽
orr r1,, r1,, #0xC0 ; 屏蔽中斷位
msr CPSR, r1 ; 關(guān)中斷(IRQ and FIQ)
and r0,, r0,, #0x80 ; 從初始CSR 返回FIQ 位
mov pc,lr ; 返回
INTS_ON
mrs r0,, cpsr ; 當(dāng)前CSR
bic r0,, r0, #0xC0 ; 屏蔽中斷
msr CPSR,, r0 ; 開中斷(IRQ and FIQ)
mov pc,,lr ; 返回
3)OS_STK_GROWTH
絕大多數(shù)的微處理器和微控制器的堆棧是從上往下長的。但是某些處理器是用另外一種方式工作的,。μC/OS-Ⅱ被設(shè)計(jì)成兩種情況都可以處理,,只要在結(jié)構(gòu)常量OS_STK_GROWTH中指定堆棧的生長方式就可以了,。
置OS_STK_GROWTH 為0 表示堆棧從下往上長,。
置OS_STK_GROWTH 為1 表示堆棧從上往下長,。
用c語言編寫6個與操作系統(tǒng)相關(guān)的函數(shù)(OS_CPU_C.C)
1. OsTaskStKInit()
OSTaskCreate()和OSTaskCreateExt()通過調(diào)用OSTaskStkInit()來初始化任務(wù)的堆
棧結(jié)構(gòu)。因此,,堆??雌饋砭拖駝偘l(fā)生過中斷并將所有的寄存器保存到堆棧中的情形一樣。
圖12-2 顯示了OSTaskStkInt()放到正被建立的任務(wù)堆棧中的東西,。這里我們定義了堆棧是
從上往下長的,。
在用戶建立任務(wù)的時候,用戶傳遞任務(wù)的地址,,pdata 指針,,任務(wù)的堆棧棧頂和任務(wù)的
優(yōu)先級給OSTaskCreate()和OSTaskCreateExt()。一旦用戶初始化了堆棧,,OSTaskStkInit
?。ǎ┚托枰祷囟褩V羔?biāo)傅牡刂贰STaskCreate()和OSTaskCreateExt()會獲得該地
址并將它保存到任務(wù)控制塊(OS_TCB)中,。
OS_STK * OSTaskStkInit (void (*task)(void *pd),, void *pdata, OS_STK *ptos,, INT16U opt)
{
unsigned int * stk;
stk = (unsigned int *)ptos;
opt++;
*--stk = (unsigned int) task;
*--stk = (unsigned int) task;
*--stk = 12;
*--stk = 11;
*--stk = 10;
*--stk = 9;
*--stk = 8;
*--stk = 7;
*--stk = 6;
*--stk = 5;
*--stk = 4;
*--stk = 3;
*--stk = 2;
*--stk = 1;
*--stk = (unsigned int) pdata;
*--stk = (SUPMODE);
*--stk = (SUPMODE);
return ((OS_STK *)stk);
}
2).OSTaskCreateHook
當(dāng)用OSTaskCreate()和OSTaskCreateExt ()建立任務(wù)的時候就會調(diào)用OSTaskCreateHook
?。ǎT摵瘮?shù)允許用戶或使用移植實(shí)例的用戶擴(kuò)展μC/OS-Ⅱ功能,。當(dāng)μC/OS-Ⅱ設(shè)置完了自己的內(nèi)部結(jié)構(gòu)后,,會在調(diào)用任務(wù)調(diào)度程序之前調(diào)用OSTaskCreateHook()。該函數(shù)被調(diào)用的時候中斷是禁止的,。因此用戶應(yīng)盡量減少該函數(shù)中的代碼以縮短中斷的響應(yīng)時間,。當(dāng)OSTaskCreateHook()被調(diào)用的時候,它會收到指向已建立任務(wù)的OS_TCB 的指針,,這樣它就可以訪問所有的結(jié)構(gòu)成員了,。
函數(shù)原型:
void OSTaskCreateHook (OS_TCB *ptcb)
3).OsTaskDelHook()
當(dāng)任務(wù)被刪除的時候就會調(diào)用OSTaskDelHook()。該函數(shù)在把任務(wù)從μC/OS-Ⅱ的內(nèi)部
任務(wù)鏈表中解開之前被調(diào)用,。當(dāng)OSTaskDelHook()被調(diào)用的時候,,它會收到指向正被刪除任務(wù)的OS_TCB 的指針,這樣它就可以訪問所有的結(jié)構(gòu)成員了,。OSTaskDelHook()可以來檢驗(yàn)TCB 擴(kuò)展是否被建立(一個非空指針)并進(jìn)行一些清除操作,。
函數(shù)原型:
void OSTaskDelHook (OS_TCB *ptcb)
4.OsTaskSwHook()
當(dāng)發(fā)生任務(wù)切換的時候就會調(diào)用OSTaskSwHook()。OSTaskSwHook()可以直接訪問
OSTCBCur 和OSTCBHighRdy,,因?yàn)樗鼈兪侨肿兞?。OSTCBCur 指向被切換出去的任務(wù)OS_TCB,,而OSTCBHighRdy 指向新任務(wù)OS_TCB。注意在調(diào)用OSTaskSwHook()期間中斷一直是被禁止的,。因此用戶應(yīng)盡量減少該函數(shù)中的代碼以縮短中斷的響應(yīng)時間,。
函數(shù)原型:
void OSTaskSwHook (void)
5.OsTaskStatHook()
OSTaskStatHook()每秒鐘都會被OSTaskStat()調(diào)用一次。用戶可以用OSTaskStatHook
?。ǎ﹣頂U(kuò)展統(tǒng)計(jì)功能,。例如,用戶可以保持并顯示每個任務(wù)的執(zhí)行時間,,每個任務(wù)所用的CPU 份額,,以及每個任務(wù)執(zhí)行的頻率等。
函數(shù)原型:
void OSTaskStatHook (void)
6.OsTimeTickHook()
OSTimeTickHook()在每個時鐘節(jié)拍都會被OSTaskTick()調(diào)用,。實(shí)際上,,OSTimeTickHook
()是在節(jié)拍被μC/OS-Ⅱ真正處理,,并通知用戶的移植實(shí)例或應(yīng)用程序之前被調(diào)用的,。
函數(shù)原型:
void OSTimeTickHook (void)
后5 個函數(shù)為鉤子函數(shù),可以不加代碼,。只有當(dāng)OS_CFG.H 中的OS_CPU_HOOKS_EN
被置為1 時才會產(chǎn)生這些函數(shù)的代碼,。
用匯編語言編寫4個與處理器相關(guān)的函數(shù)(OS_CPU_a.asm)
(1)OsStartHighRdy();運(yùn)行優(yōu)先級最高的就緒任務(wù)
OSStartHighRdy
LDR r4,, addr_OSTCBCur ; 得到當(dāng)前任務(wù)TCB 地址
LDR r5,, addr_OSTCBHighRdy ; 得到最高優(yōu)先級任務(wù)TCB 地址
LDR r5, [r5] ; 獲得堆棧指針
LDR sp,, [r5] ; 轉(zhuǎn)移到新的堆棧中
STR r5,, [r4] ; 設(shè)置新的當(dāng)前任務(wù)TCB 地址
LDMFD sp!,, {r4} ;
MSR SPSR,, r4
LDMFD sp!,, {r4} ; 從棧頂獲得新的狀態(tài)
MSR CPSR,, r4 ; CPSR 處于SVC32Mode 摸式
LDMFD sp!,, {r0-r12,, lr, pc } ; 運(yùn)行新的任務(wù)
?。?)OS_TaSK_SW();任務(wù)級的任務(wù)切換函數(shù)
OS_TASK_SW
STMFD sp,!, {lr} ; 保存pc
STMFD sp!,, {lr} ; 保存lr
STMFD sp,!, {r0-r12} ; 保存寄存器和返回地址
MRS r4,, CPSR
STMFD sp,!, {r4} ; 保存當(dāng)前的PSR
MRS r4,, SPSR
STMFD sp,!,, {r4} ; 保存SPSR
; OSPrioCur = OSPrioHighRdy
LDR r4,, addr_OSPrioCur
LDR r5, addr_OSPrioHighRdy
LDRB r6,, [r5]
STRB r6,, [r4]
; 得到當(dāng)前任務(wù)TCB 地址
LDR r4, addr_OSTCBCur
LDR r5,, [r4]
STR sp,, [r5] ; 保存sp 在被占先的任務(wù)的TCB
; 得到最高優(yōu)先級任務(wù)TCB 地址
LDR r6, addr_OSTCBHighRdy
LDR r6,, [r6]
LDR sp,, [r6] ; 得到新任務(wù)堆棧指針
; OSTCBCur = OSTCBHighRdy
STR r6, [r4] ; 設(shè)置新的當(dāng)前任務(wù)的TCB 地址
;保存任務(wù)方式寄存器
LDMFD sp,!,, {r4}
MSR SPSR, r4
LDMFD sp,!,, {r4}
MSR CPSR, r4
; 返回到新任務(wù)的上下文
LDMFD sp,!,, {r0-r12, lr,, pc}
?。?)OSINTCTXSW();中斷級的任務(wù)切換函數(shù)
OSIntCtxSw
add r7, sp,, #16 ; 保存寄存器指針
LDR sp,, =IRQStack ;FIQ_STACK
mrs r1, SPSR ; 得到暫停的PSR
orr r1,, r1,, #0xC0 ; 關(guān)閉IRQ, FIQ.
msr CPSR_cxsf,, r1 ; 轉(zhuǎn)換模式(應(yīng)該是SVC_MODE)
ldr r0,, [r7,, #52] ; 從IRQ 堆棧中得到IRQ‘s LR (任務(wù)PC)
sub r0, r0,, #4 ; 當(dāng)前PC 地址是(saved_LR - 4)
STMFD sp,!, {r0} ; 保存任務(wù)PC
STMFD sp,!,, {lr} ; 保存LR
mov lr, r7 ; 保存FIQ 堆棧ptr in LR (轉(zhuǎn)到nuke r7)
ldmfd lr,!,, {r0-r12} ; 從FIQ 堆棧中得到保存的寄存器
STMFD sp!,, {r0-r12} ;在任務(wù)堆棧中保存寄存器
;在任務(wù)堆棧上保存PSR 和任務(wù)PSR
MRS r4,, CPSR
bic r4, r4,, #0xC0 ; 使中斷位處于使能態(tài)
STMFD sp,!, {r4} ; 保存任務(wù)當(dāng)前PSR
MRS r4,, SPSR
STMFD sp,!, {r4} ; SPSR
; OSPrioCur = OSPrioHighRdy // 改變當(dāng)前程序
LDR r4,, addr_OSPrioCur
LDR r5,, addr_OSPrioHighRdy
LDRB r6, [r5]
STRB r6,, [r4]
; 得到被占先的任務(wù)TCB
LDR r4,, addr_OSTCBCur
LDR r5, [r4]
STR sp,, [r5] ; 保存sp 在被占先的任務(wù)的TCB
; 得到新任務(wù)TCB 地址
LDR r6,, addr_OSTCBHighRdy
LDR r6, [r6]
LDR sp,, [r6] ; 得到新任務(wù)堆棧指針
; OSTCBCur = OSTCBHighRdy
STR r6,, [r4] ; 設(shè)置新的當(dāng)前任務(wù)的TCB 地址
LDMFD sp!,, {r4}
MSR SPSR,, r4
LDMFD sp!,, {r4}
BIC r4,, r4, #0xC0 ; 必須退出新任務(wù)通過允許中斷
MSR CPSR, r4
LDMFD sp,!,, {r0-r12, lr,, pc}
完成了上述工作以后,,μC/OS-Ⅱ就可以正常運(yùn)行在ARM 處理器上了。
我們的板子上已經(jīng)有移植成功的簡單應(yīng)用,,移植部分不須多大改動就可以直接復(fù)制到您的應(yīng)用中去,。
文件系統(tǒng)的建立:
文件系統(tǒng)相關(guān)的API函數(shù)功能解釋:
void initosfile();
功能:初始化文件管理,為文件結(jié)構(gòu)分配空間,,在系統(tǒng)初始化時調(diào)用
FILE* OPENOSFILE(char filename[],,u32 open mode);
功能:以讀取方式或?qū)懭敕绞街付ù蜷_的文件,并創(chuàng)建FILE結(jié)構(gòu),,為文件讀取分配緩沖區(qū),,返回當(dāng)前指向文件結(jié)構(gòu)的指針,。
參數(shù)說明:
filename 打開的文件名
openmode 打開文件的方式:FILEMODE_READ 1
FILEMODE_WRITE 2
U32 Readosfile(FILE* pfile,,u8* readbuffer,u32 nreadbyte);
功能: 讀取已經(jīng)打開的文件到制定的緩沖區(qū),,成功則返回讀取的字節(jié)數(shù)
參數(shù)說明:
pfile : 指向打開文件的指針
readbuffer :讀文件的目的緩沖區(qū),。
Nreadbyte: 讀文件的字節(jié)數(shù)
U32 linereadosfile(FILE* pfile,char str[]);
功能:讀取之定文件的一行,,返回讀取文件的字節(jié)數(shù),。
參數(shù)說明:
Pfile: 指向打開文件的指針
Str: 讀取的字符竄數(shù)組
U8 writeosfile(FILE* pfile,u8* writebuffer,,u32 nreadbyte);
功能:把緩沖區(qū)寫入指定的文件,,如果成功就返回true 否則false.
參數(shù)說明:
pfile: 指向打開文件的指針
writebuffer :寫入文件的目的緩沖區(qū)。
Nreadbyte: 寫入文件的字節(jié)數(shù)
Void closeosfile()
功能:關(guān)閉打開的文件,,釋放文件緩沖區(qū)
參數(shù)說明:
pfile: 指向打開文件的指針
u8 getnextfilename(u32 *filepos,,char filename[]);
功能:得到文件目錄分配表中的指定位置的文件名(包括擴(kuò)展名),文件位置自動下移,。
若文件有效則返回true ,,否則flase
filepos: 文件的位置,范圍從0~511,;
filename: 返回的文件名
u8 listnextfilename(u32 *filepos,,char fileexname[],char filename[]);
功能:列出當(dāng)前位置開始第一個制定擴(kuò)展名的文件,,如果沒有,,返回flase
參數(shù)說明:
filepos: 文件的位置,范圍從0~511;
fileexname:指定的文件擴(kuò)展名
filename:返回的文件名
外設(shè)計(jì)驅(qū)動程序
1) 串口接口函數(shù)
void Uart_Init(int uartnum,,int mclk,,int baud);
功能:初始化串口,設(shè)置通訊的波特率
參數(shù)說明:
uartnum :所設(shè)定的串行口號
mclk: 系統(tǒng)的主時鐘頻率,,如果為0則為默認(rèn)值 60
baud:所設(shè)定的串口通訊波特率
void uart_printf(char *fmt,,…)
功能:輸出字符到串口0
參數(shù)說明:
fmt:輸出到串口的字符串
char uart_getch(char *revdatq,int uartnum,,int timeout);
功能:接收指定的串口的數(shù)據(jù),,收到數(shù)據(jù)是返回true 否則flase
參數(shù)說明:
revdatq: 輸入緩沖區(qū)
uartnum:所設(shè)定得串口號
timeout: 等待超時時間
void uart_sendbyte(int uartnum,u8 data);
功能:向指定串口發(fā)送數(shù)據(jù)
參數(shù)說明:
uart_num : 所設(shè)定得串口號
data: 發(fā)送的數(shù)據(jù)
例子:
當(dāng)操作系統(tǒng)啟動時,,將自動初始化各串行口,,所以應(yīng)用程序調(diào)用串行口資源將變得非常
容易。值的注意的是,,應(yīng)用程序往往是多任務(wù)系統(tǒng),,為了實(shí)時監(jiān)測串行口信息,在本操作環(huán)
境中必須單開一個串行口掃描任務(wù),,保證信息不丟失,。
⑴ 打開一個已有的工程文件,,在其中的主函數(shù)MAIN 中添加串行口的寄存器初始化
代碼,,并添加串行口和鍵盤掃描任務(wù),串行口掃描任務(wù)的代碼如下:
void Uart_Scan_Task1(void *Id)
{
char c1;
POSMSG pmsg1;
for (;;){
if(Uart_Getch(&c1,,0,,1))
{
pmsg1=OSCreateMessage(NULL,OSM_SERIAL,,0,,c1);
if(pmsg1)
SendMessage(pmsg1);
}
}
}//Uart_Scan_Task
(2)當(dāng)系統(tǒng)收到串行口信息時,,將會自動向主任務(wù)發(fā)送一個串行口消息,。主任務(wù)接收
到該消息,將會調(diào)用響應(yīng)函數(shù),,響應(yīng)該消息,。添加消息響應(yīng)函數(shù)的代碼如下:
void onSerial(int portn, char c)
{
Uart_SendByte(0,,c);
?、?添加主任務(wù)
void Main_Task(void *Id) //Main_Test_Task
{
POSMSG pMsg=0;
ClearScreen();
//消息循環(huán)
for(;;){
pMsg=WaitMessage(0); //等待消息
switch(pMsg-{
case OSM_SERIAL:
onSerial(pMsg-break;
}
DeleteMessage(pMsg);//刪除消息,釋放資源
}
}
2) 鍵盤掃描驅(qū)動4*4
u32 GetKey();
功能:1 有效,。此函數(shù)位死鎖函數(shù),,調(diào)用以后,,除非有鍵按下 否則不返回
void setfunctionkey();
功能:設(shè)定功能鍵掃描碼,1 有效,。類似計(jì)算機(jī)的ctrl/alt ,,可以提供復(fù)合鍵
u32 getnotaskkey();
功能:1 有效。此函數(shù)位死鎖函數(shù),,調(diào)用以后,,除非有鍵按下 否則不返回, 與u32 GetKey()的區(qū)別詩詞函數(shù)不會釋放此任務(wù)的控制權(quán),,除非有更高級的任務(wù)運(yùn)行
例子
1)在主函數(shù)中定義鍵盤映射表,,定義鍵盤掃描函數(shù),定義鍵盤驅(qū)動函數(shù),。
?。?)定義鍵盤響應(yīng)函數(shù),將得到的鍵值在液晶屏上顯示,。
void onKey(int nkey,, int fnkey)//鍵盤響應(yīng)函數(shù)
{
char temp[3];//轉(zhuǎn)換成ASC-II 的鍵值數(shù)組
if(nkey《9)
{
temp[0]=0x31;
temp[1]=(nkey-10)|0x30;
temp[2]=0;
}
else
{
temp[0]=nkey+0x30;
temp[1]=0;
}
LCD_printf(temp);//在液晶平上顯示鍵值
LCD_printf(“\n”);
}
(3)定義鍵盤掃描任務(wù),。
OS_STK My_Key_Scan_Stack[STACKSIZE]={0,, }; //定義鍵盤掃描任務(wù)的堆棧大小
void My_Key_Scan_Task(void *Id); //定義鍵盤掃描任務(wù)
#define MyKey_Scan_Task_Prio 58 //定義鍵盤掃描任務(wù)的優(yōu)先級
OSTaskCreate(My_Key_Scan_Task,(void*)0,,(OS_STK*)&My_Key_Scan_Stack[STACKSIZE-1],,
MyKey_Scan_Task_Prio );//在主函數(shù)中創(chuàng)建鍵盤掃描任務(wù)
void My_Key_Scan_Task(void *Id)//鍵盤掃描任務(wù)
{
U32 key;
u32 tempkey=0;
POSMSG pmsg;//創(chuàng)建消息
Uart_Printf(“begin key task \n”);
for (;;)
{
key=MyGetKey();
key&=0x000f;
if(key《9)
{
Uart_SendByte(0,0x31);
32
tempkey=key-10;
Uart_SendByte(0,,tempkey|=0x0030);
}
else
Uart_SendByte(0,key|0x0030);
Uart_Printf(“,,”);
pmsg=OSCreateMessage(NULL,, OSM_KEY,key,,key);//創(chuàng)建鍵盤消息
if(pmsg)
SendMessage(pmsg);//發(fā)送鍵盤消息
}
}
?。?)定義主任務(wù)。
OS_STK Main_Stack[STACKSIZE*8]={0,, };//定義主任務(wù)的堆棧大小
void Main_Task(void *Id); //定義主任務(wù)
#define Main_Task_Prio 12 //定義主任務(wù)的優(yōu)先級
OSTaskCreate(Main_Task,,(void*)0,(OS_STK*)&Main_Stack[STACKSIZE*8-1],,
Main_Task_Prio);//在主函數(shù)重創(chuàng)建主任務(wù)
void Main_Task(void *Id) //主任務(wù)
{
POSMSG pMsg=0;//創(chuàng)建消息
LCD_ChangeMode(DspTxtMode);//將液晶屏設(shè)為文本顯示摸式
LCD_Cls();//清屏
for(;;)
{
pMsg=WaitMessage(0); //等待消息
switch(pMsg-{
case OSM_KEY:
onKey(pMsg-break;
Delay(200);
}
DeleteMessage(pMsg);//刪除消息,,釋放資源
} }
注意:以上API接口函數(shù)只是原型 ;例子只作為參考