馮林琳,耿恒山
(河北工業(yè)大學(xué)計(jì)算機(jī)科學(xué)與軟件學(xué)院,天津 300401)
本文采用的S3C6410芯片是基于ARM11架構(gòu)的16/32位RISC微處理器。它采用ARMv6指令集,支持從 SD Card、NOR Flash、NAND Flash 和 One-NAND Flash中引導(dǎo)系統(tǒng),是一個(gè)低成本、低功耗、高性能的應(yīng)用處理器解決方案。開(kāi)發(fā)板主要硬件資源見(jiàn)表1。
表1 開(kāi)發(fā)板主要硬件資源
本文使用 Kubuntu 12.04作為編譯系統(tǒng),采用arm-linux-gcc-4.7.0工具鏈作為編譯器。開(kāi)發(fā)板與目標(biāo)機(jī)通過(guò)串口和網(wǎng)口鏈接,并使用Jlink V8仿真器進(jìn)行調(diào)試和下載。
BootLoader是嵌入式設(shè)備上電后執(zhí)行的第一段程序,負(fù)責(zé)初始化硬件設(shè)備、建立內(nèi)存空間映射圖,引導(dǎo)嵌入式操作系統(tǒng)內(nèi)核,其功能同X86體系結(jié)構(gòu)中BIOS基本相同。BootLoader通常使用SD Card、NOR Flash和NAND Flash啟動(dòng)。目前,常用的BootLoader主要為vivi和Uboot,其中Uboot又占據(jù)了絕大部分份額。
Uboot為德國(guó)DENX小組開(kāi)發(fā)的嵌入式通用BootLoader。它支持 ARM、MIPS、XScale等多種體系結(jié)構(gòu),并支持引導(dǎo)Linux、VxWorks、NETBSD等多種操作系統(tǒng)。本文采用Uboot-2012-4版本。
Uboot共有18個(gè)目錄,按層次和調(diào)用關(guān)系如圖1所示。
圖1 UBoot源代碼層次和調(diào)用關(guān)系
Uboot新版本相對(duì)之前的舊版本,層次結(jié)構(gòu)和調(diào)用關(guān)系更加清晰,對(duì)于移植新平臺(tái)非常有利,降低了移植的難度和時(shí)間。
Uboot的啟動(dòng)分為兩個(gè)階段。第一階段主要為匯編代碼,涉及 cpu/arm1176/start.s,board/開(kāi)發(fā)板目錄/lowlevel_init.S 和 arch/arm/lib/board.c 中的 borad_init_f函數(shù)。完成如下工作:
(1)設(shè)置CPU為SVC模式,關(guān)中斷,關(guān)看門(mén)狗,關(guān)MMU;
(2)設(shè)置時(shí)鐘,初始化各硬件控制器;
(3)設(shè)置堆棧;
(4)復(fù)制(重定位)Uboot到內(nèi)存中;
(5)跳轉(zhuǎn)到第二階段代碼入口。
第一階段流程圖如圖2所示。
圖2 第一階段流程圖
因?yàn)樵诘谝浑A段已經(jīng)設(shè)置好堆棧,所以從第二階段開(kāi)始使用C語(yǔ)言實(shí)現(xiàn)。在arch/arm/lib/board.c的borad_init_r函數(shù)中uboot繼續(xù)初始化各硬件資源,如串口、網(wǎng)卡、NAND Flash等。然后跳轉(zhuǎn)至死循環(huán)common/main.c中的main_loop函數(shù),啟動(dòng)Linux內(nèi)核或等待用戶(hù)輸入命令。
針對(duì)本文采用的開(kāi)發(fā)板,使用與其硬件資源相近并且Uboot已經(jīng)支持的SMDK6400開(kāi)發(fā)板實(shí)現(xiàn)移植。本開(kāi)發(fā)板沒(méi)有配置NOR Flash,因此要實(shí)現(xiàn)從NAND Flash中啟動(dòng)UBoot。
(1)在boardsamsung下,新建文件夾S3C6410。將SMDK6400目錄下所有文件拷貝到S3C6410中,重命名 smdk6400.c和 smdk6400_nand_spl.c為s3c6410.c和 s3c6410_nand_spl.c,修改 Makefile 中COBJS-y:=smdk6400.o 為 COBJS-y:=s3c6410.o。
(2)在nand_sploardsamsung下,新建文件夾s3c6410,拷貝smdk6400目錄下所有文件到s3c6410中。重命名smdk6400_nand_spl.c為s3c6410_nand_spl.c,修改 makefile中 smdk6400 字段為 s3c6410。
(3)在includeconfigs目錄下,拷貝 smdk6400.h并重命名為s3c6410.h。
(4)修改根目錄下的makefile,依據(jù)smdk6400添加s3c6410編譯規(guī)則。
ARM體系結(jié)構(gòu)的微處理器上電后從地址0x0開(kāi)始執(zhí)行第一條代碼。隨著時(shí)代的發(fā)展,NAND Flash憑借容量大、速度快、價(jià)格低等優(yōu)點(diǎn)逐漸取代NOR Flash。許多嵌入式平臺(tái)上已經(jīng)不再配備N(xiāo)OR Flash。
NOR Flash可以按地址讀取,NAND Flash只能按頁(yè)讀取,因此不能直接從NAND Flash中啟動(dòng)Uboot。當(dāng)S3C6410芯片配置成從NAND Flash啟動(dòng)模式時(shí),系統(tǒng)上電后通過(guò)NAND Flash控制器自動(dòng)讀取NAND Flash中前4k內(nèi)容到S3C6410芯片內(nèi)部的stepping stone中,并將其映射到地址0x0開(kāi)始執(zhí)行。所以,如果S3C6410要從NAND Flash中啟動(dòng),就必須在程序前4k代碼中將完整的Uboot從NAND Flash中復(fù)制到內(nèi)存,然后跳轉(zhuǎn)到內(nèi)存中相應(yīng)繼續(xù)執(zhí)行,完成啟動(dòng)過(guò)程。
從NAND Flash啟動(dòng)的Uboot由兩部分組成:前4k uboot_nand_spl文件和正常Uboot文件。它們順序相接,中間沒(méi)有空隙。宏 CONFIG_NAND_SPL是uboot_nand_spl的編譯開(kāi)關(guān)。當(dāng)編譯uboot_nand_spl時(shí),第一階段將由s3c6410_nand_spl.c中board_init_f函數(shù)替換board.c中的 board_init_f函數(shù)。此處的board_init_f不設(shè)置堆棧直接跳轉(zhuǎn)回start.S,然后再?gòu)膕tart.s跳轉(zhuǎn)至 nand_spl and_boot.c 中的 nand_boot函數(shù)。nand_boot函數(shù)負(fù)責(zé)將NAND Flash中4k之后正常的Uboot復(fù)制到內(nèi)存中,并跳轉(zhuǎn)到內(nèi)存中相應(yīng)位置繼續(xù)執(zhí)行。
nand_boot函數(shù)用C語(yǔ)言實(shí)現(xiàn),但第一階段的board_init_f沒(méi)有設(shè)置堆棧,所以這里使用的堆棧應(yīng)該是s3c6410內(nèi)部的IRAM(地址為0x0c00_0000~0x0fff_ffff,實(shí)際使用只有4k)。
將 start.s中的
此時(shí)sp指向S3C6410內(nèi)部的IRAM。
在uboot-2012-4版本中,已經(jīng)實(shí)現(xiàn)對(duì)DM9000A網(wǎng)卡的支持,在此只需正確配置網(wǎng)卡信息,即可完成網(wǎng)卡驅(qū)動(dòng)的移植。
開(kāi)發(fā)板的所有硬件資源配置信息在include/configs/s3c6410.h中。本開(kāi)發(fā)板使用的DM9000A網(wǎng)卡連接至S3c6410芯片的Bank0,地址為0x18000300,DM9000A。修改 s3c6410.h,添加以下 DM9000A網(wǎng)卡配置信息:
刪除以下cs8900網(wǎng)卡配置信息:
本文使用的開(kāi)發(fā)板為256MB內(nèi)存,需修改內(nèi)存配置信息:
在Uboot根目錄下執(zhí)行make s3c6410_config,生成編譯配置文件,再執(zhí)行make編譯Uboot鏡像。根目錄生成的u-boot.bin鏡像可在內(nèi)存和NOR Flash中啟動(dòng),u-boot-nand.bin鏡像可在NAND Flash中啟動(dòng)。
NAND Flash無(wú)法直接使用Jlink燒寫(xiě),本文通過(guò)Uboot自身功能實(shí)現(xiàn)NAND Flash的燒寫(xiě)。
使用Jlink把u-boot.bin和 u-boot-nand.bin下載到開(kāi)發(fā)板內(nèi)存中0x50000000和0x50100000處,運(yùn)行u-boot.bin。此時(shí) Uboot由內(nèi)存中啟動(dòng)。執(zhí)行 Uboot的nand erase 0x0 64000擦除NAND Flash最前面400kB空間,執(zhí)行 nand write 0x50100000 0x0 64000將u-boot-nand.bin燒寫(xiě)到NAND Flash。復(fù)位開(kāi)發(fā)板實(shí)現(xiàn)從NAND Flash中啟動(dòng)Uboot。
BootLoader是嵌入式開(kāi)發(fā)極其重要的一環(huán),本文在分析Uboot原理后,結(jié)合最新Uboot源代碼和編譯環(huán)境,在 S3C6410開(kāi)發(fā)板上移植成功,并實(shí)現(xiàn)了NAND Flash啟動(dòng)和網(wǎng)絡(luò)通信等功能。本方法為S3C6410后續(xù)開(kāi)發(fā)奠定了基礎(chǔ),并對(duì)其它開(kāi)發(fā)板的Uboot移植工作提供了一定的參考價(jià)值。
[1]田澤.嵌入式系統(tǒng)開(kāi)發(fā)與應(yīng)用[M].北京:北京航空航天大學(xué)出版社,2005:134-349.
[2]陳文智,王總輝.嵌入式系統(tǒng)原理與設(shè)計(jì)[M].北京:清華大學(xué)出版社,2011:53-178.
[3]陳賾.ARM嵌入式技術(shù)原理與應(yīng)用[M].北京:北京航空航天大學(xué)出版社,2011:127-183.
[4]Sumsuang Electronics.S3C6410x User’s Manual[Z].Sumsuang Electronics,2008:60-245.
[5]Sumsuang Electronics.K9F2G08UXA Datasheet[Z].Sumsuang Electronics,2007:2-44
[6]Davicom Semiconductor.DM9000A Datasheet[Z].Davicom Semiconductor,2006:6-52.
[7]Sumsuang Electronics.S3C6410x Application Note(Internal ROM Booting)[Z].Sumsuang Electronics,2008:5-19.
[8]廣州友善之臂計(jì)算機(jī)科技有限公司.Tiny6410硬件說(shuō)明手冊(cè)[Z].廣州友善之臂計(jì)算機(jī)科技有限公司,2011:5-26.
[9][美]Daniel W Levis.嵌入式軟件基礎(chǔ)—C語(yǔ)言與匯編的整合[M].陳宗斌譯.北京:高等教育出版社,2005:182-194.
[10]劉凱.ARM嵌入式接口技術(shù)應(yīng)用[M].北京:清華大學(xué)出版社,2009:78-157.
[11]劉峰.ARM匯編語(yǔ)言[M].成都:電子科技大學(xué)出版社,2010:10-63.
[12]DENX.U-Boot Source Code[DB/OL].http://www.denx.de/wiki/U-Boot/SourceCode,2012-08-15
[13]DENX.The DENX U-Boot and Linux Guide(DULG)for canyonlands[DB/OL]. http://www.denx.de/wiki/DULG/Manual,2012-08-15.
[14]DENX.The Universal Boot Loader(“Das U-Boot”)[DB/OL].http://www.denx.de/wiki/U-Bootdoc/Presentation,2012-08-15.