S3C2416裸機開發(fā)系列十五_GCC下uCOS的移植(1)
操作系統(tǒng)是用來管理系統(tǒng)硬件、軟件及數據資源,控制程序運行,并為其它應用軟件提供支持的一種系統(tǒng)軟件。根據不同的種類,又可分為實時操作系統(tǒng)、桌面操作系統(tǒng)、服務器操作系統(tǒng)等。對于一些小型的應用,對系統(tǒng)實時性要求高,硬件資源有限等的情況下,應盡量避免使用復雜龐大的操作系統(tǒng)(如Linux),使用小型的實時操作系統(tǒng)(如uCOS)更能滿足應用的需求。筆者此處就uCOS-II的移植作一個簡單的介紹。
1. 代碼準備uCOS-II V2.91源碼,這個版本的源碼是uCOS-II的最新版本,請讀者自行從Micrium官網或其它網站下載這個版本的源碼,當然,其它版本的uCOS-II也是一樣方式移植的。Micrium官網也給出了一些cpu的移植范例,可供參考,此處是下載源碼,一步一步進行移植。
s3c2416啟動代碼工程,啟動代碼是s3c2416/50/51這系列arm9芯片在運行用戶c代碼main函數之前必須先運行的代碼,啟動代碼支持sd、Nand啟動,為用戶設置系統(tǒng)時鐘,初始化內存,自動識別啟動設備并搬移代碼到RAM,MMU映射,中斷管理等,用戶只需專注于用c開發(fā)其它功能函數即可。關于啟動代碼以及啟動代碼的實現過程,筆者前面章節(jié)有非常詳細的介紹。此處以GCC下移植uCOS為講解,下載”GCC啟動代碼工程應用實例”中的啟動代碼源碼即可。如果在MDK下開發(fā),下載”MDK啟動代碼工程應用實例”中的啟動代碼源碼。
用戶代碼,用c開發(fā)的所有功能代碼,其中,用戶代碼入口為main()函數,在這里實現uCOS多任何運行代碼。
2. 工程搭建在linux操作系統(tǒng)下任一路徑下新建一個uCOS的工程目錄,該目錄下新建uCOS-II目錄用來保存uCOS相關部分。下載uCOS-II V2.91源碼并解壓,把Source目錄全部拷貝到uCOS-II目錄下,同時在目錄下新建一個Cfg目錄用來保存uCOS的配置文件,新建一個Ports目錄用來保存uCOS移植接口文件。
把啟用代碼目錄start_code拷貝到UCGUI目錄下,這部分代碼無需任何的修改。并保留其中的Makefile這些文件。GCC啟動代碼下的工程管理Makefile提取自uboot,可以方便地增加源代碼以及代碼目錄。
在UCGUI目錄下新建apps目錄,用來保存應用相關的源碼。
最終的UCGUI目錄內容如下:
uCOS/start_code,保存s3c2416啟動代碼相關的部分
uCOS/app,保存工個工程的應用部分
uCOS/uCOS-II/Cfg,保存uCOS的配置部分
uCOS/uCOS-II/Ports,保存uCOS移植部分
uCOS/uCOS-II/Source,保存uCOS的源碼,通常可直接替換更高版本的源碼
3. uCOS移植uCOS-II應用在不同的cpu,需要在uCOS-II/Ports目錄中實現os_cpu.h、os_cpu_a.s、os_cpu_c.c這三個文件的修改編寫。
3.1. os_cpu.h的編寫3.1.1. 外部聲明uCOS-II用OS_CPU_GLOBALS和OS_CPU_EXT來聲明外部的變量、符號,這部分如下:
#ifdef OS_CPU_GLOBALS
#define OS_CPU_EXT
#else
#define OS_CPU_EXT extern
#endif
3.1.2. 數據類型定義為了確保uC/OS-II的可移植性,在os_cpu.h中聲明了一系列的類型定義。這些類型不依賴于c數據類型如int、short、long等。數據類型定義如下:
typedef unsigned char BOOLEAN; /* 布爾變量*/
typedef unsigned charINT8U; /* 無符號8位整型變量*/
typedef signed char INT8S; /* 有符號8位整型變量*/
typedef unsigned shortINT16U; /* 無符號16位整型變量*/
typedef signed shortINT16S; /* 有符號16位整型變量*/
typedef unsigned int INT32U; /* 無符號32位整型變量*/
typedef signed int INT32S; /* 有符號32位整型變量*/
typedef float FP32; /* 單精度浮點數(32位長度)*/
typedef double FP64; /* 雙精度浮點數(64位長度)*/
3.1.3. 棧配置uCOS-II適用于8位、16位、32位的cpu,不同字長的cpu,其棧字長也是不一樣的,uCOS-II用OS_STK表棧類型,同時棧的生長方式可以由高地址到低地址,也可由低地址到高地址。對于arm架構cpu,??梢韵蛳拢部梢韵蛏显鲩L。但對于各個編譯器是約定棧由高地址向低地址增長的,棧字長為32位。棧配置內容如下:
typedef INT32U OS_STK; /* 棧是32位寬度*/
#define OS_STK_GROWTH 1 /* 棧是從高往下生長*/
3.1.4. 臨界區(qū)訪問對于可搶占式操作系統(tǒng),有一小段關鍵代碼必須獨占訪問,如果有一個任務(線程)正在訪問臨界代碼,則其它任務(線程)不能再進入該段代碼,直到占有訪問權的任務(線程)退出這個臨界區(qū)。uCOS-II在訪問內核臨界區(qū)時是通過OS_ENTER_CRITICAL()/OS_EXIT_CRITICAL()這兩個宏開關中斷來禁止任務搶占來確保臨界區(qū)不被破壞。通常,臨界區(qū)訪問有三種方式,一是直接開關中斷,二是從棧中保存/恢復中斷狀態(tài)再開關中斷,三是從局部變量保存/恢復中斷狀態(tài)再開關中斷。uCOS-II采用了第三種開關中斷方式,需實現狀態(tài)保存恢復開關中斷CPU_SR_Save()/CPU_SR_Restore(),需引入一個OS_CPU_SR類型的變量保存cpu中斷狀態(tài),臨界區(qū)中斷訪問內容如下:
#define OS_CRITICAL_METHOD 3 /*局部變量保存/恢復狀態(tài)再開關中斷 */
typedef INT32U OS_CPU_SR; /*開關中斷前用來保存/恢復中斷狀態(tài)*/
#define OS_ENTER_CRITICAL() {cpu_sr =CPU_SR_Save ();} /* 關中斷 */
#define OS_EXIT_CRITICAL() {CPU_SR_Restore (cpu_sr);} /* 開中斷*/
3.1.5. 函數聲明uCOS-II需匯編實現開關中斷、任務切換這些與體系結構相關的功能,在匯編文件os_cpu_a.s中進行實現,頭文件進行函數聲明,聲明有如下幾個函數:
#define OS_TASK_SW() OSCtxSw() /* 任務級任務切換函數*/
OS_CPU_SR CPU_SR_Save(void);
void CPU_SR_Restore(OS_CPU_SR cpu_sr);
void OSStartHighRdy(void);
void OSCtxSw(void);
void OSIntCtxSw(void);
3.2. os_cpu_a.s的編寫高級語言不能實現保存/恢復寄存器,因此uCOS-II需要編寫匯編實現六個簡單的函數,CPU_SR_Save ()、CPU_SR_Restore()、OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()、IRQ_SaveContext()。
3.2.1. CPU_SR_Save()函數由于采用從局部變量保存/恢復中斷狀態(tài)再開關中斷的方式,用R0返回中斷狀態(tài),并關閉中斷,該函數是OS_ENTER_CRITICAL()的宏實現。
.globl CPU_SR_Save
CPU_SR_Save:
MRS R0, CPSR
ORR R1, R0, #0xC0 // 設置IRQ,FIQ均禁止中斷
MSR CPSR_c, R1
BX LR // 禁止中斷,返回中斷狀態(tài)到R0中
3.2.2. CPU_SR_Restore()函數臨界區(qū)訪問完后,需恢復關中斷前的中斷狀態(tài),該函數是OS_EXIT_CRITICAL()的宏實現。
.globl CPU_SR_Restore
CPU_SR_Restore:
MSR CPSR_c, R0
BX LR
3.2.3. OSStartHighRdy()函數當用戶通過OSStart()啟動uCOS內核進行管理時,OSStart()會首先調用OSStartHighRdy()來運行已創(chuàng)建任務中優(yōu)先級最高的任務,OSStartHighRdy()需完成以下工作:
(1) 禁止中斷切換到管理模式,所有任務均工作在管理模式
(2) 調用任務切換鉤子函數,即先調用OSTaskSwHook()函數
(3) 標記uCOS-II內核已啟動運行,OSRunning = 1
(4) 獲得最高優(yōu)先級任務TCB,得到任務棧指針,SP切換到任務棧
(5) 出棧SP中的任務棧,包括任務狀態(tài)寄存器CPSR,R0-R12,LR,繼續(xù)執(zhí)行任務。
#define I_Bit 0x80// IRQ中斷禁止位
#define F_Bit 0x40// FIQ中斷禁止位
#define Mode_SVC 0x13 // 管理模式
#define Mode_SYS 0x1f // 系統(tǒng)模式
.extern OSTaskSwHook
.extern OSRunning
.extern OSTCBHighRdy
.globl OSStartHighRdy
OSStartHighRdy:
MSR CPSR_c, #(I_Bit+F_Bit+Mode_SVC) // 禁止中斷切換到管理模式
LDR R0, =OSTaskSwHook // 調用任務切換鉤子函數
MOV LR, PC // 準備函數返回地址