摘 要:嵌入式硬件的更新往往造成相應軟件系統需要重新開發。為解決這一問題,可以將嵌入式軟件系統建立在嵌入式操作系統之上,通過移植操作系統達到移植整個軟件系統的目的。將基于EP7312處理器的Nucleus嵌入式操作系統移植到基于XScale處理器的硬件環境中的過程,可以作為嵌入式操作系統在不同處理器上移植的參考。
關鍵詞:嵌入式操作系統; 移植; Nucleus
中圖法分類號:TP311.54文獻標識碼:A
文章編號:1001—3695(2007)02—0083—03
1 引言
Nucleus嵌入式實時操作系統是ATI公司的產品,它采用微內核技術,提供豐富的功能模塊,并且開放源碼[1]。在以往的工作中,我們以Nucleus為基礎開發了大量的軟件產品。但隨著硬件技術的發展,舊的芯片面臨淘汰,所以需要將Nucleus移植到新硬件環境中,使各種軟件產品可以不加改動地實現移植,從而大大縮短整個軟件系統的開發周期。
舊硬件環境是基于Cirrus Logic公司推出的EP7312處理器,它采用ARM 720T內核結構,被廣泛應用于各種嵌入式設備中[2];新硬件環境是基于Intel公司推出的XScale處理器,它采用ARM V5TE內核結構,處理能力較強,被廣泛應用于掌上設備中[3]。兩種處理器同屬ARM體系結構,具有相同的通用寄存器和中斷向量入口地址,而且都包含USER,SUP,IRQ,FIQ四種運行模式,為Nucleus移植提供了可行性。但由于兩種處理器基于不同的ARM體系結構版本和設計思路,存在很大的不同,主要表現在:①CPU控制寄存器不同;②協處理器不同;③內部中斷和外部中斷處理機制不同;④XScale的運行狀態較多。這些不同造成了基于EP7312的Nucleus操作系統不能直接在基于XScale的硬件環境中運行。
本文詳細介紹了將基于EP7312的Nucleus嵌入式操作系統移植到基于XScale的硬件環境中的過程,包含的主要步驟有:移植硬件初始化模塊;移植中斷處理模塊;移植進程調度模塊;移植操作系統時鐘等。本文的內容對嵌入式操作系統在不同硬件環境中的移植有較強的指導作用。
2 嵌入式操作系統移植
2.1 硬件初始化
硬件初始化從CPU上電開始到操作系統接管所有資源結束。經過總結,嵌入式系統硬件初始化部分主要包括Memory控制器初始化;時鐘初始化;內存管理單元(MMU)及Cache初始化;操作系統代碼搬移;堆棧初始化等幾大步驟。雖然不同硬件的初始化步驟大致相同,但由于具體實現存在較大差別,所以移植操作系統時需要在保證主要步驟不變的前提下重寫硬件初始化模塊。
EP7312與XScale的CPU控制器和協處理器不同,在移植Nucleus時,我們重寫了硬件初始化部分。下面逐個介紹硬件初始化的主要步驟:
(1)初始化Memory控制寄存器。因為程序代碼在Memory(SDRAM或Flash)中執行,若初始化錯誤將影響代碼的正確執行。Memory控制寄存器的初始化主要包括:①初始化靜態Memory(Flash);②初始化動態Memory(SDRAM)。初始化代碼主要配置Memory控制器的數據寬度、尋址方式、訪問速度、等待周期等參數。
(2)配置硬件系統時鐘及操作系統時鐘。時鐘初始化包括:①硬件時鐘使能,為CPU、Memory、設備控制器提供時鐘;②操作系統時鐘初始化,為軟件特別是操作系統提供時鐘。另外,在該步驟中可以對XScale的運行頻率和運行模式進行初始化。
(3)初始化MMU和Cache。在具備MMU單元的CPU初始化過程中該步驟比較重要,關系到整個軟件系統的正確運行。MMU和Cache初始化包含TLB地址映射表的建立、MMU及Cache使能、代碼跳轉,其主要通過控制協處理器完成。
TLB是一個表結構,被保存在SDRAM中。TLB包含了從實地址到虛地址的映射以及地址空間相應的Cache,Buffer等屬性信息。此外,MMU和Cache初始化部分還負責安排CPU地址空間的使用。最后,MMU使能過程中要考慮PC指針的問題,如果處理不好,在MMU使能后,由于地址發生改變,PC指針指向的位置可能不是正確的代碼。我們的解決辦法是將存放代碼的空間映射成其自身的地址。
(4)搬運代碼。在初始化好主要硬件之后,需要將代碼從靜態Memory(Flash)搬到SDRAM中運行,這是因為SDRAM的訪問速度通常比Flash快。代碼搬運與軟件編譯選項緊密相關,由于我們使用的是ADS 1.2版本的ARM編譯器[4],且操作系統與應用軟件編譯在同一個映像中,所以代碼搬運包括只讀代碼搬運、常量搬運、靜態變量搬運。通常在搬運完成后還要對代碼和變量進行重定位,比較麻煩。我們采用的辦法是在完成代碼從Flash搬運到SDRAM之后,通過MMU將Flash地址與SDRAM地址互換,從而省掉了代碼重定位的步驟。
(5)初始化堆棧。最后需要針對CPU的幾種狀態,即USER,SUP,IRQ,FIQ設定相應的堆棧。堆棧的位置設置如表1所示。
表1 堆??臻g安排
名 稱地 址 范 圍CPU模式
IRQ 棧System_Stack—(System_Stack+IRQ_STACK_SIZE)IRQ
FIQ棧IRQ stack end—(IRQ stack end+FIQ_STACK_SIZE)FIQ
SUP棧FIQ stack end—(FIQ stack end+SUP_STACK_SIZE)SUP
系統堆SUP stack end—(Memory total-frame buffer size-TLB size)SUP
堆棧的設置與原來EP7312的設置大致相同,不同點在于將LCD使用的幀緩存(Frame Buffer)和TLB放置在SDRAM的地址高端,所以需要在系統堆中減去它們所占用的空間。Nucleus沒有提供棧越界的保護機制,所以程序員要小心計算堆棧的大小,防止越界。
硬件初始化部分完成后將控制權交給操作系統,程序跳轉到INT_Initialize處繼續運行。
2.2 中斷處理
由于中斷模塊的接口經常被操作系統其他模塊及應用程序調用,所以在移植操作系統時必須保持原有中斷模塊的接口不變。中斷模塊的接口包括中斷響應、中斷申請、中斷使能/屏蔽等。
EP7312與XScale的中斷處理原理相同,都是通過中斷屏蔽寄存器、中斷狀態寄存器等實現控制的。但兩種CPU處理中斷的機制卻存在很大的不同,主要表現在:XScale使用通用輸入/輸出腳(GPIO2—80)檢測外部中斷,需要兩級中斷處理機制。由于Nucleus按照一級中斷模式處理中斷申請、響應、使能等,所以我們將XScale的所有中斷統一編碼,使每個中斷對應一個軟件中斷號。這樣,我們就可以按照原有的一級中斷處理方式統一處理所有中斷,從而保證中斷模塊接口不變。本節主要介紹IRQ中斷處理模塊的移植。
ARM體系結構CPU的中斷處理函數入口地址相同,從地址0x0開始依次為RST,UNDEF,SWI,PABORT,DABORT,IRQ,FIQ[5]。其中IRQ中斷的入口地址為0x00000018,我們通過編譯器將該地址定義為一個跳轉指令,使其跳轉到INT_IRQ_PARSE執行。在INT_IRQ_PARSE中,首先調用TCT_Interrupt_Context_Save保存CPU狀態、通用寄存器、棧指針(注意:進入IRQ狀態后使用IRQ棧)等;然后區分是否操作系統時鐘中斷,由于操作系統時鐘的移植在第2.4節中介紹,這里以其他中斷為例進行分析;最后,程序跳轉到Nucleus中斷處理函數irq_entry執行。
Irq_entry函數負責區分處理兩級中斷,即CPU內部中斷和GPIO外部中斷,其中GPIO2—80外部中斷會引發內部中斷IRQ10。Irq_entry的兩級中斷處理方式的偽代碼如下:
算法:Irq_entry
輸入:無
輸出:無
算法:{
int_num1=IRQ_GPIO0; //初始化一級號
int_num2=IRQ_GPIO(2)-2;
//初始化二級中斷號,二級中斷號排在一級中斷號之后
s=ICIP;
//ICIP寄存器每位代表一個中斷,相應位為1代表產生中斷
s>>=8; //ICIP寄存器低八位是保留位
while(s){
if(s1){
if(int_num1==IRQ_GPIO_2_80){//為二級中斷
根據GPIO狀態寄存器計算二級中斷號int_num2;
TCC_Dispatch_LISR(int_num2); //分發二級中斷}else//為一級中斷
TCC_Dispatch_LISR(int_num1); //分發一級中斷}
s>>=1;
int_num1++;}}
在設計時,我們將二級中斷號排在一級中斷號之后,配合中斷申請函數及分發函數,可以將具體的硬件中斷與操作系統能夠識別的中斷號對應起來,從而找到正確的處理函數。映射兩級中斷的相關宏定義如下:
#define PXA_IRQ_SKIP 8 /*保留的內部中斷*/
#define PXA_IRQ(x)((x)-PXA_IRQ_SKIP)/*一級中斷*/
#define GPIO_2_80_TO_IRQ(x) PXA_IRQ((x)-2+32)
/*二級中斷*/
2.3 調度
調度模塊是操作系統的核心,如果處理不好會造成系統崩潰。調度模塊的主要任務是正確處理CPU的各種狀態,其核心工作是保存和恢復CPU狀態。調度模塊的移植工作量較大,需要統籌安排CPU狀態、堆棧等,主要包括以下工作:
(1)中斷過程中CPU運行模式的切換、CPU當前狀態的保存與恢復、棧的保存與恢復以及CPU中斷開關等操作。
(2)進程調度模塊中由進程創建、退出、切換等引起的CPU運行模式切換、CPU當前狀態保存與恢復、棧保存與恢復。
(3)核心程序及用戶程序交替運行過程中引起的CPU運行模式切換、CPU當前狀態保存與恢復、棧保存與恢復。
其中(1)和(2)在移植Nucleus的過程中需要改動;而(3)由于Nucleus應用程序在SUP模式下運行,所以不需要處理相應的CPU模式、狀態及棧變化。
XScale與EP7312的不同主要體現在CPU內部狀態定義的不同,如CPSR[6]的定義,另外,XScale CPU的工作模式較多。我們根據Nucleus的調度模塊適當作了簡化,僅使用SUP,IRQ,FIQ及各種異常狀態,且讓CPU始終工作在具有較高頻率的Turbo模式下。這里以屏蔽中斷和切換CPU運行模式為例介紹移植工作。關CPU中斷定義如下:
MRS a2,CPSR;讀取當前程序狀態寄存器CPSR
ORRa2,a2,#LOCKOUT;置屏蔽IRQ和FIQ中斷位
MSRCPSR_cxsf,a2;關中斷
這里關中斷是指關CPU的中斷響應而非更改中斷控制寄存器的相應位。因為通過中斷控制寄存器關中斷后CPU還是會響應中斷,從而造成CPU狀態及棧的變化,所以在調度模塊中通常直接關CPU中斷響應。
CPU在用戶程序運行及系統程序運行時均處于SUP模式,只有在產生了中斷或異常后會進入FIQ,IRQ等狀態。CPU運行模式切換定義如下:
MRSa1,CPSR;讀取當前程序狀態寄存器CPSR
BICa1,a1,#MODE_MASK;清CPU狀態位
ORRa1,a1,#SUP_MODE;置CPU狀態位SVC
MSRCPSR_cxsf,a1;切換CPU狀態
2.4 操作系統時鐘
操作系統時鐘中斷是操作系統運行的脈動,它負責驅動核心的各種定時器、觸發進程調度、產生信號等。正確的時鐘中斷處理是核心正常運行的保證,對該模塊的任何改動都有可能影響整個操作系統的運行,所以在移植的過程中應盡量保持原有的接口。通過深入了解時鐘模塊的運行機制我們發現,可以在移植的過程中保持原有的處理流程和接口,只需要改動與XScale相關的小部分代碼即可。
XScale提供四個OS時鐘。由于Nuclues系統只需一個時鐘中斷,所以只使用了OST0。OST0的設置過程如下:
(1)配置時鐘信號使能寄存器,產生OST0所需要的時鐘信號。
(2)配置OST0寄存器,使OST0在需要的時間間隔之后產生中斷。
(3)使能OST0中斷,產生OST0溢出中斷。
(4)在時鐘中斷處理結束后重新設置溢出寄存器、中斷控制寄存器。
改動主要集中在對時鐘中斷的處理上。時鐘中斷發生后的主要處理步驟如下:
ldr a2,=OST_OSSR_REG
mova1,#0x1
stra1,[a2];清中斷狀態位,使時鐘產生下一次中斷
ldra2,=OST_OSCR_REG
ldra1,[a2]
adda1,a1,#36864
;根據OSCR值,計算得到下一次時鐘中斷的計數
ldra2,=OST_OSMR0_REG
stra1,[a2]
;將計數寫入OSMR,OSCR與OSMR值相同時產生中斷
BLTMT_Timer_Interrupt;操作系統時鐘處理,與原有接口相同
3 總結
本文以Nucleus嵌入式操作系統和XScale處理器為例介紹了嵌入式操作系統移植的主要部分,包括硬件初始化模塊移植、中斷處理模塊移植、進程調度模塊移植、操作系統時鐘移植。移植后的操作系統保留了原有軟件接口,使應用軟件能夠不加改動地在新的硬件環境中運行,從而大大縮短了整個嵌入式系統的開發周期。本文的工作對嵌入式操作系統在不同硬件環境中的移植有較強的指導作用。
本文中所涉及到的圖表、注解、公式等內容請以PDF格式閱讀原文。