ucos ii嵌入式操作系統(tǒng)的分析和移植實例

2013-08-28 17:35 來源:電子信息網 作者:鈴鐺

ucos ii的特點

1.ucos ii是由Labrosse先生編寫的一個開放式內核,最主要的特點就是源碼公開。這一點對于用戶來說可謂利弊各半,好處在于,一方面它是免費的,另一方面用戶可以根據自己的需要對它進行修改。缺點在于它缺乏必要的支持,沒有功能強大的軟件包,用戶通常需要自己編寫驅動程序,特別是如果用戶使用的是不太常用的單片機,還必須自己編寫移植程序。

2.ucos ii是一個占先式的內核,即已經準備就緒的高優(yōu)先級任務可以剝奪正在運行的低優(yōu)先級任務的CPU使用權。這個特點使得它的實時性比非占先式的內核要好。通常我們都是在中斷服務程序中使高優(yōu)先級任務進入就緒態(tài)(例如發(fā)信號),這樣退出中斷服務程序后,將進行任務切換,高優(yōu)先級任務將被執(zhí)行。拿51單片機為例,比較一下就可以發(fā)現這樣做的好處。假如需要用中斷方式采集一批數據并進行處理,在傳統(tǒng)的編程方法中不能在中斷服務程序中進行復雜的數據處理,因為這會使得關中斷時間過長。所以經常采用的方法是置一標志位,然后退出中斷。由于主程序是循環(huán)執(zhí)行的,所以它總有機會檢測到這一標志并轉到數據處理程序中去。但是因為無法確定發(fā)生中斷時程序到底執(zhí)行到了什么地方,也就無法判斷要經過多長時間數據處理程序才會執(zhí)行,中斷響應時間無法確定,系統(tǒng)的實時性不強。如果使用μC/OS-II的話,只要把數據處理程序的優(yōu)先級設定得高一些,并在中斷服務程序中使它進入就緒態(tài),中斷結束后數據處理程序就會被立即執(zhí)行。這樣可以把中斷響應時間限制在一定的范圍內。對于一些對中斷響應時間有嚴格要求的系統(tǒng),這是必不可少的。但應該指出的是如果數據處理程序簡單,這樣做就未必合適。因為ucos ii要求在中斷服務程序末尾使用OSINTEXIT函數以判斷是否進行任務切換,這需要花費一定的時間。

3.ucos ii和大家所熟知的Linux等分時操作系統(tǒng)不同,它不支持時間片輪轉法。ucos ii是一個基于優(yōu)先級的實時操作系統(tǒng),每個任務的優(yōu)先級必須不同,分析它的源碼會發(fā)現,ucos ii把任務的優(yōu)先級當做任務的標識來使用,如果優(yōu)先級相同,任務將無法區(qū)分。進入就緒態(tài)的優(yōu)先級最高的任務首先得到CPU的使用權,只有等它交出CPU的使用權后,其他任務才可以被執(zhí)行。所以它只能說是多任務,不能說是多進程,至少不是我們所熟悉的那種多進程。顯而易見,如果只考慮實時性,它當然比分時系統(tǒng)好,它可以保證重要任務總是優(yōu)先占有CPU。但是在系統(tǒng)中,重要任務畢竟是有限的,這就使得劃分其他任務的優(yōu)先權變成了一個讓人費神的問題。另外,有些任務交替執(zhí)行反而對用戶更有利。例如,用單片機控制兩小塊顯示屏時,無論是編程者還是使用者肯定希望它們同時工作,而不是顯示完一塊顯示屏的信息以后再顯示另一塊顯示屏的信息。這時候,要是ucos ii即支持優(yōu)先級法又支持時間片輪轉法就更合適了。

4.ucos ii對共享資源提供了保護機制。正如上文所提到的,ucos ii是一個支持多任務的操作系統(tǒng)。一個完整的程序可以劃分成幾個任務,不同的任務執(zhí)行不同的功能。這樣,一個任務就相當于模塊化設計中的一個子模塊。在任務中添加代碼時,只要不是共享資源就不必擔心互相之間有影響。而對于共享資源(比如串口),ucos ii也提供了很好的解決辦法。一般情況下使用的是信號量的方法。簡單地說,先創(chuàng)建一個信號量并對它進行初始化。當一個任務需要使用一個共享資源時,它必須先申請得到這個信號量,而一旦得到了此信號量,那就只有等使用完了該資源,信號量才會被釋放。在這個過程中即使有優(yōu)先權更高的任務進入了就緒態(tài),因為無法得到此信號量,也不能使用該資源。這個特點的好處顯而易見,例如當顯示屏正在顯示信息的時候,外部產生了一個中斷,而在中斷服務程序中需要顯示屏顯示其他信息。這樣,退出中斷服務程序后,原有的信息就可能被破壞了。而在μC/OS-II中采用信號量的方法時,只有顯示屏把原有信息顯示完畢后才可以顯示新信息,從而可以避免這個現象。不過,采用這種方法是以犧牲系統(tǒng)的實時性為代價的。如果顯示原有信息需要耗費大量時間,系統(tǒng)只好等待。從結果上看,等于延長了中斷響應時間,這對于未顯示信息是報警信息的情況,無疑是致命的。發(fā)生這種情況,在μC/OS-II中稱為優(yōu)先級反轉,就是高優(yōu)先級任務必須等待低優(yōu)先級任務的完成。在上述情況下,在兩個任務之間發(fā)生優(yōu)先級反轉是無法避免的。所以在使用ucos ii時,必須對所開發(fā)的系統(tǒng)了解清楚,才能決定對于某種共享資源是否使用信號量。

ucos ii在單片機使用中的一些特點

1.在單片機系統(tǒng)中嵌入ucos ii將增強系統(tǒng)的可靠性,并使得調試程序變得簡單。以往傳統(tǒng)的單片機開發(fā)工作中經常遇到程序跑飛或是陷入死循環(huán)。可以用看門狗解決程序跑飛問題,而對于后一種情況,尤其是其中牽扯到復雜數學計算的話,只有設置斷點,耗費大量時間來慢慢分析。如果在系統(tǒng)中嵌入 ucos ii的話,事情就簡單多了??梢园颜麄€程序分成許多任務,每個任務相對獨立,然后在每個任務中設置超時函數,時間用完以后,任務必須交出 CPU的使用權。即使一個任務發(fā)生問題,也不會影響其他任務的運行。這樣既提高了系統(tǒng)的可靠性,同時也使得調試程序變得容易。

2.在單片機系統(tǒng)中嵌入ucos ii將增加系統(tǒng)的開銷?,F在所使用的51單片機,一般是指87C51或者89C51,其片內都帶有一定的RAM和 ROM。對于一些簡單的程序,如果采用傳統(tǒng)的編程方法,已經不需要外擴存儲器了。如果在其中嵌入ucos ii的話,在只需要使用任務調度、任務切換、信號量處理、延時或超時服務的情況下,也不需要外擴ROM了,但是外擴RAM是必須的。由于ucos ii是可裁減的操作系統(tǒng),其所需要的RAM大小就取決于操作系統(tǒng)功能的多少。舉例來說,μC/OS-II允許用戶定義最大任務數。由于每建立一個任務,都要產生一個與之相對應的數據結構TCB,該數據結構要占用很大一部分內存空間。所以在定義最大任務數時,一定要考慮實際情況的需要。如果定得過大,勢必會造成不必要的浪費。嵌入ucos ii以后,總的RAM需求可以由如下表達式得出:

RAM總需求=應用程序的RAM需求+內核數據區(qū)的RAM需求+(任務棧需求+最大中斷嵌套棧需求)·任務數

所幸的是,μC/OS-II可以對每個任務分別定義堆棧空間的大小,開發(fā)人員可根據任務的實際需求來進行??臻g的分配。但在RAM容量有限的情況下,還是應該注意一下對大型數組、數據結構和函數的使用,別忘了,函數的形參也是要推入堆棧的。

3.ucos ii的移植也是一件需要值得注意的工作。如果沒有現成的移植實例的話,就必須自己來編寫移植代碼。雖然只需要改動兩個文件,但仍需要對相應的微處理器比較熟悉才行,最好參照已有的移植實例。另外,即使有移植實例,在編程前最好也要閱讀一下,因為里面牽扯到堆棧操作。在編寫中斷服務程序時,把寄存器推入堆棧的順序必須與移植代碼中的順序相對應。

4.和其他一些著名的嵌入式操作系統(tǒng)不同,ucos ii在單片機系統(tǒng)中的啟動過程比較簡單,不像有些操作系統(tǒng)那樣,需要把內核編譯成一個映像文件寫入ROM中,上電復位后,再從ROM中把文件加載到RAM中去,然后再運行應用程序。ucos ii的內核是和應用程序放在一起編譯成一個文件的,使用者只需要把這個文件轉換成HEX格式,寫入ROM中就可以了,上電后,會像普通的單片機程序一樣運行。

結語

由以上介紹可以看出,ucos ii具有免費、使用簡單、可靠性高、實時性好等優(yōu)點,但也有移植困難、缺乏必要的技術支持等缺點,尤其不像商用嵌入式系統(tǒng)那樣得到廣泛使用和持續(xù)的研究更新。但開放性又使得開發(fā)人員可以自行裁減和添加所需的功能,在許多應用領域發(fā)揮著獨特的作用。當然,是否在單片機系統(tǒng)中嵌入ucos ii應視所開發(fā)的項目而定,對于一些簡單的、低成本的項目來說,就沒必要使用嵌入式操作系統(tǒng)了。

44B0下ucos-ii的移植

要保證ucos Ⅱ移植到微處理器后能正確運行;處理器需具備如下特性:

1) 處理器的c編譯器支持可重入函數

可重入的代碼指的是一段代碼(如一個函數)可以被多個任務同時調用,而不必擔心會破壞數據。也就是說,可重入型函數在任何時候都可以被中斷執(zhí)行,過一段時間以后又可以繼續(xù)運行,而不會因為在函數中斷的時候被其他的任務重新調用,影響函數中的數據。下面的兩個例子可以比較可重入型函數和非可重入型函數:

程序1:可重入型函數

void swap(int *x, int *y)

int temp;

temp=*x;

*x=*y;

*y=temp;

程序2:非可重入型函數

int temp;

void swap(int *x, int *y)

temp=*x;

*x=*y;

*y=temp;

程序1 中使用的是局部變量temp 作為變量。通常的C 編譯器,把局部變量分配在棧中。

所以,多次調用同一個函數,可以保證每次的temp 互不受影響。而程序2 中temp 定義的是全局變量,多次調用函數的時候,必然受到影響。代碼的可重入性是保證完成多任務的基礎,除了在C 程序中使用局部變量以外,還需要C 編譯器的支持。筆者使用的是ARM SDT 以及ADS 的集成開發(fā)環(huán)境,均可以生成可重入的代碼。

2)在程序中可以打開和關閉中斷

在ucos Ⅱ中,可以通過OS_ENTER_CRITICAL()或者OS_EXIT_CRITICAL()宏來控制

系統(tǒng)關閉或者打開中斷。這需要處理器的支持,在ARM7TDMI 的處理器上,可以設置相應的寄存器來關閉或者打開系統(tǒng)的所有中斷。

3)處理器支持中斷,并且能產生定時器中斷(ucos Ⅱ是通過定時器中斷來實現多任務的調度,即時間片的產生 )ucos Ⅱ 是通過處理器產生的定時器的中斷來實現多任務之間的調度的。在ARM7TDMI 的處理器上可以產生定時器中斷。

4)處理器要具有一定的硬件堆棧數量

5)處理器要有將堆棧指針和其他cpu寄存器存儲和讀出堆棧(或者內存)的指令(如51的pop,push指令)。

ucos Ⅱ進行任務調度的時候,會把當前任務的CPU 寄存器存放到此任務的堆棧中,然后,再從另一個任務的堆棧中恢復原來的工作寄存器,繼續(xù)運行另一個任務。所以,寄存器的入棧和出棧是ucos Ⅱ多任務調度的基礎。

ARM7TDMI 處理器完全滿足上述要求。

接下來將介紹如何把ucos Ⅱ移植到Samsung公司的一款ARM7TDMI 的嵌入式處理器——S3C44B0X 上。

ucos Ⅱ中與處理器有關的代碼:os_cpu.h os_cpu_a.asm os_cpu_c.c

ucos Ⅱ的設置 : os_cfg.h inludes.h

ucos Ⅱ在44b0上的移植

1)設置inludes.h中與處理器及編譯器有關的代碼

FORADS

#include “os_cpu.h”

#include “os_cfg.h”

#include “ucos_ii.h”

這里未做處理 取默認的數據類型。

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);

********************************************************************************

其他人的應用修改事例:

#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

因為不同的微處理器有不同的字長,所以ucos Ⅱ的移植包括了一系列的類型定義以確

保其可移植性。尤其是ucos Ⅱ代碼從不使用C 的short,int 和long 等數據類型,因為它們是與編譯器相關的,不可移植。相反的,我們定義的整形數據結構既是可移植的又是直觀的。為了方便,雖然ucos Ⅱ不是用浮點數據,但我們還是定義了浮點數據類型。

例如,INT16U 數據類型總是代表16 位的無符號整數?,F在,ucos Ⅱ和用戶的應用程序就可以估計出聲明為該數據類型的變量的取值范圍是0~65535。將ucos Ⅱ移植到32 位的處理器上也就意味著INT16U 實際被聲明為無符號短整形數據結構而不是無符號整數數據結構。但是,μC/OS-Ⅱ所處理的仍然是INT16U。用戶必須將任務堆棧的數據類型告訴給μC/OS-Ⅱ。這個過程是通過為OS_STK 聲明正確的C 數據類型來完成的。我們的處理器上的堆棧成員是16 位的,所以將OS_TSK 聲明為無符號整形數據類型。所有的任務堆棧都必須用OS_TSK 聲明數據類型。

2)OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()

與所有的實時內核一樣,μC/OS-Ⅱ需要先禁止中斷再訪問代碼的臨界區(qū),并且在訪問完

畢后重新允許中斷。這就使得μC/OS-Ⅱ能夠保護臨界區(qū)代碼免受多任務或中斷服務例程

(ISR)的破壞。在S3C44B0X 上是通過兩個函數(OS_CPU_A.S)實現開關中斷的。

INTS_OFF

mrs r0, cpsr ; 當前CSR

mov r1, r0 ; 復制屏蔽

orr r1, r1, #0xC0 ; 屏蔽中斷位

msr CPSR, r1 ; 關中斷(IRQ and FIQ)

and r0, r0, #0x80 ; 從初始CSR 返回FIQ 位

mov pc,lr ; 返回

INTS_ON

mrs r0, cpsr ; 當前CSR

bic r0, r0, #0xC0 ; 屏蔽中斷

msr CPSR, r0 ; 開中斷(IRQ and FIQ)

mov pc,lr ; 返回

3)OS_STK_GROWTH

絕大多數的微處理器和微控制器的堆棧是從上往下長的。但是某些處理器是用另外一種方式工作的。μC/OS-Ⅱ被設計成兩種情況都可以處理,只要在結構常量OS_STK_GROWTH中指定堆棧的生長方式就可以了。

置OS_STK_GROWTH 為0 表示堆棧從下往上長。

置OS_STK_GROWTH 為1 表示堆棧從上往下長。

用c語言編寫6個與操作系統(tǒng)相關的函數(OS_CPU_C.C)

1 2 3 > 
嵌入式操作系統(tǒng) ucos ii

相關閱讀

暫無數據

一周熱門