李宇飛 嵇啟春 劉浩洋
(西安建筑科技大學信息與控制工程學院, 陜西 西安 710055)
摘要: 引導加載程序是嵌入式系統開發的重要環節,它使得操作系統和硬件平臺聯系起來,對嵌入式系統的后繼軟件開發十分重要。為此,介紹了當前嵌入式開發中功能強大、穩定可靠的引導加載程序U-Boot的目錄結構、啟動流程及其移植的思路和引導內核的方法;給出了移植Uboot-2010-06到ARM微處理器S3C2440上所需操作環境的搭建,具體代碼的修改,具體參數的設置,以及所需的操作命令等要點。最后將編譯生成的U-Boot.bin文件下載到ARM微處理器S3C2440上,測試顯示,U-Boot可以達到設計的功能要求并能夠穩定運行,而且通過對其進行正確的配置可以引導內核。
關鍵詞: 嵌入式系統; 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 引言
在嵌入式軟件開發中,嵌入式Linux系統通常包括引導加載程序、Linux內核、文件系統和用戶應用程序四部分[1]。引導加載程序包括固化在固件(firm-ware)中的boot代碼(可選)和Bootloder。簡言之,Bootloader就是在操作系統內核運行之前運行的一段小程序,它在系統上電時開始執行,初始化硬件設備、準備好軟件環境,最后調用操作系統內核[2]。由于Bootloader的實現非常依賴于具體的硬件,即使是基于同一種處理器構建的不同開發板,具有相同的CPU,它的外設(比如FLASH)也可能不同,所以不可能有一個通用的Bootloader來支持所有的CPU,而可能的是,讓一個Bootloader代碼支持多種不同的構架和操作系統,并讓它有很好的可移植性。U-Boot就是支持多平臺多操作系統的一個杰出代表,移植U-Boot是為下一步引導內核和文件系統做準備,但U-Boot移植完成后由于開發途徑的不同還需要做些設置才能引導內核和文件系統。本文重點是針對最小硬件系統的Bootloader移植的研究。
1 U-boot的概述及啟動過程
1.1 U-Boot簡介
U-Boot (universal boot loader)是德國DENX軟件工程中心開發的一款遵循GPL條款的開放源碼軟件產品,其對現在市場上主流的操作系統,CPU都能提供良好的支持,除了支持Linux系統的引導外,還支持NetBSD、VxWorkd、LynxOS等嵌入式操作系統,并且支持ARM、PowerPC、NIOS、XScale等處理器。U-Boot的程序框架清晰,功能強大,具有較高的穩定性和可靠性,豐富的設備驅動源碼,移植方便。這些特點是它被選擇移植到mini2440開發板上的原因。
1.2 U-Boot的源碼結構
本文主要是針對U-Boot-2010-06的分析與移植。其源碼可以在官方網站下載,解壓后可以得到它的全部代碼。
U-Boot-2010-06根目錄下共有29個子目錄,根據其作用可以分為開發板類型相關、平臺相關、通用的函數、通用的設備驅動、文檔示例程序、工具等幾類。表1給出了U-Boot的主要目錄結構[3]。
1.3 U-Boot的啟動流程
由于本次移植采用的硬件平臺是友善之臂的mini2440開發板,而U-boot-2010-06沒有提供基于S3C2440芯片的開發板支持,我們可以通過修改與其結構相近的smdk2410的配置文件和相關源代碼,去實現U-Boot對s3c2440的支持[4]。Bootloader的啟動過程可以分為單階段和多階段。從固態存儲設備上啟動的Bootloader是兩個階段的啟動過程。第一階段用到的文件為cpu/xxx/start.S和board/xxx/lowlevel_init.S文件中,這兩個文件用匯編語言寫成;第二階段的代碼通常放在lib_xxx/board.c文件中,用C語言寫成,主要任務是初始化本階段用到的硬件、檢測系統內存映射、將內核鏡像和根文件系統鏡像從Flash上讀到RAM空間中并為內核設置啟動參數最終啟動內核。
表1U-Boot主要目錄說明
[[U-Boot目錄\&功能說明\&board\&一些已經支持的開發板相關文件\&common\&與處理器體系結構無關的通用代碼\&cpu\&與處理器相關的文件\&disk\&Disk驅動分區相關信息代碼\&doc\&U-Boot的說明文檔\&drivers\&通用設備驅動程序,如:網卡、FLASH、串口、USB總線等\&fs\&支持文件系統的文件,如:cramfs、fat、fdos、jffs2等\&include\&U-Boot頭文件,還有各硬件平臺的匯編文件,系統配置文件\&Lib_xxx\&處理器體系結構相關文件,如:lib_arm包含的是ARM體系結構\&net \&與網絡功能相關的文件,如:bootp 、nfs、tftp等\&post\&上電自檢文件目錄\&tools\&用于創建U-Boot、S-Record和Bin鏡像文件的工具\&]]
[系統復位轉入U-BOOT
的stage1入口點][設置異常向量][設置CPU的時鐘、速度、
頻率及終端控制寄存][初始化內存控制器][拷貝U-BOOT的stage2到代碼到RAM空間][設置堆棧、初始化數據段][本階段硬件設備初始化] [Stage1部分][跳轉到stage2的
C入口點][初始化FLASH設備][初始化NAND、顯示、
網絡等設備][初始化系統內存][將kernel和根文件系統映射從FLASH讀到ARM中][設定內核啟動參數和調用內核][本階段硬件設備初始化] [Stage2部分]
圖1U-Boot的啟動流程圖
2 U-Boot的移植
在移植U-Boot之前首先要建立開發環境,然后根據具體的應用平臺的要求生成相應的U-Boot.bin二進制文件,再將U-Boot.bin下載到目標板上,本文采用的是友善之臂的mini2440開發板,此開發板采用405MHZ的ARM920T內核的處理器S3C2440,下面是具體的移植過程。
2.1 移植環境
2.1.1 所需要的軟件環境
軟件環境為:Vm-ware6.0、Ubuntu/Redhat、TFTP Server、J-Link、Samba服務器、arm-linux-gcc-4.3.2.tgz、U-Boot-2010.
06.tar.gz2等。
2.1.2 Windows所需開發環境
⑴ 安裝TFTP Server,此軟件用于開發板和Windows的交互,通過它可以把編譯好的U-Boot的二進制文件和內核二進制文件燒錄到開發板上。
⑵ 使用超級終端通過串口顯示U-Boot的運作信息。
⑶ 安裝J-Link,此軟件的作用是把生成U-Boot.bin燒寫到目標板上。
⑷ 安裝Vm-ware6.0用于安裝Linux操作系統。
2.1.3 Linux所需開發環境
⑴ 建立Linux和Windows的交互平臺Samba服務。使得Linux和Windows之間可以通過一個共享目錄互相傳送文件。
⑵ 交叉編譯環境的搭建。將arm-linux-gcc-4.3.2.tgz通過Samba服務器傳送到Linux內,然后解壓,輸入命令:
#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操作系統,讓新增加的配置生效。
⑶ 解壓U-Boot-2010.06.tar.gz2。方法和解壓arm-linux-
gcc-4.3.2.tgz類似。
2.2 移植文件操作
移植U-Boot除了依賴CPU的體系結構外,還依賴于具體的嵌入式板級設備的配置,只需選擇與自己板子最為相近的作為基礎。與CPU相關的文件位于U-Boot根目錄下CPU/arm920t目錄及子目錄S3C24x0中。與Board相關的文件位于U-Boot根目錄下的board/sbc2410x目錄下。該版本U-Boot并不支持本文使用的ARM微處理器S3C2440,但是對于同一個系列的另一款微處理器S3C2410卻有很完善的支持。兩款芯片使用相同的ARM核,片內集成的功能以及寄存器的使用都很接近,所以U-Boot的移植工作在S3C2410和對應的開發板SMDK2410的基礎上展開;并且隨著U-Boot版本的不斷升級許多目錄的內容做了很多改動,例如U-Boot-2010-06和以前的版本就有變化,它的/cpu/arm920t下的很多內容移放到了drivers目錄下,因此/drivers目錄下也需要修改,對此就不作詳細介紹,在此我們重點介紹移植的思路[5]。
⑴ 進入u-boot的根目錄,并修改Makefile文件。
修改Makefile的命令如下:
$ cd u-boot-2010.06/
$ gedit Makefile
首先搜索CROSS_COMPILE,將CROSS_COMPILE=?改為交叉編譯工具鏈CROSS_COMPILE ?= arm-linux-,然后搜索smdk2410,并仿照它建立自己開發板的配置選項,在smdk2410_config: unconfig @$(MKCONFIG) $(@:_config=) arm arm920t s3c2410NULL s3c24x0下添加mini2440_config: unconfig @$(MKCONFIG) $(@:_config=) arm arm920tmini2440 jason s3c24x0然后保存。
說明:
arm:CPU的架構(ARCH)。
arm920t:CPU的類型。
mini2440:對應在board目錄下建立新的開發板項目的目錄。
jason:新開發板項目目錄的上級目錄,如直接在board下建立新的開發板項目的目錄,則這里就為NULL。
s3c24x0:CPU型號。
注意:編譯選項格式的第二行在@前面要用Tab鍵開始,否則編譯會出錯。
⑵ 建立mini2440開發板的板子目錄文件。
① 復制smdk2410的板子目錄文件為mini2440,命令如下:
$ mkdir -p board/jason
$ cd board/jason/
$ cp -rf ../samsung/smdk2410/ mini2440
② 重命名smdk2410.c為mini2440.c并修改對應的Makefile文件:
$ mv smdk2410.c mini2440.c
COBJS :=mini2440.o flash.o
SOBJS :=lowlevel_init.o
⑶ 在根目錄下定位到include/configs,建立mini2440開發板的配置頭文件。
修改頭文件smdk2410.h。該文件的作用是對CPU內部寄存器相對位置安排和命名寄存器的名稱。將smdk2410.h復制并粘貼到當前目錄下,將其重命名成mini2440.h,命令如下:
$ cp include/configs/smdk2410.h include/configs/mini2440.h
⑷ 修改開發板的終端中命令行提示符。
用gedit打開include/configs/mini2440.h頭文件,定位到117行,其中的“SMDK2410#”就是開發板在終端顯示的提示符,現在將其改為“[u-boot@MINI2440]#,如下所示:
#define CONFIG_SYS_PROMPT “[u-boot@MINI2440]#”
/*Monitor Command Prompt */
⑸ 注釋掉不需要的LED代碼。
① $ gedit arch/arm/cpu/arm920t/start.S
下面這兩行是AT91RM9200DK開發板的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文件是開發板相關的,這表示如果外接的設備不一樣,可以修改lowlevel_init.S文件中的相關宏。
部分修改代碼如下:
#if defined(CONFIG_S3C2440)
#define Trp 0x2 /* 4clk */
#define REFCNT 1012
#else
#define Trp 0x0 /* 2clk */
#define REFCNT 1113
……
⑻ 增加對S3C2440一些寄存器的支持,添加中斷禁止部分和時鐘設置部分。
① 修改cpu/arm920t中的start.S文件,U-Boot的階段1代碼通常放在此文件中。
中斷禁止部分添加代碼如下:
# if defined(CONFIG_S3C2440) //添加s3c2440的中斷禁止部分
ldr r1, =0x7fff //根據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 //系統主頻配置寄存器基地址
#define UPLLCON 0x4C000008 //USB時鐘頻率配置寄存器基地址
ldr r0, =CLKDIVN //設置分頻系數FCLK:HCLK:PCLK=1:4:8
mov r1, #5
str r1, [r0]
ldr r0, =MPLLCON //設置系統主頻為405MHz
ldr r1, =0x7F021 //這個值參考芯片手冊“PLL VALUE SELECTION
TABLE”部分
str r1, [r0]
ldr r0,=UPLLCON //設置USB時鐘頻率為48MHz
ldr r1,=0x38022 //這個值參考芯片手冊“PLL VALUE SELECTION
TABLE”部分
str r1,[r0]
# else
……
② 修改與Board相關的文件mini2440.c,該文件主要完成對GPIO和PLL的配置。
修改代碼如下:
#define FCLK_SPEED 2 //設置默認等于2,即下面代碼部分有效
#elif FCLK_SPEED==2/* Fout=405MHz */
#define M_MDIV 0x7F //這三個值根據S3C2440芯片手冊“PLL
VALUE SELECTION TABLE”部分進行設置
#define M_PDIV 0x2
#define M_SDIV 0x1
#define USB_CLOCK 2//設置默認等于2,即下面代碼部分有效
#elif USB_CLOCK==2/* Fout=48MHz */
#define U_M_MDIV 0x38//這三個值根據S3C2440芯片手冊
“PLL VALUE SELECTION TABLE”部分進行設置
#define U_M_PDIV 0x2
#define U_M_SDIV 0x2
③ 修改cup/arm920t/s3c24x0/speed.c文件,根據設置的分頻系數FCLK:HCLK:PCLK=1:4:8修改獲取時鐘頻率的函數。由于s3c2410和s3c2440的MPLL、UPLL計算公式不一樣,所以修改get_PLLCLK和函數加入以下代碼:
#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內部寄存器相對位置安排和命名寄存器的名稱,具體修改可參照s3c2440數據手冊,例如:
使用命令$ 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結構體中加入2440 的NAND FLASH 的數據結構成員CAMDIVN定義,具體代碼為:
#if defined (CONFIG_S3C2440)
u32 CAMDIVN; //for mini2440
#endif
注:這個結構是用來封裝時鐘寄存器的,要在其中增加一項CAMDIVN寄存器是2410所沒有的,而2440在配置時鐘的時候又必須用到,看名字我們就知道是用來配置CAMERA時鐘的,即用來配置攝像頭的時鐘的。
③ 修改timer.c
在defined(CONFIG_SMDK2410) || \ 下添加defined(CONFIG_MINI2440) || \。
3 U-boot的生成、測試
3.1 目標文件的生成
現在編譯u-boot,在根目錄下會生成一個u-boot.bin文件。我們利用mini2440原有的supervivi把u-boot.bin下載到RAM中運行測試(注意:我們使用supervivi進行下載時已經對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操作系統,在U-Boot主目錄下依次運行以下命令:
$ make distclean
$ make mini2440_config
Configuring for mini2440 board...
$ make
編譯成功會生成一個二進制文件u-boot.bin,通過特制的Flash燒寫程序J-Link將二進制文件U-boot.bin燒入Flash的零地址。燒寫成功后,拔掉J-Link接口復位開發板。
從超級終端輸出如下信息:
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和串口已經正常工作,能進入U-Boot界面。接下來我們用命令測試Flash、SDRAM、網絡等。測試結果表明,U-Boot移植成功并且可以在系統板上穩定地運行。
4 結束語
U-Boot作為目前使用最廣泛的嵌入式Bootloader,一直都是嵌入式系統研究的重點。針對S3C2440的特點,我們詳細介紹了U-boot的移植過程。通過上述方法移植的U-Boot目前能穩定地運行在開發板上,實現了串口與PC機的通信,查看和修改內存,以及引導Linux內核等的功能,為后續嵌入式系統軟件的開發提供了良好的環境。
參考文獻:
[1] 田會峰.基于S3C2440的Bootloader設計與實現[J].自動化技術與
應用,2010.29(7):29-32
[2] 韋東山.嵌入式Linux應用開發完全手冊[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] 孫天澤.嵌入式設計及Linux驅動開發指南[M].電子工業出版社,
2005.