摘 要:采用U-Boot 1.1.2構(gòu)建嵌入式系統(tǒng)的引導(dǎo)加載程序。在對(duì)U-Boot的啟動(dòng)工作機(jī)理和源碼主要函數(shù)功能進(jìn)行了簡(jiǎn)略分析后,針對(duì)基于AT91RM9200的目標(biāo)板對(duì)U-Boot作了具體的修改和移植,并講述如何設(shè)置環(huán)境變量,從而引導(dǎo)Linux內(nèi)核啟動(dòng)。應(yīng)用結(jié)果表明,移植后的U-Boot在目標(biāo)板上運(yùn)行良好,可成功引導(dǎo)Linux內(nèi)核。
關(guān)鍵詞:U-Boot;移植;內(nèi)核;AT91RM9200;嵌入式系統(tǒng)
中圖分類號(hào):TN99 文獻(xiàn)標(biāo)識(shí)碼:B
文章編號(hào):1004373X(2008)0515703
Porting and Start Analysis of U-Boot Based on AT91RM9200 Board
ZHOU Qingsong,SHI Xiaojun
(Deptartment of Electronic Science and Engineering,Southeast University,Nanjing,210018,China)
Abstract:A bootloader for embedded system is developed with the U-Boot 1.1.2.After analyzing the booting mechanism of U-Boot and the function of sound code,the modification and porting in an embedded system board based on AT91RM9200 are done in detail,with environment variable settings and consequent Linux kernel booting process.The application shows that U-Boot runs well and can lead Linux kernel successfully.
Keywords:U-Boot;porting;kernel;AT91RM9200;embedded system
1 引 言
U-Boot(Universal Boot Loader)是遵循GPL條款的開放源碼項(xiàng)目,他支持多種體系結(jié)構(gòu)的上百種開發(fā)板,并且支持多種嵌入式操作系統(tǒng)內(nèi)核,具有較高的可靠性和穩(wěn)定性,已經(jīng)成為功能最多、靈活性最強(qiáng)并且開發(fā)最積極的開放源碼BootLoader。作為通用的BootLoader,U-Boot可以方便地移植到其他硬件平臺(tái)上。
本文基于AT91RM9200的嵌入式目標(biāo)板和U-Boot 1.1.2源碼資源,分析了U-Boot的啟動(dòng)過(guò)程,介紹了U-Boot的移植方法和具體操作,最后講述如何引導(dǎo)內(nèi)核啟動(dòng)。
2 U-Boot啟動(dòng)分析
在具體移植之前,先來(lái)了解一下U-Boot啟動(dòng)過(guò)程。U-Boot啟動(dòng)過(guò)程可以分成3個(gè)階段。
(1) 在FLASH中運(yùn)行匯編程序,進(jìn)行基本硬件初始化,并將FLASH中的啟動(dòng)代碼復(fù)制到SDRAM中,同時(shí)創(chuàng)造環(huán)境準(zhǔn)備運(yùn)行C程序。
匯編程序start.s是U-Boot啟動(dòng)后執(zhí)行的第一個(gè)程序,他位于CPU/AT91RM9200中,鏈接腳本Board/AT91RM920DK/U-Boot.lds決定U-Boot的入口函數(shù)位于該程序中,上電后,處理器首先執(zhí)行該程序,具體工作流程如圖1所示。
(2) 跳轉(zhuǎn)到SDRAM中執(zhí)行,對(duì)硬件進(jìn)行初始化,并向顯示終端輸出啟動(dòng)信息。
start[CD#*2]armboot是U-Boot執(zhí)行的第一個(gè)C語(yǔ)言函數(shù),他位于lib[CD#*2]arm/board.c中,主要完成系統(tǒng)初始化工作,進(jìn)入主循環(huán),處理用戶輸入的命令。 具體工作流程如圖2所示。

全局變量結(jié)構(gòu)體gd用來(lái)保存開發(fā)板信息、終端存在標(biāo)志位、環(huán)境變量結(jié)構(gòu)體起始地址、環(huán)境變量校驗(yàn)標(biāo)志位、frame buffer 基地址等。他是指向gd[CD#*2]t結(jié)構(gòu)體的指針,gd[CD#*2]t結(jié)構(gòu)體定義在include\\\\asm-asm\\\\global[CD#*2]data.h中。
硬件初始化中執(zhí)行函數(shù)及各函數(shù)作用如下:
board[CD#*2]init:基本的板級(jí)相關(guān)配置,主要包括:設(shè)置處理器類型和啟動(dòng)參數(shù)地址;
interrupt[CD#*2]init:中斷處理初始化,主要對(duì)TC控制器作設(shè)置。
env[CD#*2]init:設(shè)置環(huán)境變量,初始化環(huán)境;
init[CD#*2]baudrate:指定串口的波特率;
serial[CD#*2]init:串口初始化設(shè)置;選擇通訊端口,設(shè)置串口波特率和工作方式;
console[CD#*2]init[CD#*2]f:設(shè)置gd->have[CD#*2]console=1,表示可以使用串口通訊控制臺(tái);
display[CD#*2]banner:在控制臺(tái)輸出 U-Boot信息;
dram[CD#*2]init:設(shè)置SDRAM的起始地址和大??;
display[CD#*2]dram[CD#*2]config:在控制臺(tái)輸出 SDRAM信息;
FLASH[CD#*2]init:設(shè)置FLASH芯片ID號(hào)、每個(gè)扇區(qū)起始地址等信息,將信息送到相應(yīng)的結(jié)構(gòu)體中;對(duì)FLASH中U-Boot和環(huán)境變量存儲(chǔ)扇區(qū)做軟件寫保護(hù);
display[CD#*2]FLASH[CD#*2]config (size):在上位機(jī)終端輸出FLASH大小。
(3) 將內(nèi)核映像和根文件系統(tǒng)映像從FLASH拷貝到SDRAM中,為內(nèi)核設(shè)置啟動(dòng)參數(shù),進(jìn)入內(nèi)核的入口函數(shù)。
U-Boot作為BootLoader,具備多種引導(dǎo)內(nèi)核啟動(dòng)的方式,常用bootm命令引導(dǎo)內(nèi)核映像啟動(dòng)。使用bootm命令時(shí),需要首先使用U-Boot自帶的mkimage命令,將內(nèi)核映像文件轉(zhuǎn)換成U-Boot格式映像。即在內(nèi)核的前頭加上64 B的信息幀頭,供建立tag之用。
bootm命令調(diào)用do[CD#*2]bootm函數(shù),這個(gè)函數(shù)專門用來(lái)引導(dǎo)各種操作系統(tǒng)映像,可以支持引導(dǎo)Linux,vxWorks,QNX等操作系統(tǒng)。具體完成的工作有:保存內(nèi)核引導(dǎo)地址;分析內(nèi)核幀頭;復(fù)制內(nèi)核映像到SDRAM中;調(diào)用do[CD#*2]bootm[CD#*2]linux()函數(shù)。
do[CD#*2]bootm[CD#*2]linux()函數(shù)是專門引導(dǎo)Linux映像的函數(shù),他還可以處理ramdisk文件系統(tǒng)的映像。具體完成的工作有:
(1) 檢查是否有根文件系統(tǒng)映像文件,這里只用bootm命令引導(dǎo)內(nèi)核映像;
(2) 將要傳遞給Linux的參數(shù)存放到標(biāo)記列表中,內(nèi)核將會(huì)從此處接收參數(shù),完成參數(shù)傳遞;
(3) 調(diào)用 Linux內(nèi)核,系統(tǒng)采用下列代碼來(lái)進(jìn)入內(nèi)核函數(shù):
第一行代碼將theKernel函數(shù)指向內(nèi)核首地址處;第二行代碼調(diào)用theKernel()函數(shù),并通過(guò)r0,r1,r2將機(jī)器編號(hào)和參數(shù)鏈表物理地址傳遞給內(nèi)核。
3 嵌入式目標(biāo)板介紹
本目標(biāo)板以AT91RM9200作為微處理器,板上存儲(chǔ)系統(tǒng)包括NOR FLASH,NAND FLASH,SDRAM等;外圍支持設(shè)備有JTAG、串口、USB接口、 網(wǎng)絡(luò)接口、SD Card 接口及顯示接口等。目標(biāo)板硬件架構(gòu)如圖3所示,主要硬件資源如表1所示。

4 U-Boot源碼修改與編譯
根據(jù)目標(biāo)板的配置,主要考慮修改以下U-Boot源碼文件:
(1) include/configs/AT91RM9200dk.h:該頭文件包含了SDRAM的一些設(shè)置和定義,主要修改內(nèi)容包括:定義CONFIG[CD#*2]BOOTBINFUNC宏變量;修改SDRAM大??;修改FLASH大小和扇區(qū)數(shù)。
(2) board/AT91RM9200dk/FLASH.c:該程序完成的功能包括FLASH初始化、打印FLASH信息、FLAH擦除和FLASH寫入等操作??稍趨⒖家延蠪LASH驅(qū)動(dòng)的基礎(chǔ)上,結(jié)合目標(biāo)板FLASH數(shù)據(jù)手冊(cè),進(jìn)行適當(dāng)修改。
(3) include/FLASH.h:FLASH程序頭文件,結(jié)合目標(biāo)板修改FLASH型號(hào)和ID定義。
U-Boot的源碼通過(guò)GCC和Makefile組織編譯。頂層目錄下的Makefile設(shè)置開發(fā)板的定義,遞歸地調(diào)用各級(jí)子目錄下的Makefile,把編譯過(guò)的程序鏈接成U-Boot映像。
這里上位機(jī)操作系統(tǒng)采用Redhat 9.0,交叉工具鏈采用cross-2.95.3。GCC安裝路徑為/usr/loacal/arm/2.95.3,在環(huán)境變量PATH中添加相應(yīng)路徑,就可以直接使用arm-linux-gcc命令。
編譯U-Boot分兩步:第一步配置,執(zhí)行命令: make at91rm9200dk[CD#*2]config;第二步編譯,執(zhí)行命令: make。編譯完成,生成3個(gè)映像文件system.map,U-Boot,U-Boot.bin,和1個(gè)符號(hào)表system.map,一般U-Boot.bin最為常用,直接按照二進(jìn)制格式下載。
使用FLASH燒寫程序?qū)-Boot.bin燒進(jìn)NOR FLASH中,目標(biāo)板重新上電復(fù)位后,U-Boot啟動(dòng)成功,在超級(jí)終端會(huì)顯示如下啟動(dòng)信息:
出現(xiàn)Warning的原因是還未設(shè)置環(huán)境變量,設(shè)置環(huán)境變量后執(zhí)行saveenv命令即可去掉Warning。
5 引導(dǎo)內(nèi)核
U-Boot的最終目的是引導(dǎo)內(nèi)核啟動(dòng)。上述僅僅啟動(dòng)了U-Boot,要引導(dǎo)內(nèi)核啟動(dòng)還需要設(shè)置環(huán)境變量、下載內(nèi)核和根文件系統(tǒng)映像、執(zhí)行引導(dǎo)內(nèi)核啟動(dòng)命令。假設(shè)內(nèi)核映像文件為zImage,根文件系統(tǒng)映像文件為myramdisk.gz(生成方法略)。具體方法如下:
(1) 啟動(dòng)目標(biāo)機(jī),在U-Boot中進(jìn)行網(wǎng)絡(luò)參數(shù)等環(huán)境變量設(shè)置:
這里網(wǎng)絡(luò)環(huán)境變量設(shè)置的目的是為了能夠使用TFTP協(xié)議;bootargs用來(lái)定義傳遞給Linux內(nèi)核的命令行參數(shù);Bootcmd定義自動(dòng)啟動(dòng)時(shí)執(zhí)行的命令;bootm 10100000表示從0x10100000處引導(dǎo)內(nèi)核程序。[LL]
(2) 給內(nèi)核映像加幀頭
在上位機(jī)Linux環(huán)境下,將U-Boot\\\ools\\\\mkimage.exe COPY 到\\\\bin目錄下,輸入如下命令:
[root@localhost tftpboot]#mkimage-n ′linux-2.6.19′-A arm -O linux-T kernel-C none-a 0x20008000-e 0x20008000-d zImage zImage.img
這里zImage為原始內(nèi)核映像文件名;zImage.img為生成的加過(guò)幀頭的內(nèi)核映像名。
(3) 加載內(nèi)核和根文件系統(tǒng)映像到FLASH中
加載zImage.img到0x10100000,加載myramdisk.gz到0x10300000。
至此,我們將UBOOT、內(nèi)核、根文件系統(tǒng)都下載到FLASH中了,并且設(shè)置了環(huán)境變量。重啟目標(biāo)板,等待延時(shí)時(shí)間結(jié)束自動(dòng)進(jìn)入本地裝載模式,即可引導(dǎo)內(nèi)核啟動(dòng)。
上面講述的是將內(nèi)核和根文件系統(tǒng)固化到FLASH中的情況,即使用本地加載模式,當(dāng)以嵌入式產(chǎn)品發(fā)布時(shí),BootLoader必須工作在這種模式下。但實(shí)際在初期調(diào)試的時(shí)候,可以在下載操作模式下直接用TFTP命令將這些映像文件下載到SDRAM中,然后用bootm命令從SDRAM中引導(dǎo)。此時(shí)在給內(nèi)核映像加幀頭的時(shí)候要注意,bootm xxxx 指定的地址xxxx是否與mkImage命令處的-a指定的加載地址相同。如果不同,mkImage命令的寫法和上面介紹的一致;如果相同,在使用mkImage命令時(shí),-e參數(shù)后的入口地址要比-a參數(shù)后的存儲(chǔ)地址推后64 B。
6 結(jié) 語(yǔ)
U-Boot是一個(gè)功能強(qiáng)大的BootLoader開源軟件,他支持上百種開發(fā)板和多種嵌入式操作系統(tǒng),可方便地移植到各種硬件平臺(tái)上。目前,筆者移植的U-Boot已成功運(yùn)行在目標(biāo)板上,并在此基礎(chǔ)上成功地加載了Linux內(nèi)核和根文件系統(tǒng),為后續(xù)的驅(qū)動(dòng)和應(yīng)用開發(fā)奠定了基礎(chǔ)。對(duì)于不同的CPU和開發(fā)板,U-Boot的啟動(dòng)原理和移植步驟大致相同。希望本文能對(duì)學(xué)習(xí)U-Boot的朋友有所幫助。
參考文獻(xiàn)
[1]張進(jìn),姜威.U-Boot的啟動(dòng)流程及移植[J].國(guó)外電子元器件,2005(5):11-14.
[2]孫紀(jì)坤,張小泉.嵌入式Linux系統(tǒng)開發(fā)技術(shù)詳解——基于ARM[M].北京:人民郵電出版社,2006.
[3]焦玉全,黃鄉(xiāng)生,鮑玉軍.U-Boot在S3C2410上的移植[J].電子設(shè)計(jì)應(yīng)用,2006(3):126-128.
[4]Karim Yagbmour.構(gòu)建嵌入式Linux系統(tǒng)[M].北京:中國(guó)電力出版社,2004.
作者簡(jiǎn)介
周慶松 男,1980年出生,江蘇省儀征市人,碩士研究生。主要從事嵌入式系統(tǒng)的研究和應(yīng)用。
史小軍 男,1952年出生,教授,碩士生導(dǎo)師。