蔡利平,任家富,童 銳,張敬倫
(成都理工大學(xué) 信息科學(xué)與技術(shù)學(xué)院,四川 成都610059)
嵌入式系統(tǒng)開發(fā)在當(dāng)今日新月異的科技時代獨樹一幟,生活中大量的智能電子設(shè)備就是嵌入式應(yīng)用的一個縮影,比如PDA、機頂盒和智能手機等。然而,在嵌入式軟件的開發(fā)中,嵌入式引導(dǎo)程序 (Bootloader)的設(shè)計、開發(fā)與嵌入式系統(tǒng)的硬件息息相關(guān),這個特性決定了不可能用一個通用程序作為眾多嵌入式系統(tǒng)的引導(dǎo)程序。在這樣的背景下,針對不同的開發(fā)環(huán)境設(shè)計不同的嵌入式系統(tǒng)引導(dǎo)程序成為首要問題,本文根據(jù)實際的情況,詳細(xì)的分析了嵌入式引導(dǎo)程序的引導(dǎo)、啟動原理,同時結(jié)合S3C2410開發(fā)板和 U-Boot-1.1.6引導(dǎo)程序,分析從 Nand Flash啟動的具體流程,修改并完成了 U-Boot從Nand Flash啟動的移植。
嵌入式軟件從應(yīng)用角度可以劃分為4個層次:引導(dǎo)程序 (Bootloader)、內(nèi)核、文件系統(tǒng)以及嵌入式應(yīng)用軟件(如GUI)。Bootloader是嵌入式系統(tǒng)中第一個被運行的程序,其功能是初始化部分硬件、為隨后加載的系統(tǒng)內(nèi)核準(zhǔn)備相關(guān)的系統(tǒng)參數(shù) (機器類型ID和啟動參數(shù)標(biāo)記列表在RAM中的地址)、加載內(nèi)核到內(nèi)存并將系統(tǒng)的控制權(quán)移交給內(nèi)核?,F(xiàn)在支持ARM體系結(jié)構(gòu)的bootloader很多,比如Vivi、RedBoot、BLOB以及U-Boot等。不同的Bootloader在支持的體系結(jié)構(gòu)和種類上有所不同,本文主要是針對U-Boot進行分析與移植。U-Boot是德國DENX研究中心開發(fā)設(shè)計的,其對現(xiàn)在市場上主流的操作系統(tǒng)、CPU都能提供良好的支持,功能相當(dāng)?shù)膹姶?。U-Boot的文件組織方式與Linux內(nèi)核相同,將功能或者特性相同的源文件放在一起,方便對源文件的管理與閱讀。根據(jù)文件的不同作用,本人將U-Boot中所有的源文件相對的劃分為下面的3個層次。如圖1所示。
之所以這樣分層,是因為:上層包含的/cpu和/board文件決定了系統(tǒng)所使用的ARM芯片類型以及與開發(fā)板相同或者相近的板級體系結(jié)構(gòu),如S3C2410開發(fā)板,相近的文件就 是/cpu/arm920t和/board/smdk2410,而/lib_xxx文件主要包含的是庫文件,屬于必不可少的部分;中間層文件include/configs/xxx.h中定義了眾多的宏,其中定義的配置宏和參數(shù)宏在代碼的編譯過程中將決定哪些代碼段將被包含,哪些代碼段將不被包含,控制Bootloader所實現(xiàn)的功能,起一個承上啟下的作用;底層主要包含了相關(guān)的驅(qū)動程序以及一些通用函數(shù)和接口函數(shù)。
在嵌入式系統(tǒng)中,根據(jù)引導(dǎo)系統(tǒng)存儲的位置,引導(dǎo)系統(tǒng)啟動主要分為有兩種方式:Nor Flash引導(dǎo)和Nand Flash引導(dǎo)。這兩種引導(dǎo)方式不管是從硬件連接還是從軟件設(shè)計都有本質(zhì)的不同,現(xiàn)在主流的引導(dǎo)程序基本上都支持從Nor Flash的啟動引導(dǎo),軟件技術(shù)的實現(xiàn)相對比較成熟;但是對Nand Flash的啟動支持還不是很完善,要能夠從Nand Flash啟動,需要引導(dǎo)程序和開發(fā)板都支持從Nand Flash啟動。本文使用的U-Boot-1.1.6并不支持從Nand Flash啟動的,而開發(fā)板S3C2410的硬件特性支持從Nand Flash啟動。本文將通過分析U-Boot的啟動流程,最終實現(xiàn)U-Boot從Nand Flash的啟動與移植。
Bootloader的啟動一般可以分為兩個階段。第一階段主要是對部分硬件 (關(guān)閉看門狗、關(guān)中斷、設(shè)置時鐘和初始化存儲設(shè)備等)的初始化、拷貝引導(dǎo)程序U-Boot自己全部的代碼到SDRAM中以及為第二階段的執(zhí)行準(zhǔn)備硬件環(huán)境 (清除BSS段、設(shè)置堆棧等),用匯編代碼實現(xiàn)。第二階段繼續(xù)完成對外圍硬件設(shè)備的檢測與初始化,為內(nèi)核引導(dǎo)提供硬件環(huán)境和引導(dǎo)參數(shù)。U-Boot在第二階段對Nor Flash和對Nand Flash的支持是相同的,因此,支持Nand Flash啟動的代碼修改主要集中在U-Boot啟動的第一階段。為了得出U-Boot從Nor Flash引導(dǎo)與從Nand Flash引導(dǎo)的不同之處,這里結(jié)合韓國Mize公司的Vivi bootloader,Vivi最初主要是針對S3C2410X處理器的,支持從Nand Flash啟動的引導(dǎo),通過分析,第一階段的引導(dǎo)流程如圖2所示。
圖2中方向①、②指明了Nand Flash與Nor Flash在引導(dǎo)程序第一階段的不同之處,在程序中體現(xiàn)在/cpu/arm920t/start.S源文件的重定位代碼段,源文件start.S也是U-Boot程序的入口文件,具體比較如圖3所示。
U-Boot從Nor Flash啟動的引導(dǎo)系統(tǒng),只需要根據(jù)具體硬件的配置,更改少量的配置選項即可完成引導(dǎo)工作。通過上面的分析,為了實現(xiàn)Nand Flash引導(dǎo)啟動需要修改U-Boot代碼完成以下幾個方面的問題:
(1)保證U-Boot的前4k代碼不僅能夠初始化相關(guān)的硬件,還要能夠?qū)⒋鎯υ贜and Flash中的所有U-Boot代碼拷貝到SDRAM中,這也是第一階段的主要任務(wù);
(2)在配置文件/include/configs/xxx.h中添加相關(guān)的宏,確定啟動是從Nand Flash中進行,以及確定U-Boot代碼在SDRAM中的起始位置、設(shè)置堆棧大小;
(3)最后需要實現(xiàn)對Nand Flash讀寫操作的命令支持,能夠使U-Boot在控制終端使用Nand Flash命令對Nand Flash進行相關(guān)的操作。
圖3 Nor Flash引導(dǎo)和Nand Flash引導(dǎo)的比較
系統(tǒng)引導(dǎo)啟動方式 (Nor Flash or Nand Flash引導(dǎo))是由引腳OM [1:0]來確定的,如果OM [1:0]為0x0,則是從Nand Flash引導(dǎo);如果OM [1:0]的值為0x1,0x2則是從Nor Flash引導(dǎo),這可以通過跳線來設(shè)置,有的開發(fā)板直接使用Nand Flash硬件連接。系統(tǒng)如果從Nand Flash啟動,由于Nand Flash接口的特殊性,系統(tǒng)上電后會自動將Nand Flash前4k的代碼復(fù)制到S3C2410內(nèi)部集成的SRAM中,然后跳到這個SRAM緩沖區(qū)中0x0開始執(zhí)行,這部分代碼需要完成硬件的初始化并將U-Boot代碼拷貝到SDRAM中后,然后跳轉(zhuǎn)到SDRAM中執(zhí)行。這里首先修改 源文件 uboot/board/s3c2410/start.S,在其中添加對Nand Flash的初始化代碼,然后完成 U-Boot的拷貝:
coyp_myself_uboot:
(Nand Flash的初始化代碼)
……
ldr r0,=UBOOT_RAM_BASE
//這是將U-Boot代碼拷貝到SDRAM中的起始地址
mov r1,#0x0
//這是U-Boot在Nand Flash中的起始地址,即0x0
mov r2,#0x20000
//這是U-Boot代碼的長度
bl nandTOsdram
//完成U-Boot到SDRAM拷貝的C函數(shù)
……
跳轉(zhuǎn)到源文件nand_copy.c中的拷貝函數(shù)nandTOsdram中。這里的寄存器r0,r1,r2依次作為nandTOsdram的第一、第二和第三個參數(shù)。在/board/s3c2410/下添加文件nand_copy.c,主要代碼如下:
……
int nandTOsdram (unsigned char*buf,unsigned long start_addr,int size){
int i,j;
if((start_addr & NAND_BLOCK_MASK)‖ (size&NAND_BLOCK_MASK)){
return-1; /*invalid alignment*/
}
/*chip Enable*/
NFCONF &= ~0x800;
for(i=0;i<10;i++);
for(i=start_addr;i< (start_addr+size);){
/*READ0*/
NFCMD=0;
/* Write Address*/
NFADDR =i &0xff;
NFADDR= (i>>9)&0xff;
NFADDR= (i>>17)&0xff;
NFADDR= (i>>25)&0xff;
wait_idle ();
for(j=0;j< NAND_SECTOR_SIZE;j++,i++){
*buf= (NFDATA &0xff);
buf++;
}
}
/*chip Disable*/
NFCONF|=0x800; /*chip disable*/
return 0;
}
通過在/cpu/arm920t/start.s中添加的Nand Flash初始化代碼以及C源文件nand_copy.c解決了U-Boot從Nand Flash啟動的第一個問題。
配置文件/include/configs/xxx.h控制整個開發(fā)板的編譯選項,主要包括兩類:以CONFIG_開頭的文件用于選擇CPU、SOC、開發(fā)板類型等,作為系統(tǒng)框架設(shè)計的一個選項;還有一類是以CFG_開頭的宏,作為系統(tǒng)的參數(shù)出現(xiàn),如設(shè)置緩沖池的大小、提示符等。為了獲得U-Boot Nand Flash啟動的支持,需要在配置文件中添加以下幾個宏:
#define CONFIG_S3C2410_NAND_BOOT 1//控制編譯從Nand Flash啟動的代碼
#define STACK_BASE 0x33f00000//定義堆棧在SDRAM中的位置以及長度
#define STACK_SIZE 0x8000
#define UBOOT_RAM_BASE 0x33f80000//U-Boot代碼在SDRAM中的起始位置
#define NAND_CTL_BASE 0x4e000000//Nand Flash各個控制器的地址的定義
#define bINT_CTL (Nb) __REG (INT_CTL_BASE+ (Nb))
/
*offset*/
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFADDR 0x08
#define oNFDATA 0x0c
#define oNFSTAT 0x10
#define oNFECC 0x14
經(jīng)過上述兩步的修改,U-Boot已經(jīng)實現(xiàn)了從Nand Flash的啟動,但是在控制終端并不能通過U-Boot的命令來對Nand Flash進行讀寫操作。
U-Boot對Nand Flash的讀寫操作命令并沒有給予完整的支持。要先在配置文件中打開Nand Flash命令的控制宏:
#define CONFIG_COMMANDS\
(CONFIG_CMD_DFL | \
CFG_CMD_CACHE | \
CFG_CMD_NAND | 去掉之前的注釋符號,使的CFG_CMD_NAND可用
/
*CFG_CMD_EEPROM|*/\
/*CFG_CMD_I2C |*/\
……)
同時,由于U-Boot默認(rèn)的代碼不能識別本文開發(fā)板上的Nand Flash K9F1208U0A芯片型號,還需要在文件/include/linux/mtd/nand_ids.h中的結(jié)構(gòu)體添加如下代碼,以識別芯片型號:
static struct nand_flash_dev nand_flash_ids[]= {
……
{"Samsung K9F1208U0A",NAND _MFR _SAMSUNG,0x76,26,0,3,0x4000,0},}
對 Nand Flash的讀寫操作在 U-Boot-1.1.6中有新舊兩套代碼,/driver/nand是新代碼文件,/driver/nand_legacy是舊代碼文件,如果在配置文件中定義了宏CFG_NAND_LEGACY,則通過舊代碼部分獲得對Nand Flash的支持,否則使用新代碼支持Nand Flash的底層操作,本文使用的是新代碼部分。在代碼中還需要實現(xiàn)函數(shù)board_nand_init()的定義,實現(xiàn)對Nand Flash的底層操作,這個函數(shù)在文件/driver/nand/nand.c中只進行了聲明:
……
extern void board_nand_init (struct nand_chip *nand);
……
沒有定義的具體代碼,添加源文件nflash.c并在此源文件中實現(xiàn)board_nand_init函數(shù),函數(shù)的調(diào)用過程如圖4所示。
圖4 board_nand_init函數(shù)的調(diào)用過程
對Nand Flash底層函數(shù)的管理都是通過結(jié)構(gòu)體struct nand_chip實現(xiàn)的,在board_nand_init函數(shù)中就是要實現(xiàn)這個結(jié)構(gòu)體中各個底層函數(shù),但是并不用實現(xiàn)結(jié)構(gòu)體的每一個成員變量,這里必須要實現(xiàn)的結(jié)構(gòu)體成員有:
讀寫信號nand->IO_ADDR_R= (void*)&s3c2410_mynand->NFDATA,nand->IO_ADDR_W= (void*)&s3c2410_mynand->NFDATA;控制信號函數(shù)nand->hwcontrol=s3c2410_nand_control_signal;芯片狀態(tài)函數(shù)nand->dev_ready=s3c2410_nand_if_busy;片選信號函數(shù) nand->select_chip=s3c2410_nand_select_chip以及位寬options的設(shè)置。到這里就完成了U-Boot從Nand Flash啟動的代碼修改,也實現(xiàn)了在終端對Nand Flash命令的支持。
在U-Boot的頂層目錄執(zhí)行命令:
make distclean
make s3c2410_config
make CROSS_COMPILE=arm-linux-
生成目標(biāo)文件uboot.bin,將其通過并口燒寫到Nand Flash中,然后重啟,控制終端顯示如下:
U-Boot 1.1.6(Nov 20 2010-15:32:38)
U-Boot code:33F80000->33F9A768BSS:->33F9EF18
DRAM: 64 MB
NAND: 64 MB
In: serial
Out: serial
Err: serial
CAI_s3c2410#
到這里就成功的完成了U-Boot的修改與移植。這里還有幾個問題需要注意:為了能夠在控制終端顯示U-Boot在SDRAM中段的分布,需要將文件/lib_arm/board.c中的debug("U-Boot code:%08lX-> %08lX BSS:-> %08lX\n",_armboot_start,_bss_start,_bss_end)換成printf("U-Boot code:%08lX-> %08lX BSS:-> %08lX\n",_armboot_start,_bss_start,_bss_end);本開發(fā)板上沒有nor flash,因此要在配置文件中注釋掉flash的定義,并且注釋掉/common/cmd_bootm.c中關(guān)于imls命令的程序段和/common/cmd_flash.c中的程序段。
結(jié)合硬、軟件開發(fā)的嵌入式系統(tǒng),分析、設(shè)計其啟動流程是開發(fā)過程中第一個需要解決的問題。U-Boot引導(dǎo)程序以清晰明了的流程,詳細(xì)的描述了怎么實現(xiàn)引導(dǎo)的具體過程。本文同時結(jié)合了Vivi的啟動流程分析,實現(xiàn)了支持Nand Flash啟動引導(dǎo)的U-Boot,詳細(xì)的介紹怎么實現(xiàn)這個程序的修改過程。通過對U-Boot啟動的分析能夠深刻的理解到軟件是怎么實現(xiàn)對硬件的操作,綜合的應(yīng)用了所學(xué)的知識,為開發(fā)嵌入式系統(tǒng)獲得直接經(jīng)驗。
[1]DU Chunlei.The architecture of ARM and program [M].Beijing:Tsinghua University Press,2009:58-223 (in Chinese).[杜春雷.ARM體系結(jié)構(gòu)與編程 [M].北京:清華大學(xué)出版社,2009:58-223.]
[2]LAI Yushu.ARM MPU and applications[M].Beijing:Publishing House of Electronics Industry,2007:75-150 (in Chinese).[賴于樹.ARM微處理器與應(yīng)用開發(fā) [M].北京:電子工業(yè)出版社,2007:75-150.]
[3]WANG Minghu.The exploitation induction of ARM embedded Linux[M].Beijing:Publishing House of Electric Power China,2008:55-102 (in Chinese).[汪明虎.ARM嵌入式Linux應(yīng)用開發(fā)入門 [M].北京:中國電力出版社,2008:55-102.]
[4]WEI Dongshan.The app exploitation entirety manual of embedded Linux[M].Beijing:The Press of People Postal and Electricity,2008:240-292(in Chinese).[韋東山.嵌入式Linux應(yīng)用開發(fā)完全手冊 [M].北京:人民郵電出版社,2008:240-292.]
[5]SUN Qiong.The application exploitation details of embedded Linux[M].Beijing:The Press of People Postal and Electricity,2006:116-121(in Chinese).[孫瓊.嵌入式Linux應(yīng)用程序開發(fā)詳解[M].北京:人民郵電出版社,2006:116-121.]
[6]Stephen Prate.C primer plus [M].Beijing:Posts &Telecom Press,2010:354-376 (in Chinese).[Stephen Prate.C primer plus[M].北京:人民郵電出版社,2010:354-376.]
[7]DU Haixing.The analysis and transplant of embedded Bootloader based ARM [J].Microcomputer Information,2010,26 (10-2):58-59(in Chinese).[杜海星.基于ARM的嵌入式Bootloader分析與移植 [J].微計算機信息,2010,26 (10-2):58-59.]
[8]ZHAN Rongkai.The startup secret of embedded Bootloader[EB/OL].http://www.ibm.com/developerworks/cn/linux/l-btloader/,2010 (in Chinese).[詹榮開.嵌入式 Bootloader啟 動 內(nèi) 幕 [EB/OL].http://www.ibm.com/developerworks/cn/linux/l-btloader/,2010.]
[9]Tekkaman Ninja.Transplant U-Boot 1.2.0 to Weichuang 2410-S (S3C2410A) [EB/OL].http://blog.chinaunix.net/u1/34474/showart.php?id= 363269,2010 (in Chinese).[Tekkaman Ninja.移植 U-Boot.1.2.0到博創(chuàng)2410-S(S3C2410A) [EB/OL].http://blog.chinaunix.net/u1/34474/showart.php?id=363269,2010.]
[10]QIU Xuehong.The truth of microcomputer and interface technic[M].Xi’an:Xi’dian University Press,2007:66-134(in Chinese).[裘雪紅.微型計算機原理及接口技術(shù) [M].西安:西安電子科技大學(xué)出版社,2007:66-134.]
[11]ZHANG Shi.The tutorial of ARM embedded system [M].Beijing:China Machine Press,2008:35-66 (in Chinese).[張石.ARM嵌入式系統(tǒng)教科書 [M].北京:機械工業(yè)出版社,2008:35-66.]
[12]WU Shili.The resolve and practice of embedded Linux App exploitation [M].Beijing:China Machine Press,2008:135-146 (in Chinese).[吳士力.嵌入式LINUX應(yīng)用開發(fā)全程解析與實戰(zhàn)[M].北京:機械工業(yè)出版社,2008:135-146.]
[13]Qing Ting Dian Shui.The startup process of U-Boot[EB/OL].http://wenku.baidu.com/view/4428024ae45c3b3567ec8b4d.html,2010(in Chinese).[蜻蜓點水.U-Boot啟動過程 [EB/OL].http://wenku.baidu.com/view/4428024ae45c3b3567ec8b 4d.html,2010.]
[14]CHU Shi Feng Mang.The manual of transplanting U-Boot to S3C2410 [EB/OL].http://wenku.baidu.com/view/1c2cb28da 0116c175f0e48f3.html,2010 (in Chinese).[初試鋒芒.UBOOT移植S3C2440完全手冊 [EB/OL].http://wenku.baidu.com/view/1c2cb28da0116c175f0e48f3.html,2010.]
[15]lien5.The Nand Flash drive analysis based on S3C2410 [EB/OL].http://hi.baidu.com/52hack/blog/item/675119df980b401b62279809.html,2010 (in Chinese).[lien5.對S3C2410平臺上 Nand Flash的驅(qū) 動 分 析 [EB/OL].http://hi.baidu.com/52hack/blog/item/675119df980b401b62279809.html,2010.]