Skip to main content

Embedded Linux簡介

在近幾年的電腦發展趨勢裡面,Linux已經從伺服器或桌上型市場跨足到嵌入式(embedded)的環境。而這些所謂的嵌入式裝置,在大部分的情況下, 其運算能力及可用資源都沒有伺服器以及桌上電腦那麼的強大。然而,Linux在最近幾年的發展及進步,已經可以讓它勝任某部份嵌入式系統所應用的範圍。因 此在本文內,筆者將簡單的介紹嵌入式Linux,包括它的發展現況以及開發流程。

嵌入式Linux簡介

對於嵌入式Linux(Embedded Linux)的定義,各家說法或有不同。簡單來說,只要不是在個人電腦或伺服器上面運作的Linux,就是所謂的是嵌入式Linux。所謂的「嵌入式」, 說穿了就是將精簡過的Linux系統寫入至Flash Rom,而日後可以藉由刷新韌體,來做功能的增加及系統的修補。而嵌入式Linux的應用其實相當廣泛,大到伺服器,小到家電,都可以看到嵌入式 Linux的影子。 只要硬體本身不故障的情況下,機器本身所內嵌的Linux,是不會遭受到任何的毀損,因此不需費心去考慮「重灌」的問題。 目前在embedded linux界有數家廠商合作起來成立一個名叫CELF的組織,透過這個組織來推動linux在家電市場的應用。


圖:CELF是一個將焦點放在如何使linux應用於消費性電子產品上面的組織(取自CELF網站)

常見的核心版本

而在嵌入式Linux的執行環境中,核心佔了相當重要的地位。一般而言,常見的Embedded Linux核心版本大概有下列數種:

  1. 由Linux之父:Linus Torvalds所維護的「正宗Linux 核心版本」。
  2. 知名的MontaVista公司所修改的版本。
  3. 專門使用在便宜且不具備記憶體管理單元(Memory-Management Unit,MMU)硬體的uCLinux。
  4. 專門應用在即時(Real-Time)系統中的RTAI以及RTLinux(RTLinux/Pro)。
當然以Linux「Open Source」的特性,說不定在網路上還有其他可供用來開發嵌入式Linux的核心,如果有興趣的話,可以去網路上找找,說不定還有意想不到的發現。 C語言函式庫的支援

除了核心之外,嵌入式Linux系統還需要很多其他的軟體元件,這些元件包括了標準的C語言函式庫。雖然GNU有發展過一套C語言函式庫可供開發時使用,但這套函式庫對嵌入式環境來說還是過於肥大,所以有很多縮小化或重新撰寫的版本被開發出來。

uCLibc http://www.uclinux.org(最為常見)
Diet libc http://www.fefe.de/dietlibc
newlib http://sources.redhat.com/newlib
表:嵌入式Linux常用的C語言函式庫

小型GUI系統

使用者可以自行在嵌入式系統內設計出一個圖形使用者介面(GUI),讓嵌入式Linux看起來較為「友善」一些,然而目前在Linux系統上的X -Window,可不是嵌入式Linux消受的起,因此就有很多小型的GUI系統(像是Qt/Embedded、OpenGUI等)被開發出來。

(按一下放大)
圖:OpenGUI的執行畫面(取自OpenGUI網站)

Java的應用

除了先前提到的C語言函式庫之外,Java的應用也日益廣泛,使用者可以在嵌入式平台上使用Java程式語言來開發應用程式,舉個例子來說,目前 有不少手機是以嵌入式Linux作為作業系統,而使用者可以在這些手機上安裝一些以Java寫成的小遊戲或者是應用程式就是一個最好的例子。

而這些用來執行Java程式的Java虛擬機器(Java Virtual Machine),也必須儘量的精簡,如此才能夠在嵌入式的硬體平台上流暢地執行,而目前較常被使用在嵌入式平台的Java虛擬機器有昇陽(SUN)的 J2ME以及免費的Kaffe兩種,而J2ME又可分為用於手機上的KVM,以及可能會使用在數位電視上的CVM。

(按一下放大)
圖:J2ME在整個Java體系的關係圖(取自Sun網站)


圖:在iPaq上使用kaffe執行一個Java程式的執行畫面(取自kaffe網站)

嵌入式Linux的優點

那麼使用嵌入式Linux到底有什麼好處呢?筆者認為使用嵌入式Linux的好處不外乎下列幾點:

  1. 通常非商業版本的嵌入式Linux元件可以免費的從網路上下載
  2. 使用者可以取得linux 核心的完整原始碼
  3. 支援多種類的CPU,包括x86,ARM,MIPS,PowerPC等等
  4. 穩定性佳
  5. Linux核心採用模組化的設計
  6. 可以獲得來自全世界的支援
  7. Linux 核心具有一個標準的程式設計介面
  8. 眾多的免費開發工具

嵌入式Linux系統的即時性

而在最近幾年的核心發展當中,有項很重要的議題一直被拿出來討論,那就是即時的(Real-Time)Linux系統。在kernel 2.4版當中,雖然進行了一些有關即時系統的改進,但一般說來,並沒有辦法達到一般的即時系統要求。不過在之後的核心發展當中,有很多新的改進被加入到核 心裡面,因此到了kernel 2.6版的時候,整個的即時特性有著很大的進步。在kernel 2.6中有關即時系統的改進有:

  1. 在2.4版核心的後續發展中,有很多關於增進即時性的修補檔(patch)被加入到核心的原始碼裡面,而這些成果都已經被正式的加入到2.6版核心內。

  2. Linux核心的發展人員在2.6版核心內設計了一個新的排程(schedule)演算法,這個新的排程演算法具有比之前版本還要快速的行程間內容轉換(context switching)時間。

  3. 由於在2.4版之前的核心當中,當某個行程呼叫了核心服務之後(例如系統呼叫),其他的行程就沒有辦法搶奪CPU的使用權,一直要等到該呼叫核心 服務的行程完成了該服務之後,其他行程才有機會搶奪CPU的使用權。這樣的缺點是,高優先權的行程有可能必須等待低優先權行程,因此在2.6版的核心當中 插入了許多個新的強佔點(preemption point),來讓2.6版核心的排程器(scheduler)有機會可以中斷目前正在執行的行程。

  4. 一個全新的POSIX執行緒系統。由於之前linux系統上預設的執行緒系統(名叫 LinuxThreads)有許多的缺點,其中包括了不完全符合POSIX的標準,後來就有一些新的執行緒系統(threading subsystem)被開發出來,這包括了Redhat公司的NPTL(Native Posix Thread Library)系統以及IBM公司的NGPT(Next Generation Posix Threading)系統等等。到最後由Redhat公司的NPTL系統勝出,作為未來linux環境下預設的執行緒系統,因此在2.6版的核心當中提供 了NPTL系統所需要的核心支援。

  5. 與uCLinux的整合。uCLinux主要是一個可被用在缺少記憶體管理單元(MMU) CPU上的linux核心版本,由於完整的虛擬記憶體機制需要MMU硬體的支援,所以uCLinux針對這個硬體受限的環境對之前版本的linux核心做 出了相對應的修改,而這些修改也被正式的加入到2.6版的核心當中。

  6. 由於linux核心內會使用虛擬記憶體(virtual memory)系統中的分頁置換(page swapping)機制來將使用者程式(user code)從虛擬記憶體中移進移出,但分頁置換將會花費大量且不確定的時間,這對即時系統來說是個巨大的致命傷,因此在2.6版的核心當中,新增了一個編 譯時期的設定選項,可以讓使用者製作出一個不使用分頁置換機制的核心出來。

  7. 另外,在最新的核心發展當中,一位名叫Ingo Molnar的程式設計師發展出一個名為CONFIG_PREEMPT_RT的套件,號稱將這個套件加入到核心的原始碼後,可以讓2.6版核心達到更好的即時性。
透過上面的介紹,我們了解到其實可以透過自行修改核心的原始碼來讓目前的linux系統取得更好的即時性。這種方法的好處是整個系統的架構將會比較簡單, 對上層的應用程式撰寫者來說,也比較容易。然而,雖然Linux核心在2.6版當中新增了許多有助於增進即時性的架構,但由於2.6版的核心在這方面只是 剛起步而已,並不夠完備,所以除非是經過大量的修改,否則並沒有辦法達到所有即時環境的要求。另外,每當Linus Torvalds發佈新的核心版本時,之前所做的自行修改也必須要重新移植到新的核心版本上,因此維護不容易便是這種方法的另一個缺點。

由於觀察到了這種不易維護的缺點,因此就有了第二種方法來達到linux系統的即時特性。這種方法是在系統中加入第二個核心。這個核心是一個獨立 於linux 核心之外的即時作業系統(RTOS,Real-Time Operating System),而linux 核心只是運作在其上的一個程序而已。


圖:新增一個RTOS來達到即時性,而linux只是運作在RTOS上的一個工作而已

由於linux 核心只是RTOS上的一個程序,所以linux 核心將沒有辦法禁止CPU中斷(interrupt)的發生,因此就沒有辦法影響到RTOS的即時特性。所以在這種系統上,所有需要即時性的工作 (real-time task)都由這個新的RTOS來處理,而其他不需要即時性的工作(non real-time task)就可以由linux 核心來處理。

採用這種雙核心架構的有名例子主要有兩個,其中一個是義大利米蘭大學 (Department of Aerospace Enginnerring of Politecnico di Milano,又叫做DIAPM)的RTAI,而另一個則是FSMLabs的RTLinux。

RTAI

RTAI目前的主持人是Paulo Mantegazza教授,這個計畫所使用的RTOS是基於Adeos nano-kernel所發展出來的。這個RTAI計劃的成果可以從網路上免費的下載到。

RTLinux

RTLinux是FSMLabs所開發的一個類似RTAI架構的即時linux系統,也是免費的,它所使用的底層RTOS名叫RTCore,不過 FSMLabs有另一款商業版的RTLinux/Pro,在這個RTLinux/Pro裡面具有很多免費版RTLinux所沒有的新功能。

不過在RTAI及RTLinux的環境中,有一個蠻常被人提及的缺點,那就是由於所有的即時工作(real-time task)都必須在RTOS下執行,所以所有的即時工作(real-time task)都必須執行在核心空間(kernel space)之下,這就代表行程與行程之間沒有辦法做到資料的隔離與保護。因此在這個問題上,就有一些新的架構被提了出來。以RTAI來說,一個新的基於 RTAI的機制名叫LXRT,它的一個最重要的好處是可以讓運作在使用者空間(user space)中的程式也能夠兼顧到即時性。

此外,以目前的情況來看,以內建第二個RTOS 核心的方法來增進linux環境的即時性還是要比單純的使用2.6版核心要來的好上許多。

常見的嵌入式平台CPU

有別於我們常見的x86系列CPU,在嵌入式平台上比較常見的有下列幾種:

ARM http://www.arm.com/
MIPS http://www.mips.com/
Xscale http://www.intel.com/design/intelxscale/
FreeScale http://www.freescale.com/
SuperH http://www.superh.com/home/index.htm
表:嵌入式平台常見的CPU

ARM


圖:ARM公司的標誌(取自ARM公司首頁)

目前在手機或PDA上,ARM的使用佔了很大的比例。ARM是由一家名叫ARM(Advanced RISC Machines)的公司所發展的,最早是由Acorn,Apple,和VLSI這三家公司在1990年合資成立的。目前的ARM CPU的架構已經推進到第五代,由於ARM CPU是屬於RISC的架構,所以每一個指令的長度都是固定的,基本的ARM指令長度是4個位元組,但從第4代開始,新增了一個名叫Thumb的指令集, 它的指令長度只有2個位元組,因此透過Thumb指令集的運用,開發者可以大幅的減少程式的大小。並且從第三代開始,ARM可以定址到4GByte的記憶 體,以及從第二代開始,ARM可以藉由協同處理器的幫助來擴充額外的功能,例如MMU的功能就位於第15號系統協同處理器(system co-processor)內。

在ARM CPU內總共區分出7種狀態,分別是USR(user)、FIQ (Fast Interrupt)、IRQ (Normal Interupt)、SVC (Superuser)、SYS(system)、ABT(Abort)、及UND(Undefined)狀態。另外,在ARM CPU內總共有16個一般暫存器可用,以及一個用來紀錄CPU狀態的狀態暫存器。

ARM系列的CPU由於耗電量低,以及擁有不錯的效能,所以在很多領域中都以著廣泛的應用。此外,ARM公司不僅僅只是販賣自家的CPU,他還透 過販賣CPU的知識產權來增加獲利。比方說,ARM公司目前將CPU的技術授權給全球的很多家廠商,例如有Intel、IBM、LG等等大廠,因此這些獲 得授權的廠商就可以生產屬於ARM架構的CPU了。


圖:使用Intel Xscale CPU(屬於ARM架構)的HP iPaq系列PDA

MIPS


圖:MIPS公司的標誌(取自MIPS公司首頁)

MIPS是由MIPS公司所開發的CPU,它的全名是Microprocessor Without Interlocked Piped Stages。由於它的低耗電量,以及不錯的效能,因此在嵌入式環境中常可看見它的蹤跡,除此之外,其實在SGI的圖形工作站,Sony的Play Station裡面,都可以看到MIPS的身影。另外,在最近越來越熱的數位電視領域中,MIPS的使用也佔據了非常重要的地位。


圖:使用MIPS CPU的Casio CASSIOPEIA系列PDA

開發嵌入式Linux的步驟

在開發嵌入式Linux方面,大概可以分為下列幾個階段:

  1. 開發環境的建置階段
  2. 開機啟動程式(開機啟動程式)建構階段
  3. 核心移植(porting)階段
  4. 上層系統建構階段

開發環境的建置階段

首先在開發環境的建置階段,最重要的大概就算是編譯器(compiler)了。一般說來,我們平常所用的CPU平台是以x86為主,然而在嵌入式 的環境中,x86平台比較少見,通常是以ARM,MIPS等等系列為主要對象。因此我們所需要的編譯器將是一個可以在x86平台上執行,但卻可以編譯出執 行在目標平台上的二進位機器碼。這一類的特殊編譯器就叫做跨平台編譯器(cross compiler)。如果廠商有提供跨平台編譯器的話,通常都有標準且方便的安裝程序可以參考。然而,如果廠商沒有提供這類特殊編譯器的話,一般說來, GNU 組織所開發的GCC系列的編譯器可以產生我們所需要的跨平台編譯器版本。


圖:藉由Cross Compiler的幫助,我們可以在一個平台上編譯出另外一個平台的執行檔

如果要從GNU GCC編譯器的原始碼產生出我們所需的跨平台編譯器大概可以分為下列五個步驟:

  1. 指定目標平台上所使用的核心版本標頭檔(header file)的位置
  2. 安裝binutils (一個GCC會需要使用到的額外工具組)
  3. 從GCC原始碼中先編譯出一個沒有支援C語言函式庫的跨平台編譯器
  4. 再利用上一步驟所建構起來的跨平台編譯器來編譯出在目標平台上所使用的C語言函式庫
  5. 最後利用上一步驟所產生的C語言函式庫來從GCC原始碼中編譯出一個支援C語言函式庫的跨平台編譯器

開機啟動程式(開機啟動程式)建構階段

在準備好跨平台編譯器之後,就可以來考慮開機啟動程式(開機啟動程式)的選擇了。目前在嵌入式環境中已經有很多現成的開機啟動程式可以使用,比較 有名的大概有BLOB,U-Boot,RedBoot,bootldr等等。我們平常在桌上linux電腦可見的lilo並不太適合使用在嵌入式系統端, 最主要的原因是lilo只支援x86平台。然而,雖然已經有很多現成的開機啟動程式可供使用,但在某些情況下,開發者可能需要自行的修改開機啟動程式的原 始碼來符合現實平台的需求。

當然,開發者也可以捨棄目前常見的一些開機啟動程式,而自行撰寫一個新的開機啟動程式出來。通常這一步驟會由先撰寫一個硬體測試程式來偵測並檢驗目標平台上的硬體裝置是否正常,接下來才會更進一步的把這個硬體測試程式開發成一個真正的開機啟動程式。

另外,除了在目標平台上安裝一個開機啟動程式(boot loader)來啟動整個系統之外,通常在整個嵌入式系統的開發初期,會透過網路連結的方式把系統啟動起來。在這邊可以使用的網路機制有 BOOTP/DHCP,TFTP(Trivial File Transfer Protocol),NFS(Network File System)等等。透過網路來啟動系統的好處是,大部份的檔案更動都可以在本機(host)端完成,而不需要下載到目標平台(target platform)上。由於通常目標平台的儲存裝置會是flash ROM,而flash ROM有最多寫入次數的限制,所以更加深了經由網路連結啟動的吸引力。

不管是自行開發一個開機啟動程式,或是從現有的開機啟動程式中做修改,在這一階段裡面勢必要進行除錯(debug)的動作。在這一階段裡面,最方 便的除錯器(debugger)要算是支援JTAG,BDM,OnCE,或OCDS等等除錯介面的除錯器了。而在購買這類型的除錯器時,有幾點需要注意:

  1. 所購買的除錯器是否可以跟目標平台連結
  2. 所購買的除錯器是否可以在本機(host)端使用,有些除錯器只有microsoft windows的驅動程式,而沒有linux的版本。
  3. 在某些目標平台上,只有DRAM這一類型的儲存裝置,而沒有ROM,因此你可能會需要一個可以初始化DRAM的除錯器,如此一來,開發者才可以把程式下載到DRAM內。

圖:American arium所開發的具有JTAG介面的硬體模擬器

另外,目前市面上大部份的這類型除錯器都有支援gdb(一個GNU組織所發展的除錯器軟體),或是正準備要支援gdb,因此開發者可以透過gdb來使用這類型的除錯器。

核心移植(porting)階段

在完成了開機啟動程式的準備及安裝之後,接下來就要進行linux 核心的移植了。由於核心的版本眾多,不同的版本也有不同的小錯誤(bugs),也可能某些版本只能被某些版本的GCC編譯,不過通常提供這些特殊平台版本 的網站上會提供相關的修補程式(patch)來解決這些問題。

而在設定核心的時候,可以根據你的開發版來載入一些預設的設定值,比方說你的開發版是基於assabet來設計的話,那麼在設定核心的時候就可以使用make assabet_config來載入assabet的預設值。


圖:Intel的assabet開發版

可以使用在這一階段的除錯器,一般說來跟開機啟動程式階段相同,也就是一個可以支援JTAG等等除錯介面的除錯器是最好用的了。

上層系統建構階段

在完成核心的移植之後,接下來就是整個系統的安裝與設定了。由於在核心以上的軟體套件比較不具備跟平台相關的相依性,而且在嵌入式平台上比較難以 去做分析比較,因此最好的方法是先在x86平台上把Linux系統的整體架構搞清楚,之後在建置一套嵌入式Linux環境時,將會容易許多。

可用來模擬嵌入式平台的模擬器

這些模擬器或多或少在某些情況下可以幫助嵌入式軟體的開發,這種模擬器最有名的要算是VMware了。不過VMware是模擬x86的環境,所以在嵌入式系統的開發上並沒有很大的用處。

而一些跟嵌入式環境相關的模擬器大概有:

名稱 用途 官方網站
PearPC 模擬PowerPC http://pearpc.sourceforge.net
ARMphetamine 模擬ARM(發展中止) http://armphetamine.sourceforge.net/
Tarmac 模擬ARM(發展中止) http://davidsharp.com/tarmac/
SkyEye 模擬ARM http://www.skyeye.org/
ARMware 模擬ARM http://www.csie.ntu.edu.tw/~r88052/ARMware/tw/frame.html
表:常見的嵌入式平台模擬器

PearPC

(按一下放大)
圖:PearPC執行Apple OS X的畫面(取自PearPC網站)

PearPC幾乎可以完美的模擬出PowerPC的執行環境,目前的最新版本為0.3.1版。另外,PearPC內建有一個動態編譯器,所以它的執行效能比起簡單的PowerPC模擬器來說已經要好上許多。

ARMphetamine

ARMphetamine是一個內建動態編譯器技術的ARM模擬器,不過他只提供簡單的ARM核心模擬,並沒有辦法模擬出整個embedded linux可以運作的環境出來。另外,目前的版本也不穩定,有很多的錯誤急需修正。

Tarmac

Tarmac是個建構在Red Squirrel模擬器上的動態編譯器,雖然它的完成度較ARMphetamine完整,不過它的設計也比較簡單。

SkyEye

(按一下放大)
圖:skyeye模擬器執行uCLinux(取自SkyEye網站)

SkyEye是個由大陸那邊的清華大學所開發的一款ARM模擬器。能夠在上面執行uCLinux,不過不支援動態編譯器技術。不過它的優點是支援很多種類的CPU,以及種類不多的週邊設備。

ARM模擬器:「ARMware」


圖:ARMware模擬器的起始畫面

ARMware是由筆者所自行撰寫的一個ARM平台模擬器。


圖:筆者是ARMware的作者

ARMware是個類似VMware或Bochs的硬體平台模擬器,不過相對於VMware或Bochs所模擬的x86平台,ARMware提供 了一個模擬ARM處理器的環境。目前ARMware所能模擬的核心為第五代的ARM架構(ARM Architecture V),並且以Intel StrongARM SA1110為模擬的對象,包括了StrongARM SA1110 內部的中斷控制器(Interrupt Controller),記憶體管理單元(MMU),LCD控制器(LCD Controller),即時時鐘(Real Time Clock),序列埠(Serial Port)等等。而在未來將會加入Intel Xscale PXA系列的模擬。除了CPU的模擬之外,ARMware還以HP iPaq H3600為目標,模擬出一個可以執行embedded linux的環境。在未來,ARMware將會以HP iPaq H5500為目標,提供一個模擬Intel Xscale的整體環境。


圖:在ARMware內執行embedded linux的畫面

(按一下放大)
圖:ARMware模擬器的架構圖

除此之外,使用者可以調整模擬環境的記憶體大小,比方說雖然iPaq H3600只提供了32MB的DRAM,但在ARMware內可以調整記憶體容量到最高512MB,因此可以模擬出一台經過修改的iPaq H3600。

(按一下放大)
圖:使用者可自行修改記憶體大小

要製作這類型的硬體模擬器,最簡單的方法是採用傳統的直譯器(interpreter)模式,也就是一個一個的去解釋目標平台上的機器指令 (machine instruction),這種方法最簡單,但其效率也最慢。由於通常模擬器的速度要比真正的目標硬體平台要慢上許多,因此便有許多較進步的技術被發展出 來應用在模擬器內部。這些先進的技術大概包括了threaded code,或是一種稱為動態編譯器(dynamic compiler,或稱做 dynamic translator)的技術。

而在ARMware內部,筆者實做了所謂的threaded code以及dynamic compiler技術。

Threaded code技術

threaded code有點像是一種快取(cache)的機制,會把解碼後的目標平台指令(target machine instruction)儲存起來,這樣一來在下一次的執行時,就不需要再進行一次複雜的解碼動作,如此可以加速執行的速度。

動態編譯器(Dynamic compiler)技術

而dynamic compiler則是在邊執行目標平台指令的同時,邊將其編譯成本機平台的機器碼(例如編譯成x86平台的機器碼),這就類似我們一般所知的編譯器,只不 過他是在程式執行的時候才去把該程式給編譯出來,因此特別稱他做動態編譯器(dynamic compiler)。比較有名的dynamic compiler應用應該是在Java虛擬機器裡面,比較為人所知的名字是JIT (Just-In-Time) compiler或是HotSpot compiler。而在ARMware 0.3.0版之後,就已經內建了一個類似HotSpot的動態編譯器,並且目前所實做出來的最佳化技術大概有下列幾項,因此對整體的執行速度有所助益:

  1. Redundant condition code calculation elimination
  2. Global grouping conditional execuating instruction
  3. Redundant jump elimination
  4. Dead code elimination
  5. Constant folding
  6. Global Common Subexpression Elimination
  7. Global redundany memory operation elimination
  8. Algebraic canonicalization
  9. Global SSA form based linear scan register allocation
因此目前在ARMware內部,當要執行一段ARM的機器碼時,會以下列的步驟來進行:
  1. 當第一次碰到一段從未執行過的ARM機器碼時, ARMware會先使用內建的直譯器(interpreter)來解釋這段ARM機器碼。

  2. 之後,當第二次碰到這段ARM機器碼時,會先由ARMware內建的分析器(profiler)來決定這段ARM機器碼是否值得被 threaded-code化,如果決定profiler決定將其threaded -code化的話,ARMware就會將這段ARM機器碼餵給ARMware內建的threaded code引擎來產生相對於該段ARM機器碼的threaded codes.

  3. 在產生完threaded codes之後,當ARMware再度碰到這段ARM機器碼時,就會使用新產生的threaded codes去解釋。然而,如果在執行threaded codes的時候,程式的流程會跳到一個還沒有被threaded code化的ARM程式碼時,ARMware就會回到直譯器(interpreter)的模式去解釋。

  4. 之後,每當再度碰到這段ARM機器碼時,ARMware 內建的 profiler會決定該段程式碼值不值得被動態的編譯成x86的機器碼(dynamic compiling),如果決定值得的話,ARMware就會將該段ARM機器碼餵給 ARMware內建的動態編譯器(dynamic compiler)來產生相對於該段ARM機器碼的x86機器碼。

  5. 在產生完 x96機器碼之後,當 ARMware 再度碰到這段ARM機器碼時,就會使用新產生的 x86機器碼來解釋。然而,如果在執行這段x86機器碼的過程當中,碰到一個還沒被動態編譯過的ARM程式碼,就會回到原始的直譯器 (interpreter)模式或是先前的threaded code模式去解釋。
(按一下放大)
圖:ARMware核心的執行流程

除此之外,筆者也對ARMware做了一些微調的動作,比方說使用組合語言的方式去最佳化一些模擬的動作,例如在LCD螢幕的模擬方面,由於要把iPaq 的畫面顯示在一般的螢幕上,必須要進行一些顏色格式的轉換,以及座標軸轉換的動作(ARMware必須把螢幕資料旋轉270度,這樣使用者看到的畫面才是 正確的),而這些動作是以一個pixel為機準的,因此可以使用x86的SIMD型態指令 (例如MMX,SSE,SSE2等等)來一次處理好幾個pixel,進而加速ARMware對整個LCD螢幕的模擬。


圖:由於iPaq的硬體配置,ARMware必須把螢幕資料旋轉270度,這樣使用者看到的畫面才是正確的

另外,由於幾乎每個CPU內都有狀態暫存器(status register)的設置,而要模擬目標平台的狀態暫存器最簡單的方法就是透過軟體的模擬,但是這樣的方式很慢。而一個比較快的模擬方式是直接拿本機 CPU的狀態暫存器去模擬目標平台的狀態暫存器,但由於高階的電腦語言通常碰不到CPU內部的狀態暫存器,所以要完成這樣的最佳化,必須要透過組合語言的 撰寫,而在ARMware內部就實做了這樣的一個最佳化狀態暫存器處理的組合語言程式碼。


圖:ARM狀態暫存器上的condition位元與x86狀態暫存器上condition位元的對應關係

除了LCD螢幕的顯示之外,ARMware還可以使用一個模擬出來的serial console來與使用者做互動。使用者可以從這個serial console中輸入命令給模擬的環境,也可以從該serial console中獲得模擬環境的一些輸出訊息,並且這個serial console也支援ANSI顏色碼,因此可以正確的看到例如ls等指令所輸出的帶有顏色的訊息。

(按一下放大)
圖:ARMware的執行畫面,左邊是模擬出來的PDA螢幕,右邊是模擬出來的serial console

而在進行iPaq等PDA或手機的系統開發時,通常需要進行Flash ROM的錄製工作,這項工作通常會由廠商所提供的工具來完成。而在ARMware內部,也內建了一個用來燒錄Flash ROM的工具程式,透過這個工具程式,使用者可以將數個分割區的映像檔(image file)組合成一個單一的Flash ROM檔,而ARMware就可以使用該Flash ROM檔來啟動整個模擬的環境。

(按一下放大)
圖:ARMware內建的Flash ROM製作工具

最後,如果讀者對這個ARMware模擬器有興趣的話,可以到筆者的網站http://www.csie.ntu.edu.tw/~r88052/ARMware/tw/frame.html下載,裡面有詳細的安裝說明與解說,目前的最新版本是0.5.0版。

結語

最後,由於Linux本身的開放性及種類繁多的功能,因此嵌入式Linux系統是個龐大且複雜但卻很有趣的一門學問,不僅在過去是如此,在未來的數年之間,也將會是個越來越熱門,有越來越多焦點會投注在裡面的一個領域。

Comments