《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 嵌入式技術(shù) > 設(shè)計(jì)應(yīng)用 > 基于AT91RM9200的ARM Linux的移植方法
基于AT91RM9200的ARM Linux的移植方法
中電網(wǎng)
摘要: 本文根據(jù)一個(gè)特定的目標(biāo)平臺(tái),結(jié)合AT91RM9200的開(kāi)發(fā)經(jīng)驗(yàn),詳細(xì)介紹了將Linux移植到ARM構(gòu)建的嵌入式系統(tǒng)上的主要技術(shù)和整個(gè)流程,實(shí)現(xiàn)了Linux向目標(biāo)系統(tǒng)AT91RM9200的移植,移植后的操作系統(tǒng)在目標(biāo)板上運(yùn)行穩(wěn)定,并且可以根據(jù)實(shí)際需要編寫(xiě)相應(yīng)的控制程序,將其應(yīng)用于實(shí)際工業(yè)控制中。掌握這些技術(shù),對(duì)于開(kāi)發(fā)嵌入式系統(tǒng)十分重要,對(duì)開(kāi)發(fā)其他類(lèi)型的嵌入式系統(tǒng)同樣具有參考意義。
Abstract:
Key words :

1.引言
目前,在嵌入式系統(tǒng)里基于ARM微核的嵌入式處理器以其功耗低,功能強(qiáng)大的優(yōu)點(diǎn)已經(jīng)成為市場(chǎng)的主流。與此同時(shí),在網(wǎng)絡(luò)上發(fā)展起來(lái)的Linux操作系統(tǒng),以其功能強(qiáng)大,開(kāi)放源代碼,支持硬件種類(lèi)眾多的特點(diǎn),越來(lái)越受到人們的青睞。然而如何把Linux操作系統(tǒng)移植到ARM平臺(tái)上卻成了一個(gè)重點(diǎn),也是一個(gè)難點(diǎn)問(wèn)題。

嵌入式Linux系統(tǒng)包括引導(dǎo)程序(Bootloader),內(nèi)核(kernel)和根文件系統(tǒng)三個(gè)部分,其開(kāi)發(fā)流程如圖1所示:嵌入式Linux 移植到特定的硬件平臺(tái)上,一般需要以下五個(gè)步驟:(1)前期準(zhǔn)備包括從網(wǎng)站http://kernel.org上下載嵌入式Linux的源碼包, 搭建交叉編譯開(kāi)發(fā)環(huán)境,配置主機(jī)的開(kāi)發(fā)環(huán)境等(2)配置Bootloader,并將其燒寫(xiě)到目標(biāo)平臺(tái)的Flash上,使其能正常的啟動(dòng)內(nèi)核;(3)配置和編譯Linux內(nèi)核,首先要對(duì)源碼進(jìn)行一定的修改, 并將其移植到目標(biāo)平臺(tái)上,然后再根據(jù)自己的硬件資源進(jìn)行裁減,使內(nèi)核達(dá)到最優(yōu);(4)制作RAMDISK來(lái)掛接Linux的根文件系統(tǒng),并在 RAMDISK上添加自己的應(yīng)用程序;(5)部署Linux系統(tǒng)使目標(biāo)板脫離交叉開(kāi)發(fā)環(huán)境,直接在目標(biāo)機(jī)上本地啟動(dòng)運(yùn)行。本文就將根據(jù)實(shí)際項(xiàng)目開(kāi)發(fā)中一個(gè) ARM構(gòu)架的嵌入式系統(tǒng)為例,闡述如何移植Linux到AT91RM9200的ARM平臺(tái)上。

29.jpg

2.建立交叉編譯環(huán)境

一般而言,直接在移植的目標(biāo)硬件平臺(tái)上編寫(xiě)和調(diào)試Linux比較困難,目前一般采用的辦法是首先在通用計(jì)算機(jī)上編寫(xiě)程序,然后通過(guò)交叉編譯生成目標(biāo)平臺(tái)上可以運(yùn)行的二進(jìn)制代碼格式,最后再下載到目標(biāo)平臺(tái)上的特定位置上運(yùn)行。

移植前需要在宿主機(jī)上建立如圖2所示的ARM的交叉編譯環(huán)境,建立ARM的交叉編譯環(huán)境主要用到的開(kāi)發(fā)工具有: binutils、gcc、glibc,其中 binutils是二進(jìn)制文件的處理工具; gcc是編譯工具, 用來(lái)編譯內(nèi)核代碼的工具; glibc 是鏈接和運(yùn)行庫(kù)。社區(qū)的開(kāi)發(fā)者和一些芯片廠商已經(jīng)編譯出了常用體系結(jié)構(gòu)的工具鏈,使用這些工具鏈,可以大大減少工作量。交叉編譯工具的安裝步驟如下: (1)從官方站點(diǎn)http://arm.Linux.org.uk下載cross-2.95.3.tar.bz2;

(2)在usr/local/arm下解壓:#tar -jxvf cross-2.95.3.tar.bz2;

(3)在/etc/bashrc文件中修改PATH環(huán)境變量,加入export PATH=/usr/local/arm/2.95.3/bin:$PATH。

3. ARM Linux系統(tǒng)的開(kāi)發(fā)

3.1 Linux啟動(dòng)代碼Bootloader的移植

Bootloader是在操作系統(tǒng)內(nèi)核運(yùn)行之前運(yùn)行的一段小程序。這段程序完成硬件的初始化和建立內(nèi)存空間的映射圖等重要工作,為內(nèi)核的啟動(dòng)創(chuàng)建正確的環(huán)境,并最終啟動(dòng)內(nèi)核,Bootloader在Linux嵌入式系統(tǒng)中所處的層次位置如圖3所示。Bootloader的實(shí)現(xiàn)依賴(lài)于CPU的體系結(jié)構(gòu),大多數(shù)的Bootloader都分為stage 1和stage 2兩大部分,圖4為兩階段Bootloader的結(jié)構(gòu)框圖。依賴(lài)于CPU體系結(jié)構(gòu)的代碼,如設(shè)備初始化代碼等,通常都放在stage 1,而且用匯編語(yǔ)言實(shí)現(xiàn)。而stage 2則通常用C語(yǔ)言實(shí)現(xiàn),這樣可以實(shí)現(xiàn)復(fù)雜功能,而且有更好的可讀性和移植性。

30.jpg

目前基于嵌入式系統(tǒng)的Bootloader版本很多,如Blob、Redboot、Vivi和U-Boot等,下面就以現(xiàn)在最流行的U-Boot為例,詳細(xì)介紹如何將它移植到自己的目標(biāo)板上。U-boot移植主要步驟如下:

首先基于自己的目標(biāo)板的硬件資源,修改或添加U-Boot源代碼的board/at91rm9200目錄中如下源碼文件:(1)重寫(xiě)FLASH的設(shè)備控制程序flash.c , U-Boot讀、寫(xiě)和刪除Flash設(shè)備的源代碼文件。由于在不同目標(biāo)板中FLASH存儲(chǔ)器種類(lèi)各不相同,參照自己flash的datasheet重寫(xiě) flash的設(shè)備控制程序flash.c,該程序完成的功能包括Flash初始化、打印Flash信息、Flash擦除和Flash寫(xiě)入等操作。(2)添加memsetup.s。該匯編源碼文件初始化時(shí)鐘、SMC控制器和SDRAM控制器。(3)添加網(wǎng)卡芯片DM9161E的設(shè)備控制程序dm9161.c 和dm9161.h,程序。(4)修改Makefile文件。對(duì)上述修改或添加的源代碼文件編譯后,在Makefile里面主要做如下修改: OBJS :=at91rm9200dk.c at45.o dm9161.o flash.o  SOBJS:=memsetup.o(5) U-Boot.lds ,設(shè)置U-boot中各個(gè)目標(biāo)文件的連接地址,基本不做修改。(6)config.mk。根據(jù)目標(biāo)板的一級(jí)boot來(lái)修改,修改后TEXT BASE=0x21f00000。

其次,修改目錄include/configs的頭文件at91rm9200dk.h,根據(jù)目標(biāo)板的資源配置,修改內(nèi)容包括CPU ,系統(tǒng)時(shí)鐘、RAM 、Flash等配里信息以及內(nèi)存映射相關(guān)參數(shù)。該頭文件還定義了U-Boot的一些環(huán)境變量和內(nèi)核啟動(dòng)參數(shù).可在U-Boot啟動(dòng)后通過(guò)setenv和 saveenv命令修改。U-Boot-1.1.2版本對(duì)at91rm9200處理器提供良好的支持,因此對(duì)于目錄CPU at91rm9200中的源碼基本不做修改。在U-Boot-1.1.2的Makefile中加入如下代碼:

at91rm9200dk_config: unconfig@/mkconfig $(@: _config=) arm at91rm9200 at91rm9200dk

其中“arm”是CPU的種類(lèi),at91rm9200是ARM CPU對(duì)應(yīng)的代碼目錄,at91rm9200dk是目標(biāo)板對(duì)應(yīng)的目錄。由于交叉編譯器安裝在目錄/usr/local/arm,應(yīng)把環(huán)境變量 CROSS_COMPILE設(shè)置成相應(yīng)路徑:CROSS_COMPILE=/usr/local/arm/2.95.3 /bin/arm-linux-

最后,調(diào)試U-Boot源代碼,直到U-Boot在開(kāi)發(fā)板上能正常啟動(dòng),調(diào)試成功后,燒寫(xiě)U-Boot到FLASH,燒寫(xiě)完成后,復(fù)位目標(biāo)板,串口終端就顯示U-Boot的啟動(dòng)信息。

3.2  Linux內(nèi)核的移植、配置和編譯

 

31.jpg

標(biāo)準(zhǔn)Linux內(nèi)核相對(duì)于資源受限的嵌入式系統(tǒng)來(lái)說(shuō)是過(guò)于龐大,整個(gè)代碼分布如圖5所示,因此要將其移植到嵌入式系統(tǒng)上,就需要將Linux內(nèi)核根據(jù)目標(biāo)平臺(tái)的情況進(jìn)行剪裁、配置,該目標(biāo)板的主要硬件資源如圖6所示。和ARM體系結(jié)構(gòu)相關(guān)的代碼都放在arch/arm/以及include/asm-arm/目錄下,將linux移植到ARM平臺(tái)上,主要修改這兩個(gè)目錄下的代碼。要想使linux內(nèi)核應(yīng)用于自己的ARM平臺(tái)AT91RM9200上,必須對(duì)內(nèi)核的源代碼做一定的修改,主要修改部分如下:(1) 修改根目錄下的Makefile文件,確認(rèn)ARCH和CROSS_COMPILE的定義:ARCH :=arm; CROSS_COMPILE :=arm-linux- (2)修改arch目錄下的Makefile文件,根據(jù)自己的電路設(shè)置TEXTADDR變量,TEXTADDR決定內(nèi)核起始運(yùn)行地址,即 image.ram應(yīng)下載的地址。(3)修改arch目錄下的config.in 文件,添加CONFIG_ARCH_AT91RM9200自選項(xiàng),config文件決定了menuconfig菜單的內(nèi)容,把使用的平臺(tái)加在需要的地方,這樣在配置linux內(nèi)核時(shí)就能夠選擇是否支你的平臺(tái)了。

(4)修改arch/arm/boot目錄下的Makefile文件,根據(jù)自己的電路設(shè)置ZTEXTADDR和ZRELADDR, ZTEXTADDR和ZRELADDR分別是自解壓代碼的起始地址和內(nèi)核解壓后代碼輸出起始地址。(5)修改arch/arm/boot /compressed目錄下的Makefile文件,加入head-at91rm9200.S (6)修改arch/arm/kernel目錄下的Makefile文件,增加AT91RM9200的支持,同時(shí)在    debug-armv.S中加入關(guān)閉全部外圍設(shè)備,保證系統(tǒng)正常運(yùn)行的代碼,在entry-armv.S中加入關(guān)于CPU中斷處理部分的代碼。(7)修改 arch/arm目錄下的mm-armv.c文件,將init_maps->bufferable=0改為init_maps-> bufferable=1;

當(dāng)然,一些大的芯片開(kāi)發(fā)商在發(fā)行芯片的同時(shí),針對(duì)自己芯片的體系結(jié)構(gòu)對(duì)linux內(nèi)核作了一些補(bǔ)丁。實(shí)驗(yàn)中使用的是針對(duì)AT91RM9200體系結(jié)構(gòu)的補(bǔ)丁patch-2.4.19-rmk7給標(biāo)準(zhǔn)內(nèi)核源代碼打上補(bǔ)丁后,該內(nèi)核就可應(yīng)用于AT91RM9200了,這樣可以大大減少開(kāi)發(fā)的工作量。

移植之后要做的工作就是編譯內(nèi)核,要想編譯適合自己工程中需要的內(nèi)核,首先要對(duì)內(nèi)核進(jìn)行配置,常用的配置命令有:make config;make oldconfig;make menuconfig;make xconfig;make defconfig;Linux內(nèi)核包允許用戶(hù)對(duì)其各類(lèi)功能逐項(xiàng)配置,在配置時(shí), 大部分選項(xiàng)可以使用其缺省值, 只有小部分需要根據(jù)用戶(hù)不同需要選擇。選擇的原則是將與內(nèi)核其它部分關(guān)系較遠(yuǎn)部分且不經(jīng)常使用的部分功能代碼編譯成為可加載模塊, 有利于減小內(nèi)核的長(zhǎng)度, 減小內(nèi)核消耗的內(nèi)存,不需要的功能就不要選, 與內(nèi)核緊密且經(jīng)常使用的部分功能代碼直接編譯到內(nèi)核中。主要是進(jìn)行以下幾項(xiàng)配置: (1)選擇處理器類(lèi)型;(2)選擇板級(jí)支持;(3)選擇對(duì)RAMDISK支持、對(duì)設(shè)備驅(qū)動(dòng)的支持以及對(duì)文件系統(tǒng)的支持。在配置工作完成后, 就可以進(jìn)行內(nèi)核編譯。

編譯內(nèi)核有壓縮方式和非壓縮兩種方式。非壓縮方式使用make vmlinux來(lái)編譯內(nèi)核,或者直接運(yùn)行make命令。壓縮方式用make bzImage來(lái)編譯內(nèi)核。編譯成功后會(huì)在arch/arm/boot目錄中生成內(nèi)核的鏡像,此鏡像下載到flash中就可以通過(guò)bootloader引導(dǎo)。具體的編譯步驟如下:(1) 進(jìn)入打上補(bǔ)丁修改好的內(nèi)核源代碼目錄下,執(zhí)行make mrproper;make clean這兩條指令,將源代碼清理干凈(防止以前編譯產(chǎn)生的“垃圾”干擾)。(2)執(zhí)行make at91rm9200dk_config,使源代碼按照AT91RM9200體系結(jié)構(gòu)來(lái)配置。 (3)執(zhí)行make o1dconfig(保存原編譯配置)(4)執(zhí)行make menuconfig進(jìn)入內(nèi)核編譯前配置界面,進(jìn)行配置。(5)執(zhí)行make dep聲稱(chēng)編譯要用的依賴(lài)文件。(6)執(zhí)行make zImage生成內(nèi)核鏡像。

3.3 文件系統(tǒng)的移植

linux采用文件系統(tǒng)組織系統(tǒng)中的文件和設(shè)備,為設(shè)備和用戶(hù)程序提供統(tǒng)一接口。linux要啟動(dòng)起來(lái)還需要有根文件系統(tǒng)。根文件系統(tǒng)的作用是存放各種工具(如Linux命令)、應(yīng)用程序、必需的鏈接庫(kù)等等。通常用busybox來(lái)制作根文件系統(tǒng),在busybox中包含一百多種Linux上標(biāo)準(zhǔn)的工具程序, 而這些工具程序僅需幾百k空間。busybox使用非常方便, 只要建立一個(gè)符號(hào)連接即可, 用戶(hù)可以通過(guò)配置Config.h 和Makefile文件來(lái)定制busybox。將busybox復(fù)制到bin目錄中,分別使用ln-s 建立每一個(gè)命令的符號(hào)連接。但應(yīng)該注意的是busybox需要glibc支持(如果使用靜態(tài)連接則不需要glibc 庫(kù)文件),因此還需要將運(yùn)行busybox所需的庫(kù)文件copy到lib目錄中, 并建立符號(hào)連接。到此為止, ARM Linux 的根文件系統(tǒng)就已經(jīng)建立起來(lái)了。

ARM Linux采用RAMDISK的方式來(lái)裝載根文件系統(tǒng),所以在運(yùn)行內(nèi)核之前,需要先制作RAMDISK,將必須的文件和設(shè)備加人到RAMDISK中。內(nèi)核啟動(dòng)后,會(huì)從指定地址去讀取根文件系統(tǒng),這里我們使用RAMDISK在內(nèi)存中虛擬一個(gè)磁盤(pán),具體方法如下:

(1)首先創(chuàng)建一個(gè)2048k的虛擬磁盤(pán),文件名為initrd.img:# dd  if= dev/zero of=initrd.img bs= lk count= 2048  (2)將該虛擬磁盤(pán)文件格式化成Ext2格式:# mkfs ext2 -c initrd.img這就生成了一個(gè)支持Ext2文件系統(tǒng)的ramdisk  (3)mount這個(gè)文件系統(tǒng)到/tmp下,# mount -o loop -t ext2 initrd.img /tmp  (4)向/tmp中添加linux啟動(dòng)必須的文件和設(shè)備。 # cd  /tmp;  # mkdir bin dev etc lib mnt proc sbin sys usr  以上這幾個(gè)程序和設(shè)備是啟動(dòng)Linux必須的,這樣得到的ramdisk大約400k  (5)創(chuàng)建設(shè)備節(jié)點(diǎn),添加相應(yīng)的程序,將已經(jīng)訂制好的一個(gè)文件系統(tǒng)全部復(fù)制過(guò)來(lái)。# cp –a  myfs/*  /tmp  (6)壓縮映像,把loop設(shè)備卸載下來(lái),然后用gzip命令把映像壓縮一下。# umount /tmp ;  #gzip –best –c initrd.img > initrd.img.gz現(xiàn)在我們就得到了一個(gè)壓縮的RAMDISK映像initrd.img.gz制作好了。

32.jpg

4. 內(nèi)核的下載和執(zhí)行

要想使目標(biāo)板的Linux系統(tǒng)脫離交叉開(kāi)發(fā)環(huán)境,直接在目標(biāo)機(jī)上本地啟動(dòng)運(yùn)行,必須通過(guò)U-boot將U-boot映像,內(nèi)核映像和RAMDISK 映像燒寫(xiě)到FLASH中,因?yàn)槭褂肬-boot引導(dǎo)程序需要使用U-boot格式的內(nèi)核映像和RAMDISK映像,可以通過(guò)以下命令來(lái)實(shí)現(xiàn):
($U-BOOT-PATH)/tools /mkimage -A arm -O linux -T kernel -C gzip –a 0x20008000 -e 0x20008000 –n “linux-2.4.19”-d linux.bin.gz uImage
($U-BOOT-PATH)/tools/mkimage-A arm -O linux -T ramdisk -C gzip –a 0x21100000 -e 0x21100000 –n “RAMDISK”-d ramdisk.bin ramdisk

通過(guò)U-boot將uImage和ramdisk燒寫(xiě)到flash相應(yīng)的分區(qū)中去,燒寫(xiě)到flash相應(yīng)分區(qū)的地址如圖7所示:燒寫(xiě)完畢后設(shè)置u- boot的環(huán)境變量,讓系統(tǒng)自動(dòng)啟動(dòng),系統(tǒng)復(fù)位后,Linux系統(tǒng)就可以完全自動(dòng)從本地flash啟動(dòng)了,啟動(dòng)后,進(jìn)行地址映射,u-boot會(huì)把u- boot壓縮映像,kernel壓縮映像,ramdisk壓縮映像全部拷貝到SDRAM的相應(yīng)地址,SDRAM的映射地址如圖8所示,這時(shí)Linux系統(tǒng)完全在SDRAM中運(yùn)行了,Linux系統(tǒng)真正啟動(dòng)起來(lái)了。

5. 總結(jié)

本文根據(jù)一個(gè)特定的目標(biāo)平臺(tái),結(jié)合AT91RM9200的開(kāi)發(fā)經(jīng)驗(yàn),詳細(xì)介紹了將Linux移植到ARM構(gòu)建的嵌入式系統(tǒng)上的主要技術(shù)和整個(gè)流程,實(shí)現(xiàn)了Linux 向目標(biāo)系統(tǒng)AT91RM9200的移植,移植后的操作系統(tǒng)在目標(biāo)板上運(yùn)行穩(wěn)定,并且可以根據(jù)實(shí)際需要編寫(xiě)相應(yīng)的控制程序,將其應(yīng)用于實(shí)際工業(yè)控制中。掌握這些技術(shù),對(duì)于開(kāi)發(fā)嵌入式系統(tǒng)十分重要,對(duì)開(kāi)發(fā)其他類(lèi)型的嵌入式系統(tǒng)同樣具有參考意義。

本論文作者創(chuàng)新點(diǎn):從軟件與硬件的相互關(guān)系, 硬件對(duì)軟件的制約、硬件對(duì)軟件的支持這個(gè)角度對(duì)裁減和移植進(jìn)行了分析,同時(shí)在Bootloader(啟動(dòng)代碼)的移植,Kernel(內(nèi)核)的裁減和移植過(guò)程中,把代碼分成了兩部分,一部分是和硬件相關(guān)的部分,一部分是和硬件無(wú)關(guān)的部分,這樣做不僅思路清晰,而且可以大大減少工作量。

參考文獻(xiàn):
[1] 許先斌, 熊慧君, 李淵, 楊芬. 基于ARM9 的嵌入式Linux開(kāi)發(fā)流程的研究[J]微計(jì)算機(jī)信息. 2006,11:87-90
[2] 劉振綱,劉成安,盧劍翔. 移植標(biāo)準(zhǔn)Linux 到S3C2410[J] 微計(jì)算機(jī)信息.2006,32:152-154
[3] 羅致,王仲東. ARM Linux在AT91RM9200平臺(tái)上的移植.軟件技術(shù),2006年第25卷第1期 
[4] 李明,ARM Linux的移植過(guò)程及分析[J ].電子設(shè)計(jì)應(yīng)用, 2003,7
[5] 劉崢嶸等編著,嵌入式Linux應(yīng)用開(kāi)發(fā)詳解[M].北京:機(jī)械工業(yè)出版社,2004. 7

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載。