uC/OS-II嵌入式操作系統移植

操作系統的移植指的是使實時系統的內核能在微處理器上運行。uC/OS-II應移植到所使用的CPU上,然後才能得到應用。在uC/OS-II的移植中,處理器必須滿足一下一些要求:
l         處理器的C編譯器能產生可重入型代碼
l         處理器支持中斷,並且能產生定時中斷
l         用C語言就可以開/關中斷
l         處理器能支持一定數量的數據存儲硬件堆棧
l         處理器有將堆棧指針以及其他CPU寄存器的內容讀出,並存儲到堆棧或內存中去的指令
實際上,uC/OS-II可以簡單地看作是一個多任務調度器,在這個任務調度器上添加了與多任務操作系統相關的一些系統服務,如信號量、郵箱等。其90%的代碼是用C語言寫的,可以直接移植到有C語言編譯器的處理器上。移植主要都集中在多任務切換的實現上,因爲這部分代碼用來保存和恢復CPU現場(即寫/讀相關寄存器),不能用C語言,只能使用彙編語言完成,即編寫OS_CPU_A.S文件。另外還需要修改與ARM體系結構相關的OS_CPU.H文件和用戶規定任務棧初始化結構的OS_CPU_C.C文件。uC/OS-II的移植工作相對來說還是很容易的,具體的移植過程如下:
INCLUDES.H是一個主頭文件,本身與移植過程無關,不過因爲每一個uC/OS-II的C文件都要用到它,故在此簡介一下。INCLUDES.H包含程序中主要的三個頭文件,分別是:OS_CPU.H,OS_CFG.H,UCOS_II.H。它使得工程項目中的每個C文件無需考慮它實際上需要哪些頭文件,增強了可讀性。另外也可以重新編輯此文件添加用戶自己定義的頭文件。
這個頭文件包括了用#define語句定義的與處理器相關的常數/宏以及類型等,其中包括臨界段代碼宏定義:OS_ENTER_CRITICAL( )和OS_EXIT_CRITICAL( ),並可以提供三種辦法開關中斷。具體代碼如下:
 
#include "arm.h"
 
#ifdef OS_CPU_GLOBALS
#define OS_CPU_EXT
#else
#define OS_CPU_EXT extern
#endif
 
typedef unsigned char BOOLEAN;    /**/
typedef unsigned char INT8U;
typedef signed char   INT8S;
typedef unsigned short  INT16U;
typedef signed     short INT16S;
typedef unsigned long  INT32U;
typedef signed long    INT32S;
typedef float          FP32;
typedef double        FP64;
typedef unsigned int   OS_STK;
typedef unsigned int   OS_CPU_SR;
 
#define BYTE           INT8S
#define UBYTE          INT8U
#define WORD          INT16S
#define UWORD         INT16U
#define LONG          INT32S
#define ULONG         INT32U
 
#define OS_CRITICAL_METHOD    1 /**/
#if      OS_CRITICAL_METHOD == 1
#define  OS_ENTER_CRITICAL() ARMDisableInt1()   /* Disable interrupts*/                       
#define  OS_EXIT_CRITICAL()   ARMEnableInt1()    /* Enable interrupts*/
#endif
#if      OS_CRITICAL_METHOD == 2
#define  OS_ENTER_CRITICAL() ARMDisableInt2()   /* Disable interrupts*/                       
#define  OS_EXIT_CRITICAL()   ARMEnableInt2()    /* Enable interrupts*/
#endif
#if      OS_CRITICAL_METHOD == 3
#define  OS_ENTER_CRITICAL() ARMDisableInt3()   /* Disable interrupts*/                       
#define  OS_EXIT_CRITICAL()   ARMEnableInt3()    /* Enable interrupts*/
#endif
/* , */
#define OS_STK_GROWTH    1
#define OS_TASK_SW()        OSTaskSw()
#ifdef SEMIHOSTED
#define OS_IDLE_STK_SIZE        (64+SEMIHOSTED_STACK_NEEDS)
#else
#define OS_IDLE_STK_SIZE        64
#endif
/* */
extern void OSTaskSw(void);
extern void OSIntCtxSw(void);
extern void ARMDisableInt1(void);
extern void ARMEnableInt1(void);
extern void ARMDisableInt2(void);
extern void ARMEnableInt2(void);
extern void ARMDisableInt3(void);
extern void ARMEnableInt3(void);
extern void OSTickISR(void);
extern void SP_Compensate(void);
 
移植首先包括一系列數據類型的定義,以適應不同微處理器的字長。uC/OS-II的代碼中不使用C語言的short,int等數據類型,因爲這些數據類型是與處理器相關,不可移植的。程序代碼中定義的數據類型字長應根據處理器C編譯器規定的數據類型字長而定。上面的數據類型移植是根據ADS編譯器對C語言各類型的字長要求定義的。其中,OS_STK是任務堆棧數據類型,在ARM中它是32位的,OS_CPU_SR是CPU狀態寄存器寬度,它也是32位的。
OS_ENTER_CRITICAL( )和OS_EXIT_CRITICAL( )是用來設置臨界段代碼的函數。OS_ENTER_CRITICAL( )使系統進入臨界段,這時要求系統內核先關閉中斷,再處置臨界段代碼,保護臨界段代碼不受多任務或中斷服務子程序破壞。推出臨界段時調用OS_EXIT_CRITICAL( ),系統重新開中斷,進行正常任務調度。通常以上兩個函數可以用3種方法實現,OS_CPU_H中定義了一個OS_CRITICAL_METHOD常數,用來選擇函數實現的方法。常數值爲1時,採用最簡單的方法,OS_ENTER_CRITICAL( )中直接調用處理器指令關閉中斷,OS_EXIT_CRITICAL( )調用相應處理器指令開中斷(詳細的代碼在os_cpu_a.s文件中定義)。這樣做存在一個問題:如果調用函數時系統禁止中斷,那當臨界段代碼執行完畢後系統中斷會變成允許了。常數值爲2時,執行OS_ENTER_CRITICAL( )時會先將中斷狀態保存到堆棧中,然後關中斷,執行OS_ENTER_CRITICAL( )時從堆棧中恢復原來的中斷狀態。這樣做解決了方法1中存在的問題。常數值爲3時需要多定義一個cpu_sr的局部變量,用於某些能直接得到當前處理器狀態字的編譯器中,保存狀態字,用來恢復PSW。由於應用簡單,方法1,2已經足夠,所以本文中沒有實現方法3的具體代碼,而使方法3和方法2實現的代碼一致。這裏可以以後再擴充。
OS_STK_GROWTH常數定義了堆棧的方向,值爲0時表示堆棧從下往上遞增,爲1時表示堆棧從上往下遞減。本次移植中的堆棧結構使用從上往下遞減方式,故此宏的值定義爲1。OS_TASK_SW( )是一個宏,是在uC/OS-II從低優先級切換到高優先級任務時用到的,此處定義成任務調度函數OSTaskSw( ),實現從低優先級任務切換到高優先級任務的工作。
本文件要求用戶編寫10個簡單函數,其中必要的函數是OSTaskStkInit( ),其它函數只要聲明即可。代碼如下:
OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
    unsigned int *stk ;
    opt = opt;       /* */
    stk = (unsigned int *)ptos;    /**/
    /* */
    *--stk = (unsigned int) task;             /* lr */
    *--stk = 0;                         /* r12 */
    *--stk = 0;                         /* r11 */
    *--stk = 0;                         /* r10 */
    *--stk = 0;                         /* r9 */
    *--stk = 0;                         /* r8 */
    *--stk = 0;                         /* r7 */
 
發佈了50 篇原創文章 · 獲贊 10 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章