王劍飛, 程耀瑜
(中北大學山西省現(xiàn)代無損檢測工程技術研究中心, 山西太原 030051)
嵌入式系統(tǒng)具有低功耗、實時性強和穩(wěn)定性高等優(yōu)點,在軍事、工業(yè)和家用等領域得到廣泛的應用。國內(nèi)對嵌入式系統(tǒng)的一般定義是:以應用為中心,以計算機技術為基礎,軟硬件可裁剪,從而能夠適應實際應用中對功能、可靠性、成本、體檢、功耗等嚴格要求的專用計算機系統(tǒng)[1]。而操作系統(tǒng)的移植已成為嵌入式系統(tǒng)設計中的重要環(huán)節(jié),具有可觀的市場價值。
對于嵌入式系統(tǒng)的開發(fā)需要建立交叉編譯環(huán)境,交叉編譯環(huán)境就是在一個平臺上生成可以在另一個平臺上執(zhí)行的代碼的編譯環(huán)境。Linux內(nèi)核完全使用C和GNU形式的匯編完成因此嵌入式Linux的開發(fā)環(huán)境采用了GNU工具鏈的交叉開發(fā)平臺。通過GNU提供的編譯器cc/gcc、連接器ld/gld、匯編器as/gas和C函數(shù)庫glibc以及精簡的C庫uClib,就可以建立完整的交叉開發(fā)環(huán)境來完成從開發(fā)GNU工具鏈針對不同的處理器提供了多種交叉開發(fā)平臺[2]。
本次移植過程中使用的宿主機的操作系統(tǒng)是Ubuntu9.10。使用支持軟浮點編譯的交叉編譯器arm-linux-gcc-3.4.5編譯U-boot,而使用支持EABI技術的交叉編譯器arm-linux-gcc-4.3.3編譯Linux內(nèi)核及根文件系統(tǒng)。使用PATH設置交叉編譯路徑[3]。將交叉編譯器的源碼包解壓到宿主機/usr/local/目錄下,然后修改環(huán)境變量:
# vi /etc/environment
PATH=/usr/local/4.3.3/bin
為了使新的環(huán)境變量生效,使用命令:source/etc/environment, 此 時,arm-linux-gcc-4.3.3交叉編譯環(huán)境就建立了。
Bootloader的作用與PC上的BIOS類似,它在系統(tǒng)上電時執(zhí)行,初始化硬件設備、準備好軟件環(huán)境,最后調(diào)用操作系統(tǒng)的內(nèi)核。Bootloader的實現(xiàn)非常依賴于具體的硬件,在嵌入式系統(tǒng)中硬件的配置千差萬別,即使是相同的CPU,它的外設也可能不同,因此在嵌入式領域幾乎不可能有統(tǒng)一的Bootloader支持所有的電路板?,F(xiàn)在Bootloader種類繁多,比如x86上有LILO、GRUB等。不同的板級硬件,都需要進行U-Boot的移植工作[4]。對于ARM架構(gòu),有U-Boot、Vivi等。U-Boot支持大多數(shù)的CPU,具有較高的可靠性和穩(wěn)定性。同時由于其開放源碼,可以根據(jù)嵌入式Linux系統(tǒng)開發(fā)的需要增強U-Boot的功能。
U-Boot的啟動過程可以分為兩個階段:第一階段使用匯編來實現(xiàn),完成同CPU體系結(jié)構(gòu)相關的初始化,并調(diào)用第二階段代碼;第二階段使用C語言實現(xiàn),完成部分硬件的初始化及檢測,最終啟動內(nèi)核[5]。
第一階段主要內(nèi)容包括:
(1)硬件設備初始化:調(diào)整CPU工作模式、設置CPU速度和時鐘頻率、關閉MMU等。
(2)為加載U-Boot的第二階段代碼準備RAM空間:調(diào)用lowlevel_init函數(shù)來設置存儲控制器,初始化外接的SDRAM。
(3)復制U-Boot第二階段的代碼到RAM空間。
(4)設置堆棧。
(5)跳轉(zhuǎn)到U-Boot第二階段代碼的C入口點:跳轉(zhuǎn)之前,應清除BSS段。
第二階段主要內(nèi)容包括:
(1)初始化相關的硬件設備。
(2)檢測系統(tǒng)內(nèi)存映射。
(3)將內(nèi)核和根文件映像復制到RAM空間。
(4)為內(nèi)核設置啟動參數(shù)。
(5)調(diào)用內(nèi)核。
對于ARM架構(gòu)的CPU,是通過do_bootm_linux函數(shù)來啟動內(nèi)核。這個函數(shù)中,設置標記列表,通過theKernel(0,bd->bi_arch_number,bd->bi_boot_params)調(diào)用內(nèi)核。其中,theKernel指向內(nèi)核存放的地址,bd->bi_arch_number就是在U-Boot中設置的機器類型ID,而bd->bi_boot_params就是標記列表的開始地址[6]。
從U-Boot的官方網(wǎng)站下載U-Boot-1.1.6.tar。bz2后解壓可以得到全部源碼。U-Boot的移植除了依賴CPU的體系結(jié)構(gòu)外,還依賴于具體嵌入式開發(fā)板外設的配置情況。在獲得U-Boot源碼后,需要根據(jù)自己開發(fā)板的具體情況和嵌入式開發(fā)的相應需要修改部分源碼。該版本的U-Boot不支持ARM微處理器S3C2440,但對同一系列的S3C2410有著完善的支持。由于兩款微處理器在架構(gòu)和使用上很接近,所以移植工作可以在對應的SMDK2410開發(fā)板的源碼上做必要的修改,并且添加部分代碼增強U-Boot的功能,以方便嵌入式系統(tǒng)的后期開發(fā)工作。
(1)進入U-Boot-1.1.6的源碼目錄,將board/smdk2410目錄復制為wang2440目錄。修改wang2440目錄下smdk2410.c為wang2440.c。同時修改該目錄下Makefile文件:COBJS:= wang 2440.o flash.o。 進入include/configs目錄, 將smdk2410.h復制為wang2440.h 。
(2)在頂層Makefile中增加:Wang2440_config :unconfig@$(MKCONFIG) $(@:_config=)arm arm920t wang2440 NULL s3c24x0
各項的意思如下:
arm:CPU的架構(gòu)(ARCH)
arm920t:CPU的類型(CPU),對應于CPU/arm920t子目錄。
wang2440:開發(fā)板的型號(BOARD),對應于board/wang2440目錄。
NULL:開發(fā)者或經(jīng)銷商(vender),此處NULL為沒有。
S3c24x0:片上系統(tǒng)(SOC)。
(3)修改SDRAM配置和時鐘設置,使其適應具體S3C2440開發(fā)板的配置。
(4)在cpu/arm920t/s3c24x0目錄中增加NAND flash讀取函數(shù)nand_flash.c。添加S3C2440 nand的驅(qū)動函數(shù),同時修改nand_flash.c中的s3c24x0_init(void)函數(shù),定義S3C2440 NAND flash的時鐘和初始化NAND flash 。在board/wang2440目錄下增加boot_init.c文件,讓U-Boot支持從nand flash啟動。
(5)U-Boot中沒有提供對yaffs文件讀寫支持,可以通過增加nand write.yaffs命令實現(xiàn)對yaffs文件的讀寫支持。在commom/cmd_nand.c中增加處理函數(shù)do_nand.c實現(xiàn)對nand yaffs的支持。由于yaffs文件本身就包含了OOB區(qū)的數(shù)據(jù)(壞塊標記、ECC校驗碼、其他yaffs相關信息),所以燒寫時不需要再計算ECC值。
完成以上修改以后使用交叉編譯工具armlinux-gcc-3.4.5編譯U-Boot,在U-Boot目錄輸入:
make ARCH=arm CROSS_COMPILE=armlinux- wang2440_config
make ARCH=arm CROSS_COMPILE=armlinux- all
可以產(chǎn)生u-boot.bin文件。通過JTAG燒入開發(fā)板并復位,在SecureCRT終端輸出如圖1所示。
圖1 u-boot運行結(jié)果
Linux的啟動過程可以分為兩部分:架構(gòu)與開發(fā)板相關的引導過程、后續(xù)的啟動過程。引導階段通常使用匯編語言編寫,首先檢查內(nèi)核是否支持當前架構(gòu)的處理器,然后檢查是否支持當前開發(fā)板。第二階段使用C語言編寫,進行內(nèi)核初始化的工作,最后調(diào)用rest_init函數(shù),創(chuàng)建第一個進程init。如圖2中是ARM架構(gòu)處理器上Linux內(nèi)核的啟動過程。
圖2 Linux內(nèi)核啟動過程
對Linux內(nèi)核的移植是一個非常繁雜的過程,在對Linux內(nèi)核深入了解的基礎上,需要添加、修改相關的代碼并對內(nèi)核進行配置。Linux內(nèi)核的確切能力取決于內(nèi)核構(gòu)建時所設定的配置。內(nèi)核的配置可以讓你移除非必要的支持或永遠不會被用到的能力[7]。從官方網(wǎng)站可以下載Linux-2.6.30.4.tar.bz2,解壓后可以得到Linux源碼包。
修改Makefile文件,設置目標平臺和指定交叉編譯器。修改 Makefile中 ARCH=arm 和CROSS_COMPILE=arm-linux-,然后保存退出。修改平臺時鐘頻率,修改內(nèi)核源碼arch/arm/mach-s3c2440/mach-smdk2440.c文件,通過函數(shù)s3c24xx_init_clocks(12000000)獲得12M的外部時鐘源輸入。修改機器碼,機器碼在內(nèi)核的arch/arm/mach-smdk2440.c文件中,確保機器碼的值和U-boot中的一致。
設置分區(qū)信息,將NAND Flash劃分為3個分區(qū),修改內(nèi)核源碼arch/arm/plat-s3c24xx/common-smdk.c文件中結(jié)構(gòu)體smdk_default_nand_part[]如下:
禁止ECC校驗,修改drivers/mtd/nand/s3c2410.c文件,將chip->ecc.mode修改為chip->ecc.mode = NAND_ECC_NONE。
(3)配置內(nèi)核,將arch/arm/configs/s3c2410_deconfig復制到.config文件,在默認配置單的基礎上,通過make menuconfig命令 對內(nèi)核進行必要的配置,把最終的配置結(jié)構(gòu)保存為.config文件。
在內(nèi)核源碼目錄下輸入:make zImage,編譯內(nèi)核源碼,編譯完成后在arch/arm/boot目錄下生成zImage鏡像,將其燒入開發(fā)板中,可以得到內(nèi)核啟動時的分區(qū)信息如圖3所示。
圖3 MTD分區(qū)信息
Linux內(nèi)核在系統(tǒng)啟動期間所進行的最后操作就是掛載根文件系統(tǒng),文件系統(tǒng)對系統(tǒng)中的文件和設備進行組織,為設備和用戶提供統(tǒng)一接口[8]。Linux根文件系統(tǒng)的作用時存放各種工具、應用程序和必需的鏈接庫等。使用Busybox可以簡化制作嵌入式系統(tǒng)根文件系統(tǒng)的過程,因此,Busybox工具在嵌入式開發(fā)中廣泛應用。從官方網(wǎng)站下載Busybox-1.15.2.tar.bz2,解壓后可以得到源碼。進入源碼目錄,修改Makefile文件,執(zhí)行make menuconfig進行配置Busybox,根據(jù)實際需要添加或去除某些選項。配置完畢后,執(zhí)行make、make install命令為新建的根文件系統(tǒng)添加/usr、/bin、/sbin等目錄。
定制根文件系統(tǒng)的步驟如下:
(1)創(chuàng)建目錄,在新建的根文件系統(tǒng)目錄下,建立etc、dev、mnt等常見的Linux系統(tǒng)目錄;
(2)創(chuàng)建設備節(jié)點;
(3)添加所需的庫文件;
(4)配置系統(tǒng)文件;
(5)指定應用程序。
文件系統(tǒng)框架制作好后,使用mkyaffs2image工具,制作yaffs鏡像。把可執(zhí)行文件復制到/usr/bin目錄下,制作文件系統(tǒng)鏡像:mkyaffs2image root root.bin,將生成的root.bin文件燒入開發(fā)板,復位開發(fā)板后,在串口終端輸入ls命令,結(jié)果如圖4所示。
圖4 根文件系統(tǒng)目錄
本文系統(tǒng)介紹了以S3C2440的ARM9處理器為硬件平臺的嵌入式Linux系統(tǒng)的移植過程。針對U-boot的源碼進行了必要的修改,方便嵌入式Linux系統(tǒng)的后續(xù)開發(fā)工作。對嵌入式Linux內(nèi)核的移植及根文件系統(tǒng)的創(chuàng)建方法進行總結(jié)。嵌入式Linux系統(tǒng)移植于嵌入式底層開發(fā)平臺對嵌入式系統(tǒng)開發(fā)設計具有重要意義。移植后的Linux系統(tǒng)在ARM平臺下穩(wěn)定工作。
[1]徐英慧,馬忠梅.ARM9嵌入式系統(tǒng)設計-基于S3C2410與Linux[M].北京:北京航空航天大學出版社,2010.
[2]劉文峰,李程遠,李善平.嵌入式Linux操作系統(tǒng)的研究[J].浙江大學學報:工學版,2004,38(4).
[3]宋凱,嚴麗平.ARM Linux在S3C2410上的移植[J].計算機工程與設計,2008,29(16).
[4]鄒穎婷,李紹榮.ARM9上的嵌入式Linux系統(tǒng)移植[J].自動化技術與應用,2009,28(6).
[5]師磊.U-Boot在S3C2440上的分析與移植[J].計算機系統(tǒng)應用,2010,19(4).
[6]韋東山.嵌入式Linux應用開發(fā)完全手冊[M].北京:人民郵電出版社,2008.
[7]Karim Yaghmour, Jonathan Masters, Gilad Ben-Yossef.Building Embedded Linux Systems[M].O’Reilly,2003.
[8]師娟娟,彭迪.基于ARM9的嵌入式Linux移植[J].武漢理工大學學報,2008,30(2).