李宇飛 嵇啟春 劉浩洋
(西安建筑科技大學(xué)信息與控制工程學(xué)院, 陜西 西安 710055)
摘要: 引導(dǎo)加載程序是嵌入式系統(tǒng)開發(fā)的重要環(huán)節(jié),它使得操作系統(tǒng)和硬件平臺聯(lián)系起來,對嵌入式系統(tǒng)的后繼軟件開發(fā)十分重要。為此,介紹了當前嵌入式開發(fā)中功能強大、穩(wěn)定可靠的引導(dǎo)加載程序U-Boot的目錄結(jié)構(gòu)、啟動流程及其移植的思路和引導(dǎo)內(nèi)核的方法;給出了移植Uboot-2010-06到ARM微處理器S3C2440上所需操作環(huán)境的搭建,具體代碼的修改,具體參數(shù)的設(shè)置,以及所需的操作命令等要點。最后將編譯生成的U-Boot.bin文件下載到ARM微處理器S3C2440上,測試顯示,U-Boot可以達到設(shè)計的功能要求并能夠穩(wěn)定運行,而且通過對其進行正確的配置可以引導(dǎo)內(nèi)核。
關(guān)鍵詞: 嵌入式系統(tǒng); Bootloader; U-Boot; S3C2440; Linux
中圖分類號:TP319文獻標志碼:A 文章編號:1006-8228(2012)11-04-04
Analysis of transplant process of U-boot to platform based on mini2440
Li Yufei, Ji Qichun, Liu Haoyang
(Xi'an University of Architecture and Technology, Xi'an, Shanxi 710055, China)
Abstract: Bootloader (boot loader) plays an important part in combining the operating system with hardware platform, and also is crucial for embedded system of software development. Directory structure, workflow, a porting thought and a booting kernel method of a powerful, stable U-Boot program in the development of the current embedded systems are proposed. The problems in transplanting uboot-2010-06 to S3C2440 are discussed, including particularly the environment establishment, the specific changes to the file, the specific settings to parameter and the demand of operation command. Finally the compiled U-Boot.bin will be downloaded to ARM microprocessor. The result shows that U-boot can reach the project request, operate steadily and boot the kernel successfully through the proper configuration.
Key words: embedded system; Bootloader; U-Boot; S3C2440; Linux
0 引言
在嵌入式軟件開發(fā)中,嵌入式Linux系統(tǒng)通常包括引導(dǎo)加載程序、Linux內(nèi)核、文件系統(tǒng)和用戶應(yīng)用程序四部分[1]。引導(dǎo)加載程序包括固化在固件(firm-ware)中的boot代碼(可選)和Bootloder。簡言之,Bootloader就是在操作系統(tǒng)內(nèi)核運行之前運行的一段小程序,它在系統(tǒng)上電時開始執(zhí)行,初始化硬件設(shè)備、準備好軟件環(huán)境,最后調(diào)用操作系統(tǒng)內(nèi)核[2]。由于Bootloader的實現(xiàn)非常依賴于具體的硬件,即使是基于同一種處理器構(gòu)建的不同開發(fā)板,具有相同的CPU,它的外設(shè)(比如FLASH)也可能不同,所以不可能有一個通用的Bootloader來支持所有的CPU,而可能的是,讓一個Bootloader代碼支持多種不同的構(gòu)架和操作系統(tǒng),并讓它有很好的可移植性。U-Boot就是支持多平臺多操作系統(tǒng)的一個杰出代表,移植U-Boot是為下一步引導(dǎo)內(nèi)核和文件系統(tǒng)做準備,但U-Boot移植完成后由于開發(fā)途徑的不同還需要做些設(shè)置才能引導(dǎo)內(nèi)核和文件系統(tǒng)。本文重點是針對最小硬件系統(tǒng)的Bootloader移植的研究。
1 U-boot的概述及啟動過程
1.1 U-Boot簡介
U-Boot (universal boot loader)是德國DENX軟件工程中心開發(fā)的一款遵循GPL條款的開放源碼軟件產(chǎn)品,其對現(xiàn)在市場上主流的操作系統(tǒng),CPU都能提供良好的支持,除了支持Linux系統(tǒng)的引導(dǎo)外,還支持NetBSD、VxWorkd、LynxOS等嵌入式操作系統(tǒng),并且支持ARM、PowerPC、NIOS、XScale等處理器。U-Boot的程序框架清晰,功能強大,具有較高的穩(wěn)定性和可靠性,豐富的設(shè)備驅(qū)動源碼,移植方便。這些特點是它被選擇移植到mini2440開發(fā)板上的原因。
1.2 U-Boot的源碼結(jié)構(gòu)
本文主要是針對U-Boot-2010-06的分析與移植。其源碼可以在官方網(wǎng)站下載,解壓后可以得到它的全部代碼。
U-Boot-2010-06根目錄下共有29個子目錄,根據(jù)其作用可以分為開發(fā)板類型相關(guān)、平臺相關(guān)、通用的函數(shù)、通用的設(shè)備驅(qū)動、文檔示例程序、工具等幾類。表1給出了U-Boot的主要目錄結(jié)構(gòu)[3]。
1.3 U-Boot的啟動流程
由于本次移植采用的硬件平臺是友善之臂的mini2440開發(fā)板,而U-boot-2010-06沒有提供基于S3C2440芯片的開發(fā)板支持,我們可以通過修改與其結(jié)構(gòu)相近的smdk2410的配置文件和相關(guān)源代碼,去實現(xiàn)U-Boot對s3c2440的支持[4]。Bootloader的啟動過程可以分為單階段和多階段。從固態(tài)存儲設(shè)備上啟動的Bootloader是兩個階段的啟動過程。第一階段用到的文件為cpu/xxx/start.S和board/xxx/lowlevel_init.S文件中,這兩個文件用匯編語言寫成;第二階段的代碼通常放在lib_xxx/board.c文件中,用C語言寫成,主要任務(wù)是初始化本階段用到的硬件、檢測系統(tǒng)內(nèi)存映射、將內(nèi)核鏡像和根文件系統(tǒng)鏡像從Flash上讀到RAM空間中并為內(nèi)核設(shè)置啟動參數(shù)最終啟動內(nèi)核。
表1U-Boot主要目錄說明
[[U-Boot目錄\&功能說明\&board\&一些已經(jīng)支持的開發(fā)板相關(guān)文件\&common\&與處理器體系結(jié)構(gòu)無關(guān)的通用代碼\&cpu\&與處理器相關(guān)的文件\&disk\&Disk驅(qū)動分區(qū)相關(guān)信息代碼\&doc\&U-Boot的說明文檔\&drivers\&通用設(shè)備驅(qū)動程序,如:網(wǎng)卡、FLASH、串口、USB總線等\&fs\&支持文件系統(tǒng)的文件,如:cramfs、fat、fdos、jffs2等\&include\&U-Boot頭文件,還有各硬件平臺的匯編文件,系統(tǒng)配置文件\&Lib_xxx\&處理器體系結(jié)構(gòu)相關(guān)文件,如:lib_arm包含的是ARM體系結(jié)構(gòu)\&net \&與網(wǎng)絡(luò)功能相關(guān)的文件,如:bootp 、nfs、tftp等\&post\&上電自檢文件目錄\&tools\&用于創(chuàng)建U-Boot、S-Record和Bin鏡像文件的工具\&]]
[系統(tǒng)復(fù)位轉(zhuǎn)入U-BOOT
的stage1入口點][設(shè)置異常向量][設(shè)置CPU的時鐘、速度、
頻率及終端控制寄存][初始化內(nèi)存控制器][拷貝U-BOOT的stage2到代碼到RAM空間][設(shè)置堆棧、初始化數(shù)據(jù)段][本階段硬件設(shè)備初始化] [Stage1部分][跳轉(zhuǎn)到stage2的
C入口點][初始化FLASH設(shè)備][初始化NAND、顯示、
網(wǎng)絡(luò)等設(shè)備][初始化系統(tǒng)內(nèi)存][將kernel和根文件系統(tǒng)映射從FLASH讀到ARM中][設(shè)定內(nèi)核啟動參數(shù)和調(diào)用內(nèi)核][本階段硬件設(shè)備初始化] [Stage2部分]
圖1U-Boot的啟動流程圖
2 U-Boot的移植
在移植U-Boot之前首先要建立開發(fā)環(huán)境,然后根據(jù)具體的應(yīng)用平臺的要求生成相應(yīng)的U-Boot.bin二進制文件,再將U-Boot.bin下載到目標板上,本文采用的是友善之臂的mini2440開發(fā)板,此開發(fā)板采用405MHZ的ARM920T內(nèi)核的處理器S3C2440,下面是具體的移植過程。
2.1 移植環(huán)境
2.1.1 所需要的軟件環(huán)境
軟件環(huán)境為:Vm-ware6.0、Ubuntu/Redhat、TFTP Server、J-Link、Samba服務(wù)器、arm-linux-gcc-4.3.2.tgz、U-Boot-2010.
06.tar.gz2等。
2.1.2 Windows所需開發(fā)環(huán)境
⑴ 安裝TFTP Server,此軟件用于開發(fā)板和Windows的交互,通過它可以把編譯好的U-Boot的二進制文件和內(nèi)核二進制文件燒錄到開發(fā)板上。
⑵ 使用超級終端通過串口顯示U-Boot的運作信息。
⑶ 安裝J-Link,此軟件的作用是把生成U-Boot.bin燒寫到目標板上。
⑷ 安裝Vm-ware6.0用于安裝Linux操作系統(tǒng)。
2.1.3 Linux所需開發(fā)環(huán)境
⑴ 建立Linux和Windows的交互平臺Samba服務(wù)。使得Linux和Windows之間可以通過一個共享目錄互相傳送文件。
⑵ 交叉編譯環(huán)境的搭建。將arm-linux-gcc-4.3.2.tgz通過Samba服務(wù)器傳送到Linux內(nèi),然后解壓,輸入命令:
#tar -xvfarm-Linux-gcc-4.3.2.tgz -C /
運行成功后會在usr/local/arm下生成目錄4.3.2。在根目錄下輸入命令:
#gedit /etc/environment
修改environment,在PATH中添加“/usr/local/arm/4.3.2/”,指定arm-linux-gcc編譯器的位置。添加完后保存退出,在根目錄鍵入命令:#su或者重新啟動Linux操作系統(tǒng),讓新增加的配置生效。
⑶ 解壓U-Boot-2010.06.tar.gz2。方法和解壓arm-linux-
gcc-4.3.2.tgz類似。
2.2 移植文件操作
移植U-Boot除了依賴CPU的體系結(jié)構(gòu)外,還依賴于具體的嵌入式板級設(shè)備的配置,只需選擇與自己板子最為相近的作為基礎(chǔ)。與CPU相關(guān)的文件位于U-Boot根目錄下CPU/arm920t目錄及子目錄S3C24x0中。與Board相關(guān)的文件位于U-Boot根目錄下的board/sbc2410x目錄下。該版本U-Boot并不支持本文使用的ARM微處理器S3C2440,但是對于同一個系列的另一款微處理器S3C2410卻有很完善的支持。兩款芯片使用相同的ARM核,片內(nèi)集成的功能以及寄存器的使用都很接近,所以U-Boot的移植工作在S3C2410和對應(yīng)的開發(fā)板SMDK2410的基礎(chǔ)上展開;并且隨著U-Boot版本的不斷升級許多目錄的內(nèi)容做了很多改動,例如U-Boot-2010-06和以前的版本就有變化,它的/cpu/arm920t下的很多內(nèi)容移放到了drivers目錄下,因此/drivers目錄下也需要修改,對此就不作詳細介紹,在此我們重點介紹移植的思路[5]。
⑴ 進入u-boot的根目錄,并修改Makefile文件。
修改Makefile的命令如下:
$ cd u-boot-2010.06/
$ gedit Makefile
首先搜索CROSS_COMPILE,將CROSS_COMPILE=?改為交叉編譯工具鏈CROSS_COMPILE ?= arm-linux-,然后搜索smdk2410,并仿照它建立自己開發(fā)板的配置選項,在smdk2410_config: unconfig @$(MKCONFIG) $(@:_config=) arm arm920t s3c2410NULL s3c24x0下添加mini2440_config: unconfig @$(MKCONFIG) $(@:_config=) arm arm920tmini2440 jason s3c24x0然后保存。
說明:
arm:CPU的架構(gòu)(ARCH)。
arm920t:CPU的類型。
mini2440:對應(yīng)在board目錄下建立新的開發(fā)板項目的目錄。
jason:新開發(fā)板項目目錄的上級目錄,如直接在board下建立新的開發(fā)板項目的目錄,則這里就為NULL。
s3c24x0:CPU型號。
注意:編譯選項格式的第二行在@前面要用Tab鍵開始,否則編譯會出錯。
⑵ 建立mini2440開發(fā)板的板子目錄文件。
① 復(fù)制smdk2410的板子目錄文件為mini2440,命令如下:
$ mkdir -p board/jason
$ cd board/jason/
$ cp -rf ../samsung/smdk2410/ mini2440
② 重命名smdk2410.c為mini2440.c并修改對應(yīng)的Makefile文件:
$ mv smdk2410.c mini2440.c
COBJS :=mini2440.o flash.o
SOBJS :=lowlevel_init.o
⑶ 在根目錄下定位到include/configs,建立mini2440開發(fā)板的配置頭文件。
修改頭文件smdk2410.h。該文件的作用是對CPU內(nèi)部寄存器相對位置安排和命名寄存器的名稱。將smdk2410.h復(fù)制并粘貼到當前目錄下,將其重命名成mini2440.h,命令如下:
$ cp include/configs/smdk2410.h include/configs/mini2440.h
⑷ 修改開發(fā)板的終端中命令行提示符。
用gedit打開include/configs/mini2440.h頭文件,定位到117行,其中的“SMDK2410#”就是開發(fā)板在終端顯示的提示符,現(xiàn)在將其改為“[u-boot@MINI2440]#,如下所示:
#define CONFIG_SYS_PROMPT “[u-boot@MINI2440]#”
/*Monitor Command Prompt */
⑸ 注釋掉不需要的LED代碼。
① $ gedit arch/arm/cpu/arm920t/start.S
下面這兩行是AT91RM9200DK開發(fā)板的LED初始化,注釋掉。
// bl coloured_LED_init
// bl red_LED_on
② $ gedit arch/arm/lib/board.c
刪除不需要的指示進度LED功能。
#if 0
/************************************************************************/
* Coloured LED functionality
……
void blue_LED_off(void)__attribute__((weak,alias("__blue_LED_off")));
#endif
⑹ 在include/configs/mini2440.h頭文件中添加宏定義如下:
#define CONFIG_S3C2440 1 /* specifically a SAMSUNG
S3C2440 SoC */
#define CONFIG_MINI2440 1 /* FriendlyARM Mini2440 */
⑺ 修改lowlevel_init.S 文件。
注:lowlevel_init.S文件是開發(fā)板相關(guān)的,這表示如果外接的設(shè)備不一樣,可以修改lowlevel_init.S文件中的相關(guān)宏。
部分修改代碼如下:
#if defined(CONFIG_S3C2440)
#define Trp 0x2 /* 4clk */
#define REFCNT 1012
#else
#define Trp 0x0 /* 2clk */
#define REFCNT 1113
……
⑻ 增加對S3C2440一些寄存器的支持,添加中斷禁止部分和時鐘設(shè)置部分。
① 修改cpu/arm920t中的start.S文件,U-Boot的階段1代碼通常放在此文件中。
中斷禁止部分添加代碼如下:
# if defined(CONFIG_S3C2440) //添加s3c2440的中斷禁止部分
ldr r1, =0x7fff //根據(jù)2440芯片手冊,INTSUBMSK寄存器有15位可用
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
由于u-boot-2010-06并不支持S3C2440,所以要添加s3c2440的時鐘部分使其工作在405MHz:
# if defined(CONFIG_S3C2440) //添加s3c2440的時鐘部分
#define MPLLCON 0x4C000004 //系統(tǒng)主頻配置寄存器基地址
#define UPLLCON 0x4C000008 //USB時鐘頻率配置寄存器基地址
ldr r0, =CLKDIVN //設(shè)置分頻系數(shù)FCLK:HCLK:PCLK=1:4:8
mov r1, #5
str r1, [r0]
ldr r0, =MPLLCON //設(shè)置系統(tǒng)主頻為405MHz
ldr r1, =0x7F021 //這個值參考芯片手冊“PLL VALUE SELECTION
TABLE”部分
str r1, [r0]
ldr r0,=UPLLCON //設(shè)置USB時鐘頻率為48MHz
ldr r1,=0x38022 //這個值參考芯片手冊“PLL VALUE SELECTION
TABLE”部分
str r1,[r0]
# else
……
② 修改與Board相關(guān)的文件mini2440.c,該文件主要完成對GPIO和PLL的配置。
修改代碼如下:
#define FCLK_SPEED 2 //設(shè)置默認等于2,即下面代碼部分有效
#elif FCLK_SPEED==2/* Fout=405MHz */
#define M_MDIV 0x7F //這三個值根據(jù)S3C2440芯片手冊“PLL
VALUE SELECTION TABLE”部分進行設(shè)置
#define M_PDIV 0x2
#define M_SDIV 0x1
#define USB_CLOCK 2//設(shè)置默認等于2,即下面代碼部分有效
#elif USB_CLOCK==2/* Fout=48MHz */
#define U_M_MDIV 0x38//這三個值根據(jù)S3C2440芯片手冊
“PLL VALUE SELECTION TABLE”部分進行設(shè)置
#define U_M_PDIV 0x2
#define U_M_SDIV 0x2
③ 修改cup/arm920t/s3c24x0/speed.c文件,根據(jù)設(shè)置的分頻系數(shù)FCLK:HCLK:PCLK=1:4:8修改獲取時鐘頻率的函數(shù)。由于s3c2410和s3c2440的MPLL、UPLL計算公式不一樣,所以修改get_PLLCLK和函數(shù)加入以下代碼:
#if defined(CONFIG_S3C2440)
if(pllreg == MPLL)
{ //參考S3C2440芯片手冊上的公式:PLL=(2*m*Fin)/(p*2s)
return((CONFIG_SYS_CLK_FREQ*m*2)/(p<
}
#endif
……
#if defined(CONFIG_S3C2440)
return(get_FCLK()/4);
#endif
⑼ 借用S3C2410的代碼修改s3c24x0_cpu.h、s3c24x0.h、timer.c。
① 修改s3c24x0_cpu.h
在這個文件中添加對S3C2440芯片的支持。例如:
將defined (CONFIG_S3C2410)改成defined (CONFIG_S3C2410)||(defined CONFIG_S3C2440)。
② 修改頭文件s3c24x0.h
該文件的作用是對CPU內(nèi)部寄存器相對位置安排和命名寄存器的名稱,具體修改可參照s3c2440數(shù)據(jù)手冊,例如:
使用命令$ gedit arch/arm/include/asm/arch-s3c24x0/s3c24x0.h分別定位到81、91、95、106、144、400行,將#ifdef CONFIG_S3C2410改為#if defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)。
然后在struct s3c24x0_clock_power結(jié)構(gòu)體中加入2440 的NAND FLASH 的數(shù)據(jù)結(jié)構(gòu)成員CAMDIVN定義,具體代碼為:
#if defined (CONFIG_S3C2440)
u32 CAMDIVN; //for mini2440
#endif
注:這個結(jié)構(gòu)是用來封裝時鐘寄存器的,要在其中增加一項CAMDIVN寄存器是2410所沒有的,而2440在配置時鐘的時候又必須用到,看名字我們就知道是用來配置CAMERA時鐘的,即用來配置攝像頭的時鐘的。
③ 修改timer.c
在defined(CONFIG_SMDK2410) || \ 下添加defined(CONFIG_MINI2440) || \。
3 U-boot的生成、測試
3.1 目標文件的生成
現(xiàn)在編譯u-boot,在根目錄下會生成一個u-boot.bin文件。我們利用mini2440原有的supervivi把u-boot.bin下載到RAM中運行測試(注意:我們使用supervivi進行下載時已經(jīng)對CPU、RAM進行了初始化,所以我們在u-boot中要屏蔽掉對CPU、RAM的初始化),用gedit打開cpu/arm920t/start.S,定位到如下代碼:
//#ifndef CONFIG_SKIP_LOWLEVEL_INIT
//bl cpu_init_crit
//#endif
3.2 測試編譯
以root用戶登陸Linux操作系統(tǒng),在U-Boot主目錄下依次運行以下命令:
$ make distclean
$ make mini2440_config
Configuring for mini2440 board...
$ make
編譯成功會生成一個二進制文件u-boot.bin,通過特制的Flash燒寫程序J-Link將二進制文件U-boot.bin燒入Flash的零地址。燒寫成功后,拔掉J-Link接口復(fù)位開發(fā)板。
從超級終端輸出如下信息:
u-Boot 2010.06 (Aug 16 2012 -14:13:18)
DRAM: 64MB
Flash:512KB
In: serial
Out:serial
Err:serial
Net:cs8900-0
[u-boot@MINI2440]#
在超級終端顯示的信息表明,CPU和串口已經(jīng)正常工作,能進入U-Boot界面。接下來我們用命令測試Flash、SDRAM、網(wǎng)絡(luò)等。測試結(jié)果表明,U-Boot移植成功并且可以在系統(tǒng)板上穩(wěn)定地運行。
4 結(jié)束語
U-Boot作為目前使用最廣泛的嵌入式Bootloader,一直都是嵌入式系統(tǒng)研究的重點。針對S3C2440的特點,我們詳細介紹了U-boot的移植過程。通過上述方法移植的U-Boot目前能穩(wěn)定地運行在開發(fā)板上,實現(xiàn)了串口與PC機的通信,查看和修改內(nèi)存,以及引導(dǎo)Linux內(nèi)核等的功能,為后續(xù)嵌入式系統(tǒng)軟件的開發(fā)提供了良好的環(huán)境。
參考文獻:
[1] 田會峰.基于S3C2440的Bootloader設(shè)計與實現(xiàn)[J].自動化技術(shù)與
應(yīng)用,2010.29(7):29-32
[2] 韋東山.嵌入式Linux應(yīng)用開發(fā)完全手冊[M].人民郵電出版社,2008.
[3] Current Versions.DENX software engineering [EB/OL].http://
www.denx.de/wiki/DULG/Manual.2010.12.
[4] 李軍,張華春.U-Boot及Linux2.6在S3C2440A平臺上的移植方法
[J].電子器件,2008.10:1667-1670
[5] u-boot-2010.06在mini2440上的移植[EB/OL].http://blog.
chinaunix.net/uid-26552187-id-3128489.html.2012.3.
[6] 孫天澤.嵌入式設(shè)計及Linux驅(qū)動開發(fā)指南[M].電子工業(yè)出版社,
2005.