嵌入式系統軟硬體環境建構步驟
Shoehorn downloader建立
在這裡我們將說明如何利用downloader(Shoehorn or Hermit)將kernel及initial ramdisk下載至EDB7209中。在整個系統的發展過程中,由於必需重覆的下載kernel與initial ramdisk,所以採用Shoehorn downloader是不錯的選擇。如前節所述,Shoehorn downloader是將kernel與initial ramdisk下載至EDB7209的DRAM中,唯一的缺點就是無法長久保存資料。而當我們的系統發展到一定階段後,為了達到嵌入式的目標,就必須讓kernel與initial ramdisk長存在硬體平台中,這時就要採用Hermit downloader,讓kernel與initial ramdisk可以儲存在FLASH中。下面將分別說明兩種downloader的下載過程。
Shoehorn downloader下載流程
在使用Shoehorn downloader下載kernel之前必須先確認kernel的設定,如前所述,在System type選項中的EDB7211 Boot Mode一定要勾選。
轉:http://blog.xuite.net/jackie.xie/bluelove/5224669
軟硬體環境
硬體平台:Ciruss Logic EDB72xx(ARM720T CPU)
使用軟體:
為了得到可以在EDB7209上執行的kernel,我們須要cross compiler工具,它的功用是讓我們能在一般的PC Linux平台編譯出可以在ARM CPU上執行的可執行檔。我們在這一部份採用GNU gcc 2.95.2做為compiler並且將其patch為ARM的cross compiler,同時我們必須有一台PC Linux平台來當做程式發展的平台,以便當我們在此平台完成kernel的編譯後再將kernel下載到EDB7209上執行。
- Cross compile Binutils : binutils2.10 , linux-2.4.0-test1.tar.gz , patch-2.4.0test1-ac19.bz2 , patch-2.4.0-test1-ac19-rmk1.gz
Gcc : gcc-2.95.2.tar.gz , gcc-2.95.2-diff-991022.gz
Glibc : glibc-2.1.3 , glibc-linuxthreads-2.1.3.tar.gz , glibc-crypt-2.1.tar.gz
- Linux kernel nkernel version 2.4.2
Patch : patch-2.4.2-rmk1.gz , patch-2.4.2-rmk1-bluemug7.gz一般針對i386平台散布的Linux並不能在ARM720T CPU執行,為了讓我們的硬體平台有Linux可以執行,我們必須找到特別針對ARM為硬體架構而發展的Linux patch。目前在Linux的討論社群上可以發現有一些專門幫ARM CPU補正Linux kernel的計畫,較知名的有Russell King 所持續釋出的ARM patch。另外,有一個組織是專門針對Ciruss Logic 所出產的EDB72xx系列的平台釋出其週邊裝置的driver patch。此外,此組織亦提供了將Linux kernel下載到平台上的工具Shoehorn與Hermit。
Shoehorn是將kernel下載到EDB7209的DRAM裡,這種方式在將EDB7209的電源切斷後,一切資料就會消失,下一次必須重新載入kernel。而Hermit則是將kernel下載到板子的FLASH中,如此一來當電源關閉時Linux仍然是存在於FLASH中,下一次再開啟電源Linux即會開機開始執行。
- Downloader shoehorn-3.4
hermit-1.1
n
建構步驟
Creating ARM tool-chain
binutilsCreating ARM-LINUX kernel
gcc
glibc
Kernel patchingCreating ramdisk
Application program : busybox0.46Creating downloader
Shoehorn downloaderDownloading kernel and ramdisk
Hermit downloader
Tool chain 的建立 Binutils Gcc Libc
ARM的tool-chain共分為三個部份:binutils、gcc、glibc。binutils包含一些binary tools,可以用來處理已編譯完的binary檔。gcc是我們所需要的cross compiler,glibc則是一些常用的函式庫。
Binutils
binutils是一些用來對binary檔做特殊處理的工具程式,這些工具將在建立cross compiler時被用到。建立步驟如下:
從下列任一網站下載binutils的原始碼檔案,在這裡我們使用binutils2.10版為例,將下載的binutils-2.10.tar.gz放置於/tmp目錄下。· ftp://ftp.gnu.org/gnu/binutils/ - binutils的官方網站 將binutils-2.10.tar.gz解開:$cd /tmp$tar zxvf ./binutils-10.1.tar.gz 現在我們準備對binutils做一些組態設定,將目錄切換至binutils的目錄。如果我們要ARM Linux的平台上建立native tool-chain則輸入下列命令:$./configure --prefix=/usr/local若我們要在一個x86平台建立cross tool-chain則輸入下列命令:(這是我們所要的選項)$./configure --target=arm-linux --prefix=/usr/local在下達上面的命令後,組態程式便會開始檢查系統的一些設定,包括平台,使用的gcc 版本以及測是一些C的函式庫是否有支援。在上面的命令中,prefix代表的是我們想要安裝binutils的目錄,而target則表示binutils在prefix目錄中的目錄名稱,也就是說將來安裝完成後binutils會被安裝到/usr/local/arm-linux/目錄中。 在組態設定完成後便可進行編譯的動作:$make此命令會啟動gcc compiler進行編譯的動作,編譯完成後進行binutils的安裝:$make install這時所有的工具程式將會被安裝到/usr/local/arm-linux/目錄下。Gcc現在我們可以開始進行gcc的建立,在編譯ARM的gcc 之前,我們須要ARM Linux kernel的標頭檔(headers)。當然假如我們要建立的是一個native compiler時這個步驟可以省略,因為在我們的系統上就已經有ARM Linux的kernel source了。但如果我們要建立的是cross compiler,那我們必須有一個ARM Linux kernel source,以便在編譯gcc時可以參考到kernel的標頭檔。
到下列網站下載Linux kernel source到/tmp目錄中,由於kernel版本眾多,在這裡只要是v2.4版以上的都可以,我們採用2.4.0-test1版,將linux-2.4.0-test1.tar.gz及patch-2.4.0test1-ac19.bz2下載到/tmp目錄:接下來到下列網站下載2.4.0-test1-ac19版的Russell M. King ARM patch patch-2.4.0-test1-ac19-rmk1.gz,一樣置於/tmp目錄中: 將kernel source在/tmp目錄下解開:$tar zxvf linux-2.4.0-test1.tar.gz這樣在/tmp目錄下會出現linux的目錄,接下來做kernel source的更新:$cd linux$bzcat ../patch-2.4.0test1-ac19.bz2 | patch -p1 -s -E這個命令共包含兩個動作bzcat與patch,首先bzcat是兩種命令的組合:bzip2與cat。所以當執行bzcat時會先將patch-2.4.0test1-ac19.bz2解壓縮(bzip2),並將其內容列印在標準輸出裝置上(cat)。而patch則是負責將patch file所更正的部份在原始檔上做修改。為了將bzcat的輸出導正為patch的輸入我們使用了pipe( | )這個命令。接著是ARM patch的更新:$ zcat ../patch-2.4.0-test1-ac19-rmk1.gz | patch -p1 -s -E由於ARM patch檔是以gzip壓縮,所以我們改用zcat取代bzcat。 現在必須編輯/tmp/linux/目錄中的Makefile檔案,將ARCH := $(shell uname ... 略 ...)改成ARCH := arm這麼做的原因是為了讓將來編譯gcc時可以正確的參考到ARM的部份。 在linux目錄下執行下列命令:$make menuconfig畫面上會出現選單式的畫面,這是用來設定kernel組態的畫面,目前我們不需要做任何的設定,只要存檔之後就可以離開。接著下此命令:$make dep如此一來,將會建立header檔的dependency tree。 接著在我們要建立tool-chain的目錄中加入kernel header的聯結$cd /usr/local/arm-linux$mkdir include$cd include$ln -s /tmp/linux/include/asm-arm asm$ln -s /tmp/linux/include/linux linux 到下列網站下載gcc的source file及其ARM patch,在本論文採用的是gcc-2.95.2.tar.gz,ARM patch則是gcc-2.95.2-diff-991022.gz及:下載至/tmp後將gcc source file解開並以patch檔更新:$tar zxvf gcc-2.95.2.tar.gz$cd gcc-2.95.2$ zcat ../gcc-2.95.2-diff-991022.gz | patch -p1 -s -E接著必須修改gcc-2.95.2/gcc/fold-const.c檔,以編輯器開啟後在tree rhs = make_range (TREE_OPERAND (exp, 1), &in1_p, &low1, &high1);tree tem;與/* If this is an OR operation, invert both sides; we will invertagain at the end. */if (or_op)之間加入下列程式碼:/* Fail if anything is volatile. */if (TREE_SIDE_EFFECTS (lhs) || TREE_SIDE_EFFECTS (rhs))return 0;存檔後,開啟gcc-2.95.2/gcc/config/arm/t-linux檔,將TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC置換成TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc -D__gthr_posix_h存檔後回到gcc-2.95.2/目錄下 開始設定組態,並編譯gcc:若要建立native compiler則下$./configure --prefix=/usr/local我們要建立的是 cross compiler 下$./configure --target=arm-linux --prefix=/usr/local --disable-threads設定完成後便可開始編譯,編譯完成後進行安裝$make LANGUAGES="c" cross$make installGlibcCross compiler完成後就可以編譯一些user-space常用的函式庫,glibc就是一些基本函式庫的集合。同時由於前面在編譯gcc時有關glibc的部份我們都避開了,所以當glibc完成後我們還必須回過頭來將整個gcc再編譯一次,以得到完整的gcc cross compiler。以下就是建立glibc的步驟。
從下列網站下載glibc的原始碼檔glibc-2.1.3.tar.gz及其附加(add-ons)函式庫glibc-linuxthreads-2.1.3.tar.gz及glibc-crypt-2.1.tar.gz到/tmp目錄中。· ftp://ftp.gnu.org/gnu/glibc - (US) 切換目錄至/tmp,分別將三個檔案解開$tar zxvf glibc-2.1.3.tar.gz$cd glibc-2.1.3$tar zxvf ../glibc-linuxthreads-2.1.3.tar.gz$tar zxvf ../glibc-crypt-2.1.tar.gz 將環境變數CC設定為cross compiler arm-linux-gcc,並進行組態設定。$export CC = arm-linux-gcc$./configure arm-linux --build=i586-linux --prefix=/usr/local/arm-linux/ --enable-add-ons組態完成後即可進行編譯的動作$make$make install 現在我們已經有了glibc函式庫,現在我們必須回頭將gcc重新編譯。首先修改gcc-2.95.2/gcc/config/arm/t-linux檔,將先前加進去的部份去掉。將TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc -D__gthr_posix_h置換成TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC存檔後回到gcc-2.95.2目錄下,重新設定組態但省略--disable-threads設定如下:$./configure --target=arm-linux --prefix=/usr/local完成後便可開始編譯完整的gcc cross compiler$make$make install完成上述步驟後,我們就擁有了一個完整的ARM tool-chain,完成後的gcc compiler會被安裝在/usr/local/bin中,所有ARM tool-chain均以arm-linux-為開頭。往後在使用這些工具程式時必須以下列命令來指定其路徑:$export PATH=/usr/local/bin:$PATH也可以在shell啟始描述檔中加入路徑設定,這樣每次登入後路徑就會自動設定。Ps.在編譯cross compiler時最後會出現下列錯誤訊息:
In file included from iogetline.c:26:
libioP.h:30: errno.h: No such file or directory
In file included from iolibio.h:1,
from libioP.h:47,
from iogetline.c:26:
libio.h:30: _G_config.h: No such file or directory
iogetline.c:27: string.h: No such file or directory
make[2]: *** [iogetline.o] Error 1
make[2]: Leaving directory `/root/gcc-2.95.2/arm-linux/libio'
make[1]: *** [all-target-libio] Error 2
make[1]: Leaving directory `/root/gcc-2.95.2'
make: *** [cross] Error 2
雖然編譯中斷,但此時我們所需的cross compiler已經編譯完成,
所以可以不管這個錯誤訊息,進行cross compiler的安裝。
Kernel 的建立
在建立了cross compiler後,我們可以接著建立ARM Linux的kernel。如前所述,我們的核心版本採用2.4.2版,在ARM Linux的討論社群上定期會有新版本的ARM patch會更新,我們必須將原始的Linux kernel以ARM patch更新,同時針對EDB7209的一些週邊驅動程式也有patch必須一一更新,才能編譯出可在EDB7209上執行的kernel。以下就是ARM Linux kernel的建立過程。
到下列網站下載Linux kernel - linux-2.4.2.tar.gz至/tmp目錄中:· ftp://ftp.uk.kernel.org/pub/linux/kernel/v2.4/在/tmp建立一新目錄,將kernel解至該目錄:$mkdir arm_linux$cd arm_linux$tar zxvf ../linux-2.4.2.tar.gz 分別到下列網站下載ARM Linux patch - patch-2.4.2-rmk1.gz 及EDB7209 driver patch - patch-2.4.2-rmk1-bluemug7.gz至/tmp目錄下:· ftp://ftp.uk.kernel.org/pub/linux/kernel/v2.4/· http://aruba.bluemug.com/~miket/arm/linux/v2.4/分別以ARM patch及EDB7209 driver patch更新Linux kernel:$cd /tmp/arm_linux/linux$zcat ../patch-2.4.2-rmk1.gz | patch -p1 -s -E$cat ../patch-2.4.2-rmk1-bluemug7.gz | patch -p1 -s -E 完成核心的更新後便可以開始進行核心的建立。現在我們要進行的是核心的組態設定,這個步驟可以讓我們設定硬體平台架構,CPU型態等,以及一些週邊的支援情形的設定,是整個建立核心過程的一個重點。在這裡Linux提供了兩種設定的方式,分別是make config及make menuconfig。兩種的差異在於使用介面的不同,make config是單純文字敘述且若設定錯誤則必須重頭來過,而make menuconfig則提供了一個選單的介面讓使用者可以勾選要設定的項目,在這裡我們用make menuconfig來設定組態,這裡要注意在系統的搜尋路徑中必須包含cross compiler所在的路徑:$cd /tmp/arm_linux/linux$make menuconfig首先,Code maturity level options選項,選擇Prompt for development and/or incomplete code/driversLoadable module support,不勾選。System Type,先進入ARM system type選項,選CLPS711X/EP721X-based接著回到上一層選CLPS711X/EP721X Implementations在CLPS711X/EP721X Implementations裡還有子選項,選擇EDB7211。在這裡可以看到有一個選項EDB7211 Boot Mode,這個選項是在選擇kernel的開機模式,這部份在實作Ramdisk時將會說明,在此不勾選。回主選單,General setup,勾選:Networking support、System V IPC、Sysctl support、NWFPE math emulation、Kernel support for ELF binaries。回主選單,Parallel port support,不勾選。Memory Technology Devices (MTD),不勾選。Plug and Play configuration,不勾選。Block devices部份,勾選RAM disk support、Initial RAM disk (initrd) support。同時更改Default RAM disk size參數為8192.回主選單,Multi-device support (RAID and LVM),不勾選。為了讓kernel支援網路功能,Networking options部份,勾選Unix domain sockets、TCP/IP networking其餘不選.
Network device support部份,我們必須根據我們的硬體平台選擇驅動程式,在EDB7209上內建了乙太網路介面,其所使用的晶片組為CS8900。勾選Network device support並進入Ethernet (10 or 100Mbit)子選單,接著勾選EISA, VLB, PCI and on board controllers,此時會出現子選項,勾選CS89x0 support.
回主選單,Amateur Radio support,不勾選。IrDA (infrared) support,不勾選。ATA/IDE/MFM/RLL support,不勾選。SCSI support,不勾選。Synchronous Serial Interfac,不勾選。I2O device support,不勾選。ISDN subsystem,不勾選。Input core support,不勾選。Character devices部份,分別勾選Virtual terminal、Support for console on virtual terminal、CLPS711X serial port support、Support for console on CLPS711X serial port、Unix98 PTY support、Enhanced Real Time Clock Support其餘不勾選。在這裡我們選擇了字元裝置裡的序列埠支援。回主選單,Multimedia devices,不勾選。File systems部份,勾選Simple RAM-based file system support、/proc file system support、Second extended fs support。我們的kernel必須支援Ext2 file system,因為我們的RAM disk將以Ext2的格式建立。 Console drivers部份,勾選Support Frame buffer devices、Support for console on virtual terminal.
接著進入Frame-buffer support子選單,勾選Support for frame buffer devices (EXPERIMENTAL)、EP7211 LCD support、Advanced low level driver options、Monochrome support、2 bpp packed pixels support、4 bpp packed pixels support
回主選單,USB support,不勾選。Kernel hacking部份,勾選Compile kernel without frame pointer、Verbose kernel error messages、Verbose user fault messages、Kernel low-level debugging functions.設定完成後回主選單,並選Exit便可存檔並離開組態設定。4. 進入include/asm/arch-ep7211/目錄,編輯hardware.h檔,將#ifdef CONFIG_EP7211_JUMPERED_BOOT#define IO_EXTKBD_START 0x40000000 /* physical */#else#define IO_EXTKBD_START 0x30000000 /* physical */#endif改成#ifdef CONFIG_EP7211_JUMPERED_BOOT#define IO_EXTKBD_START 0x40010000 /* physical */#else#define IO_EXTKBD_START 0x30010000 /* physical */#endif這樣在編譯完核心後,鍵盤才可以正常動作,原先的版本是7211板子的設定,而我們採用的是EDB7209,其設定必須採用後者。5. 組態設定完成後接下來就可以開始編譯,步驟如下:$make dep$make Imagemake dep的作用在幫我們檢查引用的標頭檔是否在正確的位置,檢查完畢就可開始正式編譯核心,若沒有錯誤的話make Image會在arch/arm/boot/目錄下產生一個Image檔,這就是我們所需要的核心檔,接下來將它壓縮:$gzip Image我們將會用Hermit downloader程式將Image.gz下載至EDB7209板中。6. 在Step3我們在System Type選項中沒有勾選EDB7211 Boot Mode,現在重新進入組態選單並勾選EDB7211 Boot Mode,存檔後重新編譯核心:$make dep$make Image完成後同樣在arch/arm/boot目錄下會產生Image檔,但不須將其壓縮,將其更名為Image_boot以茲區別。此Image_boot檔是以Shoehorn downloader下載至EDB7209。
Initial ramdisk 建立
在建立了ARM Linux kernel後,我們還需要一個檔案系統來當系統的root device。如前所述,由於EDB7209並不支援磁碟機,所以我們的檔案系統只能利用板子上的記憶體來虛擬成磁碟機,也就是ramdisk。這一節將詳細說明如何建立此一檔案系統,以及這個檔案系統需要具備哪些必要的檔案以便開機時可以用到。以下是建立的步驟:
首先我們必須有一個裝置來存放我們要建立的檔案系統,這裡我們採用系統的ramdisk來儲存,不過必須確定系統的記憶體足夠。以下命令會在/dev/ram0建立一個Ext2格式的檔案系統:$mke2fs -m 0 -i 2000 /dev/ram0此命令會在/dev/ram0裝置上建立Ext2格式的檔案系統,同時設定其inode數為2000個,而此檔案系統的大小則會依Linux kernel的預設值來決定,我們的Linux 發展平台所產生出來的檔案系統可達8192Kbytes。 接下來要將此裝置掛載(mount)至系統中:$mount /dev/ram0 /mnt此時/dev/ram0相當於系統中的一個目錄,如此以來我們可以進入/mnt目錄中準備我們的檔案系統。 在Linux的檔案系統中,有幾個目錄是必須存在的,分別是:
- /dev -- 裡面存放裝置檔 (Devices) ,為達成 I/O 工作所需
- /proc -- 存放一些系統的資訊,必須支援/proc 檔案系統
- /etc -- 裡面存放系統組態設定檔
- /sbin -- 重要的系統執行檔
- /bin -- 一些系統工具程式的存放目錄,如:ls、cd等
- /lib -- 提供 run-time 支援的共享函式庫
- /mnt -- 維護其它磁碟所用的磁碟掛入點 (mount point)
- /usr -- 額外的工具程式與應用程式
使用mkdir指令在/mnt目錄下建立上述目錄。 進入dev目錄,我們必須建立一些裝置檔以便讓一些週邊裝置或是系統裝置能夠被正常使用,其中有一些裝置檔可以從Linux平台上取得:$cd /mnt/dev$cp -dpR /dev/console
./$cp -dpR /dev/kmem ./$cp -dpR /dev/mem ./$cp -dpR /dev/null
./$cp -dpR /dev/ram0 ./$cp -dpR /dev/tty0 ./$cp -dpR /dev/tty1 ./$cp -dpR /dev/initrd
./另外序列埠裝置檔必須手動加入,而此動作必須知道此裝置的主要代碼與此要代碼,這一部份由前節所述的driver patch可查到:$mknod ttyS0 c 204 16$mknod ttyS1 c 204 17在這裡序列埠裝置的主要代碼為204,次要代碼分別為16、17。 接著進入etc目錄,我們必須準備一些設定檔在這個目錄中以便讓Linux順利開機,有幾個檔案是必備的:inittab、fstab、以及rc.d/目錄下的檔案。這些可以從系統的/etc目錄下取得,並做適當的修改即可:$cd /mnt/etc$cp /etc/inittab ./$cp /etc/fstab ./$cp -r /etc/rc.d ./inittab檔案是在描述傳遞給系統第一個程序(init)的參數,inittab檔至少須包含下列參數:id:2:initdefault:告訴init進入runlevel 2,以下是Linux中定義的runlevel:0 - halt (Do NOT set initdefault to this)1 - Single user mode2 - Multiuser, without NFS (The same as 3, if you do not have networking)3 - Full multiuser mode4 - unused5 - X116 - reboot (Do NOT set initdefault to this)si::sysinit:/etc/rc.d/rc.sysinit此行定義了系統一開始要執行的script檔,在此設定的是/etc/rc.d裡的rc.sysinit script檔。1:12345:respawn:/bin/getty tty1 9600 vt100此行定義了允許使用者可以以vt100的終端機模式在tty1以9600的速率登入。fstab檔則定義了系統開機時須要自動掛載(mount)哪些檔案系統,此檔至少須有下列描述:/dev/ram0 / ext2 defaults
/proc /proc proc defaults
rc.d/rc.sysinit檔則可視需求增減原來的內容。 bin、usr/bin、usr/sbin及sbin目錄中的系統程式或應用程式則視需求至網路上下載程式的原始碼檔,並以cross compiler編譯即可在ARM Linux中執行。在此採用另一種解決方案,專為嵌入式系統而設計的Busybox。所謂的Busybox乃是將一些常用的Unix指令及小程式適當的刪減其功能並整合在一個執行檔Busybox中,這麼做的原因是因為在大部份嵌入式系統通常不具備很大的記憶體,因此ramdisk也不能太大,而為了在有限的資源下能使用大部份的Unix指令及常用的小程式,有一群人開始試著將這些程式刪減整合成單一執行檔,稱為Busybox。通常Busybox所提供的指令會比原本的指令在功能上稍微有所不同,主要是因為空間的考量。以下將說明Busybox的建立過程:至下列網站下載Busybox原始碼檔busy-0.46.tar.gz至/tmp目錄中解開busy-0.46.tar.gz,並進行組態設定:$cd /tmp$tar zxvf busy-0.46.tar.gzBusybox可以選擇要編譯哪些程式進入busybox中,進入busybox目錄中,編輯busybox.def.h檔,即可選擇欲加入的應用程式。以cross compiler編譯busybox:$make編輯Makefile檔,設定PREFIX為/mnt$make install如此busybox將會被安裝到我們新建的檔案系統的bin目錄中,並且會建立一些連結(links)到busybox,這是因為若要使用busybox中的應用程式有兩種方法,一種是:$/bin/busybox ls另一種方法是建立一個連結:$ln –sf /bin/busybox ls$ls當我們執行make install時,會在相對應的目錄內產生這些應用程式的連結。到了這裡我們的Busybox算是完成了。- 接下來我們進入lib目錄,此目錄必須存放應用程式執行所需要的共享函式庫及載入函式庫,有時我們可能不清楚某個程式到底用到了哪些函式庫,這時可以用ldd指令來檢查。
libc-2.1.3.so及ld-2.1.3.so,是大部份程式都需要的函式庫,我們必須在lib目錄中加入:$cd /mnt/lib$cp /usr/local/arm-linux/lib/libc-2.1.3.so ./$cp /usr/local/arm-linux/lib/ld-2.1.3.so ./在lib目錄中除了要存放函式庫本身之外,通常應用程式是以連結的方式來使用這些函式庫,所以我們除了將函式庫本身複製到lib目錄外還需為每一個函式庫建立相對應的連結:$cd /mnt$chroot /mnt /sbin/ldconfig上述命令主要是透過ldconfig來完成函式庫的設定更新。ldconfig會在/mnt/etc中產生一個ld.so.cache的檔案,這個檔案是用來告訴loader去哪裡找函式庫,同時ldconfig也會為每個函式建立相對應的連結。 完成了所有必備檔案的準備後,接下來要進行的是將整個檔案系統轉換為單一檔案以便讓我們使用downloader下載到EDB7209板子中。$cd tmp$dd if=/dev/ram0 of=./ramdisk bs=1k count=4000在上述命令中,dd指令可以將/mnt目錄中的所有檔案轉成單一檔案ramdisk,選項bs指的是block size,在這裡定為1kbytes。而count則是設定所欲轉換的大小,在這裡可以視實際使用的大小來定,使用df指令可以看到/dev/ram0的總容量及其目前使用量。到這裡為止我們以經建立好一個可以讓downloader下載到EDB7209板子上的initial ramdisk 了。
Downloader 的建立
最後,我們需要一個下載的工具。由於EDB7209並不支援磁碟機,所以若是要讓EDB7209能夠像一般的Linux系統一樣開機的話,不管是kernel或是ramdisk都必須事先燒錄在EDB7209的onboard flash中。本節將介紹兩種downloader:Shoehorn以及Hermit。兩者的不同點在於Shoehorn是將kernel及ramdisk下載至EDB7209的onboard DRAM中。當EDB7209電源關閉時,儲存在DRAM中的kernel及ramdisk將會消失,下一次必須再從主電腦下載一次,而Hermit是將kernel與ramdisk燒錄至EDB7209的FLASH中,當開機時再從FLASH中載入DRAM。當電源切斷時,FLASH中的資料並不會消失,所以當電源恢復後還是可以重FLASH中將kernle及ramdisk載入DRAM而重新開機。
EDB7209有兩種開機模式,在EDB7209板上JP2是用來選擇這兩種模式的接點。當JP2短路時,EDB7209進入Jumpered Boot Mode,系統會從EP7212 ARM chip的on-chip Boot ROM開始執行,由圖所示,此模式下on-chip Boot ROM被定址到0x0000:0000的位址,所以程式會從此開始執行。在on-chip Boot ROM中的程式是CPU出廠時就燒錄在裡面,這一小段程式的主要功用是透過UART與host computer相連,並且讓我們能傳輸程式至on-chip SRAM中。這個功能對downloader來說非常重要,因為這樣我們才能將downloader的目的端程式下載到on-chip SRAM中,Shoehorn downloader就是工作在這個模式下。
當我們讓JP2斷路,並開啟電源,此時EDB7209將進入External Boot Mode。
CPU 將會從外部FLASH開始提取指令,如圖4.20所示,在External Boot Mode時外部FLASH是被從0x0000:0000開始定址,而on-chip Boot ROM則被定址到0x7000:0000。所以若是我們將kernel的映像檔燒錄到FLASH中,且讓JP22斷路,則在開機後kernel將會被從 FLASH中載入進行開機。 Hermit downloader必須利用到兩種開機模式來將kernel及ramdisk燒錄到FLASH中,以下將分別說明Shoehorn與Hermit的原理及其建立程序。Shoehorn downloader建立
編譯完成的Shoehorn可以得到兩個獨立的程式,分別是在Host端執行的shoehorn以及在target端(EDB7209)執行的loader.bin。如前所述,Shoehorn downloader是工作在EDB7209的Jumpered Boot Mode下,當我們在Host端執行shoehorn時,shoehorn首先會將loader.bin載入EP7212的on-chip SRAM中,接著系統的PC(program counter)會被指到SRAM的起始位址並開始執行loader.bin。
而在Host端的shoehorn會開始跟loader.bin建立傳輸管道(透過serial port)然後將kernel及ramdisk下載到EDB7209的DRAM中,其過程如圖4.21所示。另外,若使用Shoehorn下載kernel則在編譯kernel時必須勾選EDB7211 Boot Mode選項,這是因為EDB7209在不同的開機模式下其keyboard與Ethernet的I/O address會有不同的映對位址,所以若沒有根據所使用的開機模式編譯kernel的話,鍵盤及網路可能將失去作用。以下將詳細介紹Shoehorn的建立過程。
- 到下列網站下載Shoehorn原始碼檔,目前Shoehorn最新版為3.4版適用於Linux kernel 2.4.2版本,但亦可向下相容,若是Shoehorn 3.1版則無法適用於2.4.2版的kernel。將shoehorn-3.4.tar.gz下載至/tmp目錄下。
- 將Shoehorn原始碼檔解開:$tar zxvf shoehorn-3.4.tar.gz
- 開始編譯Shoehorn,必須注意的是,系統的搜尋路徑必須包含cross compiler所在的路徑。$make編譯完成後在shoehorn-3.4/目錄下會出現shoehorn與loader.bin兩個檔案,如此Shoehorn的建立便完成。
Hermit downloader建立
如同Shoehorn一樣,建立完成的Hermit downloader也是分為Host端(hermit)與target端(loader.boot.bin、loader.flash.bin)兩部份的程式。如前所述Hermit downloader分別工作在EDB7209的兩種開機模式下,但Hermit必須依賴Shoehorn downloader才能順利運作。首先在Jumpered Boot Mode以Shoehorn downloader將loader.boot.bin下載至EDB7209的DRAM中並開始執行,接著以hermit與loader.boot.bin連線將loader.flash.bin下載至EDB7209 FLASH的Boot Sector中.
- 至下列網站下載Hermit原始程式碼hermit-1.1.tar.gz至/tmp目錄下:將其解開:$cd /tmp$tar zxvf hermit-1.1.tar.gz
- 如前所述,我們必須修改Hermit downloader的原始碼,而Hermit原始碼分host與target兩部份,我們所要修改的是target端的程式,修改完的程式經編譯後會成為loader.flash.bin檔,它便可以將kernel及ramdisk從FLASH中載入至DRAM中。進入/tmp/hermit-1.1/src/target/epp7211目錄,編輯linux.c檔:在linux.c檔前面加入以下定義:#define INITRD_SIZE 4096
#define INITRD_START DRAM2_START上述定義中,INITRD_SIZE定義的是我們的initial ramdisk的大小,以1kbytes為單位,在本論文中initial ramdisk大小是4000kbytes。而INITRD_START定義的是initial ramdisk被載入DRAM後的起始位址,也就是0xC100:0000。另外在函式linux_cmdfunc中加入下列宣告:unsigned char *dramptr;unsigned char *flashptr;unsigned rdsize;dramptr = (unsigned char *) DRAM2_START;flashptr = (unsigned char *) 0x003E8000;上面宣告了兩個指標,其中dramptr是initial ramdisk在DRAM中的起始位址,而flashptr則是initial ramdisk被燒錄在FLASH中的起始位址。在linux_cmdfunc函式中有以下程式:/* initialize param block *//* system page size */ps->u1.s.page_size = 0x1000;/* number of pages in all banks */ps->u1.s.nr_pages = 4096;/* param flags */ps->u1.s.flags = FLAG_READONLY | FLAG_RDLOAD;/* default root device is currently ramdisk; XXX should be flash */ps->u1.s.rootdev = MKDEV(RAMDISK_MAJOR, 0);/* pages per bank */ps->u1.s.pages_in_bank[0] = 2048;ps->u1.s.pages_in_bank[1] = 2048;這段程式的功用是在設定Linux kernel的參數,這些都是kernel的起始參數,主要是設定硬體的參數,我們必須加入下列參數:ps->u1.s.initrd_start = INITRD_START;ps->u1.s.initrd_size = 4096000;ps->u1.s.ramdisk_size = INITRD_SIZE;我們所加入的參數主要是設定系統的initial ramdisk起始位址(initrd_start)、initial ramdisk的大小(initrd_size,以byte為單位)以及ramdisk大小(ramdisk_size,以kbytes為單位,與initial ramdisk大小相同)。接下來在/* decompress kernel image to DRAM */gunzip_kernel();的下面加入以下程式:for(rdsize=0;rdsize < 4096000;rdsize++){*dramptr = *flashptr;dramptr++;flashptr++;}加入這段程式的目的是為了在將kernel從FLASH中載入DRAM後繼續將initial ramdisk載入。存檔後,繼續編輯keyboard.c檔:將#ifdef BOOTMODE#define EXT_KBD_ADDR 0x40000000#else#define EXT_KBD_ADDR 0x30000000#endif修改成#ifdef BOOTMODE#define EXT_KBD_ADDR 0x40010000#else#define EXT_KBD_ADDR 0x30010000#endif如同我們在kernel中的修改一樣,這麼做的原因是讓鍵盤能正常動作。 - 將程式修改完成後回到Hermit主目錄下,開始編譯程式。Hermit在編譯時分成兩部份,首先是編譯出loader.boot.bin:$cd /tmp/hermit-1.1$make BOOTMODE=bootstrap編譯完成後在src/target/ep7211目錄中會出現loader.bin檔,我們將其更名為loader.boot.bin,並將其搬移到Hermit主目錄下:$mv src/target/ep7211/loader.bin ./loader.boot.bin
- 接著要編譯出loader.flash.bin:$make scrub$make同樣的,編譯完成後在src/target/ep7211目錄下會產生loader.bin檔,此檔與前面的loader.bin不同,它將會在FLASH中執行,所以我們將其更名為loader.flash.bin,並搬移到Hermit主目錄下,同時也將hermit主程式搬移到Hermit主目錄下:$mv src/target/ep7211/loader.bin ./loader.flash.bin$mv src/host/common/hermit ./Hermit downloader建立完成。
在這裡我們將說明如何利用downloader(Shoehorn or Hermit)將kernel及initial ramdisk下載至EDB7209中。在整個系統的發展過程中,由於必需重覆的下載kernel與initial ramdisk,所以採用Shoehorn downloader是不錯的選擇。如前節所述,Shoehorn downloader是將kernel與initial ramdisk下載至EDB7209的DRAM中,唯一的缺點就是無法長久保存資料。而當我們的系統發展到一定階段後,為了達到嵌入式的目標,就必須讓kernel與initial ramdisk長存在硬體平台中,這時就要採用Hermit downloader,讓kernel與initial ramdisk可以儲存在FLASH中。下面將分別說明兩種downloader的下載過程。
Shoehorn downloader下載流程
在使用Shoehorn downloader下載kernel之前必須先確認kernel的設定,如前所述,在System type選項中的EDB7211 Boot Mode一定要勾選。
- 將Host端電腦與EDB7209(UART1)以null modem cable連接,而EDB7209另外有ethernet介面可視需求使用。將EDB7209板上的JP2短路,開啟EDB7209電源,進入Jumperred Boot Mode。
- 進入Shoehorn主目錄輸入以下命令下載: $./shoehorn --edb7211 --initrd ../ramdisk --ethernet –terminal --kernel ../arm_linux/linux/arch/arm/boot/Image_boot其中edb7211是用來指定硬體平台,ethernet選項則是指定採用Ethernet傳輸下載kernel與initial ramdisk。initrd指定initial ramdisk的檔名,預設是initrd。kernel選項是用來指定欲下載的核心檔名,預設為Image。loader選項則是指定欲下載至EDB7209 on-chip SRAM的loader檔名,預設為loader.bin。Terminal參數則是要求Shoehorn在下載完成後進入終端機模式,以便登入ARM Linux。
執行後,Shoekorn會等待EDB7209 wakeup,此時必須依序按下EDB7209板上的Reset按鈕及Wakeup按鈕,如此Shoehorn將自動開始下載。
在這裡我們採用乙太網路的方式來下載kernel與initial ramdisk,其速度將比採用序列埠傳輸快,但即使如此仍然須要利用序列埠來下載loader.bin,所以序列埠的連線一定要接上。當下載完成,若kernel編譯正確,且initial ramdisk內容完整,則此時EDB7209的LCD顯示幕便會出現開機畫面,且Host端亦會出現Linux的提示符號,表示以開機完成。
Hermit downloader下載流程
如前所述,Hermit必須依靠Shoehorn的幫助才能順利將kernel與initial ramdisk下載至EDB7209的FLASH中。另外,在使用Hermit下載kernel之前必須確定在編譯kernel時,EDB7211 Boot Mode選項不可勾選,並且在核心編譯完成後必須將Image以gzip壓縮。
- Hermit在target端共有兩個程式分別是loader.boot與loader.flash.bin。首先我們使用Shoehorn將loader.boot.bin下載到EDB7209的DRAM中,依照前述Shoehorn下載步驟,參數更改如下:
$cd /tmp/shoehorn --edb7211 --kernel=../hermit-1.1/loader.boot.bin --initrd /etc/motd --terminal
上述命令除了在kernel選項指定為我們所要下載的loader.boot.bin外,initrd的部份則任意指定一個檔案即可,下載完成後若出現Hermit提示符號則表是loader.boot.bin以開始執行。按Ctrl + c離開終端機模式。
2.進入Hermit主目錄,此時EDB7209上執行著loader.boot.bin,此時我們開始使用hermit與loader.boot.bin連線,並將loader.flash.bin下載到FLASH中:
3.成功將loader.flash.bin下載至FLASH後,接下來將EDB7209電源關閉,將JP2開路,重新開啟電源。按下EDB7209板子上的Reset按鈕,接著按住EDB7209鍵盤上的任意鍵不放,同時按一下EDB7209板子上的Wakeup按鈕,直到板子上的LED亮起才可放開鍵盤。如此做的原因是,loader.flash.bin開始執行時會先掃描鍵盤,當鍵盤上沒有任何鍵被按下時,它就會將FLASH中的kernel載入DRAM中執行。由於目前尚無kernel存在FLASH中,所以我們必須按住EDB7209的鍵盤任意鍵,讓loader.flash.bin繼續執行。我可以用以下命令確認loader.flash.bin是否正確執行:$./hermit download --force-locked --input-file ./loader.flash.bin --region flash-1此命令是告訴Hermit將loader.flash.bin下載至第一個FLASH區塊,並將此區塊設定為強制鎖定狀態(force locked)以避免此區塊被重複寫入。
$./hermit termial
若出現Hermit提示符號則表示正確。接下來我們就可以利用Hermit與loader.flash.bin連線來將kernel與initial ramdisk下載至FALSH:
$./hermit download --input-file ../arm_linux/linux/arch/arm/boot/Image.gz \
--address 0x10000 --ethernet --remote-mac 12:34:56:78:9a:bc
上述命令會將Image.gz檔以乙太網路傳輸至EDB7209,並FLASH的0x10000位址開始寫入。之所以從0x10000開始寫入是因為要避開前面的loader.flash.bin,以免重疊。而Hermit使用乙太網路傳輸必須指定EDB7209的MAC address,在此只須輸入任意位址即可。
4. kernel下載成功後接下來就是initial ramdisk的下載:
$./hermit download --input-file ../ramdisk --address 0x003E8000 --ethernet \
--remote-mac 12:34:56:78:9a:bc
如同下載kernel的步驟,將input-file參數改為ramdisk,而位址亦需跳過kernel的所在位址,從0x003E8000開始寫入,這個位址也已經被我們寫死在loader.flash.bin程式碼中。
5. initial ramdisk下載完成後,按下EDB7209板子上的Reset按鈕,讓系統重置,接著按下Wakeup按鈕,此時以不用再按住EDB7209的鍵盤,讓loader.flash.bin將kernel與initial ramdsik載入DRAM並開始執行kernel。若kernel編譯正確,且initial ramdisk內容完整,則不久後即可在EDB7209的LCD顯示幕上看到開機訊息。
No comments:
Post a Comment