基於AT91SAM9G20構建嵌入式Linux系統

 

     本文中使用的目標平臺AT91SAM9G20是Atmel公司使用ARM926EJ-S處理器內核開發的一塊SoC嵌入式微處理器,主頻達到400MHz,具有Atmel 先進的外設DMA 和分佈式存儲器架構,連同6層總線矩陣,可實現存儲器、外設和外部接口之間的多重數據同時傳送,而無需耗費CPU的時鐘週期。與引腳兼容的200 MHz AT91SAM9260相比,AT91SAM9G20提供多達4倍的高速緩存和片上 SRAM 內存,並具有增強的外接 NAND 閃存錯誤校正功能,以及更大的以太網 FIFO,能夠減少傳輸延遲。其外部總線接口(EBI)的時鐘頻率爲133 MHz,用於片外存儲器的高速數據傳送。這些特性使得開發人員可以將WindowsCE和Linux等操作系統移植到基於這塊微處理器的目標系統中。

       操作系統也是嵌入式系統的重要組成部分。當今的嵌入式操作系統各種各樣,有VxWorks、QNX、Palm OS,Windows CE、Linux, uClinux,ucos ii等,每種操作系統都有其與衆不同之處,本文移植的嵌入式操作系統爲Linux。廣泛開放源代碼的Linux應用已經被移植到嵌入式的運行環境中,可以任意剪裁和修改後將其移植入自己的硬件平臺上,因此使用Linux開發嵌入式操作系統,可以加快嵌入式系統的開發速度,縮短產品進入市場的時間。

本文的工作主要包括Boot loader實現,Linux內核移植、文件系統的實現三個部分。

搭建交叉開發環境

在移植操作系統之前,首先要在一臺裝有Linux的PC機上搭建好開發環境,例如我們的宿主機爲Ubuntu10.04,爲獲得所有操作權限,以root身份登錄宿主機Linux系統。在 usr/local/目錄下建立arm路徑,下載交叉編譯工具arm-linux-gcc-4.3.2.tgz,將之複製到文件夾/usr/local/arm/下,並將其解壓;最後需要修改環境變量,設置默認交叉編譯工具爲arm-linux-gcc-4.3.2。利用Linux下編輯工具(如vim)打開/root/.bashrc文件,在文件末尾添加如下代碼:

if

[ -d /usr/local/arm ] ;

then PATH=/usr/local/arm/4.3.2/bin:"${PATH}"

fi

到此交叉編譯工具搭建完畢,爲驗證交叉編譯工具是否搭建成功,可以在終端下輸入命令 arm-linux-gcc -v,搭建成功後會在終端下顯示arm-linux-gcc的版本。注意此處必須註銷用戶,重新登錄系統後設置纔會生效。

引導程序

系統上電之後,需要一段程序來進行初始化:關閉看門狗、改變系統時鐘、初始化存儲控制器、將更多的代碼複製到內存中等,這段程序被稱爲Boot loader。簡言之Boot loader就是在系統上電後開始執行,初始化硬件設備、準備好軟件環境、最後調用操作系統內核。Boot loader的實現非常依賴與具體的硬件,在嵌入式系統中硬件配置千差萬別,即使是相同的CPU,外設資源也不盡相同,因此需要根據特定的硬件進行移植。

Boot Loader包含兩種不同的操作模式:啓動加載模式和下載模式。上電後,Boot loader從板子上的某個固態存儲設備上將操作系統加載到RAM中運行,整個過程沒有用戶的介入,一般用於最終產品。下載模式下則在開發過程中使用,開發人員可以使用各種命令,通過串口或網絡等通信手段從宿主機下載文件(比如內核映像,文件系統映像),將它們直接放入內存或是燒入flash類固態存儲設備中。

爲了在AT91SAM9G20上實現嵌入式操作系統運行,AT91SAM9G20採用了三.級引導方式,其Boot Loader程序由三部分組成,即RomBoot、Bootstrap和U-Boot,三.級引導程序的流程如圖1所示。

 

基於AT91SAM9G20構建嵌入式Linux系統(轉載) - liruibo19830309 - liruibo19830309的博客
 
圖1:三.級引導程序的流程圖

第一級引導程序Romboot固化在AT9lSAM9G20內部,上電或復位後先運行這段引導代碼,其作用是將存儲於外部FLASH第二級引導程序Bootstrap加載到CPU內部的SRAM中執行。Bootstrap存儲在外部FLASH的前4KB空間,其功能包括初始化時鐘、SDRAM控制器以及DEBUG串口等硬件資源,並將第三 級引導程序U-Boot從FLASH加載到SDRAM執行。U-Boot將嵌入式Linux操作系統從FLASH引導和加載到SDRAM中,並將CPU的控制權交給Linux。

本次移植使用的U-boot的版本爲1.3.4,限於篇幅,本文不做詳細的介紹。

內核的裁剪編譯

1.準備工作

從Linux官網下載linux內核源碼linux-2.6.30.tar.bz2,並從Atmel官網下載at91sam9g20的補丁文件(2.6.30-at91.patch.gz 和2.6.30-at91-exp.3.tar.gz)。在宿主機Linux開發環境下,建立自己的工作目錄,例如工作目錄爲home/work/,將上述三個文件拷貝至工作目錄下,解壓Linux2.6.30,並將2.6.30-at91.patch.gz和2.6.30-at91-exp.3.tar.gz拷貝至Linux2.6.30根目錄下,同時解壓2.6.30-at91-exp.3.tar.gz。完成此部分工作如下圖2所示。

 

基於AT91SAM9G20構建嵌入式Linux系統(轉載) - liruibo19830309 - liruibo19830309的博客
 
圖2:準備工作完成
 

2.添加補丁文件

進入上述linux-2.6.30根目錄,執行如下兩條命令:

zcat 2.6.30-at91.patch.gz | patch -p1

for p in 2.6.30-at91-exp.3/*; do patch -p1 < $p ; done

執行成功之後,即將從ATMEL官網下載的針對at91sam9g20的補丁文件添加進linux-2.6.30內核中,包括驅動程序,內核配置文件等。

3.U-boot引導Linux內核啓動

a、機器碼的確定

通常,在u-boot和kernel中都會有一個機器碼(即:MACH_TYPE),只有這兩個機器碼一致時才能引導內核。首先,確定U-boot中的MACH_TYPE,在U-boot的include/asm-arm/mach-types.h文件中針對不同的CPU定義了非常多的MACH_TYPE,可以找到下面這個定義:

#define MACH_TYPE_AT91SAM9G20EK_2MMC 2288

其次,確定kernel中的MACH_TYPE。在Linux2.6.30的arch/arm/tools/mach-types文件中也針對不同的CPU定義了非常多的MACH_TYPE,也可以找到下面這個定義

at91sam9g20ek_2mmc MACH_AT91SAM9G20EK_2MMC AT91SAM9G20EK_2MMC 2288

只有這兩者定義一致,u-boot才能完成對內核的引導,否則就會出現mach的錯誤信息。

b、添加引導地址

位於內核平臺arm目錄kernel下的head.S文件是用匯編代碼完成的,它是內核最先執行的一個文件。這一段彙編代碼的主要作用,是檢查cpu id,architecture number,初始化頁表、cpu、bbs等操作,並跳到start_kernel函數。

找到ENTRY(stext),添加如下代碼:

ENTRY(stext)

mov r0, #0

mov r1, #0x8f0

ldr r2, =0x20000100

其中r1存放是是architectureID(2288十六進制爲0x8f0),r2存放 atags 指針。 Linux內核的啓動順序如圖3所示。

 

基於AT91SAM9G20構建嵌入式Linux系統(轉載) - liruibo19830309 - liruibo19830309的博客
 
圖3:Linux內核的啓動順序

4.配置和編譯

首先要配置編譯工具,打開Linux的根目錄下的Makefile文件,找到下面的代碼進行修改:

export KBUILD_BUILDHOST := $(SUBARCH)

ARCH ?= arm

CROSS_COMPILE ?= /usr/local/arm/4.3.2/bin/arm-linux-

制定平臺爲arm平臺,交叉編譯工具爲arm-linux-gcc-4.3.2;保存之後進入linux-2.6.30根目錄,執行以下命令:

#make distclean

#make clean

此步驟刪除一些以前編譯產生的一些中間文件、臨時文件,以避免編譯出錯。最後執行命令

#make at91sam9g20ek_2mmc_defconfig

#make uImage

即根據at91sam9g20配置內核,並編譯生成內核映像文件,其中make uImage是U-boot編譯生成的工具,在uboot的/tools目錄下尋找mkp_w_picpath文件,將其複製到系統/usr/local/bin目錄下,這樣就可以運行make uImage命令。編譯完成之後(大概需要十幾分鍾),便可以在arch/arm/boot/目錄下發現uImage文件,就是我們需要的內核映像文件,下載至工控板便可以運行。

5.修改和添加驅動程序

以上步驟生成的內核映像文件是按照Atmel官網的配置進行裁剪修改的,由於實際硬件配置的不同,就要針對具體的硬件設備修改相應的驅動程序,在Linux內核中增加驅動程序需要完成以下3項工作:

將編寫的源代碼複製到Linux內核源代碼的相應目錄中。在目錄的Kconfig文件中增加新源代碼對應項目的編譯配置選項。在目錄的Makefile文件中增加對新源代碼的編譯條件。

以添加nandflash驅動程序爲例進行說明。at91sam9g20工控板的存儲芯片芯片採用三星的K9F2G08U0A實現,針對at91sam9g20編寫此芯片驅動,例如驅動文件爲9g20_nandflash.c,將此文件添加至/linux2.6.30/driver/mtd/nand目錄下,並修改Kconfig和Makefile文件。其中Makefile文件添加

obj-$(CONFIG_MTD_NAND_ATMEL) += 9g20_nandflash.o

Kconfig文件中添加如下代碼:

config MTD_NAND_ATMEL

tristate "Support for SAM9G20 NAND Flash"

depends on ARCH_AT91

help

完成之後在linux2.6.30根目錄執行make menuconfig,選擇nandflash驅動程序。如下所示。

Device Drivers --->

<*> Memory Technology Device (MTD) support --->

<*> NAND Device Support --->

<*> Support for SAM9G20 NAND Flash

其中配置內核文件,選中要配置的選項,此時按下“Y”鍵,將此選項編譯進內核,按下“M”鍵,將此選項編譯成內核模塊,按下“N”鍵表示從內核中刪除此選項。

如需要添加分區信息,則在board-sam9g20ek-2slot-mmc.c文件中添加NAND閃存的分區表:

static struct mtd_partition __initdata ek_nand_partition[] = {

{

.name = "BootLoader",

.offset = 0,

.size = 0x00200000,

},//0分區

{

.name = "Linux Kernel",

.offset = 0x00200000,

.size = 0x00200000,

},//2M

{

.name = "Cramfs",

.offset = 0x00400000,

.size = 0x00A00000,

},//10M

{

.name = "FS",

.offset = 0x00E00000,

.size = 0x0F200000,

},

};

 

保存後,重新編譯內核,即可生成帶有nandflash驅動的內核映像文件。

按照上述分區表進行分區,nandflash的資源分佈如圖4所示,我們可以看到引導程序所說明的Bootloader在閃存中的存儲情況,Linux內核以及下文要闡述的文件系統在此工控板上的存儲情況。

 

基於AT91SAM9G20構建嵌入式Linux系統(轉載) - liruibo19830309 - liruibo19830309的博客
 
圖4:NAND閃存的資源分佈圖

文件系統的實現

選擇文件系統,要根據具體應用的需求,一般要考慮可靠性,健壯性和增強的需求。如果是像工控這樣的不需經常更新控制程序的應用來說,選擇CARAMFS這樣的只讀文件系統已經足夠了,而且它還可以帶來的另外一個好處就是CRAMFS的壓縮率高達50%,可以大大節省我們的存儲空間。但是如果是像涉及到數據採集這類需要保存數據的應用來說,只讀的文件系統就很難滿足應用系統的需求,我們可以選擇 JFFS 或者 YAFFS 這樣的可讀寫的文件系統。不過在實際應用中,需要考慮的因素還應該更多。根據不同文件系統的特點,結合本9g20工控板的應用場合,採用了cramfs+jffs2文件系統。

文件系統的製作步驟大致如下:

下載busybox進行編譯,生成Linux系統最常用的命令,這裏可以根據需求選擇常用的系統工具。本文件系統採用busybox-1.14.2,使用交叉編譯工具爲arm-linux-gcc-4.3.2,這裏需要注意的是編譯busybox和編譯linux內核的交叉編譯工具最好使用同一版本的編譯工具。

建立文件系統所需要的文件,如下所示:

mkdir /9g20_rootfs

cd /9g20_rootfs

mkdir bin dev etc home lib mnt proc sbin sys tmp usr var

同時將busybox生成的bin和sbin目錄拷貝至9g20_rootfs目錄下,並將編譯busybox所需的動態連接庫文件,拷貝至9g20_rootfs /lib目錄下。

編寫必須的配置文件下,如etc目錄下的rcS、inittab、fstab等等文件,並注意文件的執行權限。

下載cramfs製作工具cramfs-1.1.tar,編譯後將生成的可執行程序mkcramf拷貝至/usr/bin目錄下,即可執行mkcramfs 9g20_rootfs 9g20.cramfs,生成的9g20.cramfs文件就是所需的文件系統。

添加jffs2分區,在/etc/init.d/rcS文件中添加如下命令:

#mount -t jffs2 /dev/mtdblock3 /home

即將mtdblock3以jffs2文件系統方式掛載爲home目錄,這樣/home目錄是可讀可寫,既解決了cramfs只讀的限制,同時系統文件是隻讀,用戶程序和數據可讀可寫,有利於保護系統文件,又減少了文件系統的體積,特別適用於嵌入式系統。

將生成的內核映像和文件系統映像下載至工控板後,可以看到移植完成後,系統正常啓動,經測試移植後的系統正常穩定運行。

本文小結

本文系統地闡述了以AT91SAM9G20的ARM9處理器爲硬件平臺的嵌入式Linux系統的構建過程,並以nandflash驅動爲例闡述了Linux下驅動程序的編寫步驟,最後給出了文件系統的解決方案。構建嵌入式Linux系統是個複雜的課題,需要對Linux操作系統內核有一定的瞭解,特別是Linux的啓動過程;驅動程序的編寫既要熟悉硬件知識,又要熟悉Linux內核數據結構;而且系統的實時性、安全性、穩定性、精簡化等方面都需要開發人員在設計中進一步考慮。經過系統測試,本文移植的Linux系統運行穩定,AT91SAM9G20的良好性能得以充分應用,爲後續應用程序的開發提供了堅實的基礎。

作者:作者:袁莎莎,蔣健,陳煒


參考文獻

[1] Atmel Corporation.AT91SAM9G20 Preliminary,2009.

[2] [美]博韋,西斯特,陳莉君,張瓊聲,張宏偉譯.深入理解LINUX內核第三版[M].北京:中國電力出版社,2007.09.

[3] 韋東山.嵌入式Linux應用開發完全手冊[M].北京:人民郵電出版社,2008.08.

[4] 黃深喜,樊曉平,劉利方,楊勝躍.基於AT91SAM926X的嵌入式LINUX引導程序設計[J].微計算機應用,2009(30).

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章