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