《電子技術應用》
您所在的位置:首頁 > 嵌入式技術 > 設計應用 > Uboot在S3C2440上的移植
Uboot在S3C2440上的移植
來源:微型機與應用2010年第24期
盧 偉, 潘 煉
(武漢科技大學 信息科學與工程學院自動化系,湖北 武漢434200)
摘要: 通過分析Uboot的文件結構及其啟動流程,詳細給出了Uboot在基于ARM920T開發板上的移植方案,包括編譯、調試全過程,最終能夠在Uboot命令方式下加載映像文件,完成Linux內核與yaffs映像文件的調試,具有Bootloader移植的通用性。
Abstract:
Key words :

摘   要: 通過分析Uboot的文件結構及其啟動流程,詳細給出了Uboot在基于ARM920T開發板上的移植方案,包括編譯、調試全過程,最終能夠在Uboot命令方式下加載映像文件,完成Linux內核與yaffs映像文件的調試,具有Bootloader移植的通用性。
關鍵詞: Uboot; S3C2440; ARM920T; 引導過程; 啟動代碼

1 Uboot移植環境準備
1.1 移植平臺的硬件組成

 硬件平臺是ARM9的體系結構,ARM920T的CPU, SOC芯片是三星的S3C2440,支持Nand Flash與Nor Flash的可選啟動方式,其主要硬件資源如表1所示[1]。

 支持Nand Flash與Nor Flash啟動,可以通過跳線來選擇啟動方式。Nand Flash啟動時,最開始4 KB數據被硬拷貝到內部Boot Internal SRAM,且被映射到nGCS0的片選空間0x0000,0000—0x0800,0000;Nor Flash方式啟動時,它直接被映射到nGCS0的片選空間。所以,在Uboot移植時,要考慮將Uboot燒寫到Nor flash上還是Nand Flash上。
1.2 Uboot工作原理
    Uboot的整體結構如圖1所示。

  從圖1可以看出,這種分層結構的Uboot分模塊化了,給移植帶來了很大的方便。由于協議層與應用層是與目標硬件無關的,因此移植工作主要集中在物理層和驅動層上面的修改。而Uboot支持串口下載、網絡下載,并提供了很多交互式命令。整個Uboot編譯、連接過程如下:
  (1)創建編譯環境
    在MAKEFILE中會調用根目錄下的mkconfig文件,如下:
    MKCONFIG:= $(SRCTREE)/mkconfig
    qq2440v3_config:unconfig
     @$(MKCONFIG)$(@:_config=)arm ARM920T qq2440v3 NULL s3c24x0
    Mkconfig文件引用傳入的參數$1=qq2440v3、$2=arm、$3=arm920t、$4=qq2440v3、$5=NULL、$6=s3c24x0,流程如圖2所示。

    (2)編譯流程
  編譯流程如圖3所示。

    最終生成內存映像圖文件U-boot.map和可執行二進制映像elf文件U-boot[2],可以直接將生成的U-boot下載到SDRAM來單步調試。
2 Uboot的移植操作
2.1存儲器映射與存儲器重映射

    存儲器映射,實現了統一編址,方便了程序在32 bit尋址(4 GB尋址空間)的范圍內能夠尋址到任意的物理存儲區。
    S3C2440芯片不帶片內Flash,帶片內4  KB的SRAM,被映射到了0x4000_0000~0x4000_1000的地址空間,外部的SDRAM被映射到bank6,網卡被映射到bank3,Flash被映射到bank0。
    由于Uboot是上電后就運行,因此需要將代碼定位在Flash從0x0000_0000的上電入口處。為了提高系統加載速度并且實現在線編程功能,需要將整個Uboot從Flash中搬到RAM運行,即代碼從定位,將整個代碼定位到SDRAM的0x3300_0000之后,來作為其實際的運行地址,具體如圖4所示。

2.2 配置主機運行環境
    Uboot與Linux系統密切相關,筆者在RH Linux的虛擬機中搭建了整個運行環境,采用的是2.2.4的Linux內核,arm-linux-gcc-3.4.1的交叉編譯工具[3],需要在/root/.bashrc文件中做一下交叉編譯工具路徑的聲明,即加上如下一句:
     export PATH=$PATH:/usr/local/arm/3.4.1/bin
     保存并退出,在終端下輸入“arm-linux-gcc-version”并回車,如果能看到輸出版本信息為3.4.1,則代表路徑設置正確,交叉編譯工具鏈已經成功安裝。
2.3 修改CPU相關代碼
    在調試Uboot時,如果每次都將二進制映像燒錄到Flash中,不僅需要等待,而且操作麻煩,本文是在調試階段將二進制映像直接燒錄到外部存儲器SDRAM中,然后直接從該處運行,這樣直接在內存中運行,可以很方便地完成Uboot調試。
    Uboot啟動的第一階段,從.\cpu\arm920t\start.s開始執行,依次完成關閉看門狗、關閉中斷、設置CPU分頻比、初始化SDRAM、代碼重定位、設置堆棧,最后跳轉到C函數的入口點。當在SDRAM中調試時,內存的初始化已經預先完成了,因此不需要初始化SDRAM和代碼重定位的功能。
    在.\include\configs\qq2430.h添加宏定義define CONFIG_SKIP_LOWLEVEL_INIT,就會跳過cpu_init_crit處的初始化SDRAM函數,代碼如下所示:
    #ifndef CONFIG_SKIP_LOWLEVEL_INIT
    cpu_init_crit:
    …
    當Uboot在SDRAM中運行時,代碼的入口地址_start與代碼在SDRAM中重定位的地址_TEXT_BASE相同,直接跳轉到堆棧初始化處stack_setup,跳過了代碼的Flash到RAM的搬運。代碼如下所示:
      adr    r0, _start        
         ldr    r1, _TEXT_BASE    
         cmp r0, r1                 
         beq  stack_setup
2.4 添加平臺相關代碼
    從匯編跳轉到C程序的入口點start_armboot時,即位于./Lib_arm/Board.c中的start_armboot函數,通過函數初始化數組來依次完成CPU(cpu_init)、板級(board_init)、中斷(interrupt_init)、環境變量(env_init)、串口(serial_init)、波特率(init_buardrate)、顯示(disp_banner)、Flash初始化(nand_init),每個初始化后返回不為0的值,否則永遠在死循環中掛起,需要重新啟動開發板。
2.4.1 鎖相環時鐘的配置
    在smdk2410開發板的基礎上修改。在./board/qq2440v3下新建qq2440v3.c,并且將Uboot中的./board/smdk2410/smdk2410.c內容全部復制給qq2440v3.c。在include/configs下新建qq2440v3.h配置文件,同時將include/configs/smdk2410.h全部復制給qq2440v3.h。因為S3C2440與S3C2410的最高運行速率不一樣,系統時鐘設置也不一樣,即鎖相環配置有差異,因此內部總線的分頻比系數是不同的。S3C2440可運行于400 MHz,而S3C2410則是200 MHz,需要更改系統時鐘部分,使其增加對S3C2440的支持。
    鎖相環輸出的MPLL(fclk時鐘頻率寄存器)與UPLL(USB控制時鐘頻率寄存器)計算式如下:
    MPLL=(2*m*Fin)/(p*2^s)         /*鎖相環輸出fclk頻率
    UPLL=(m*Fin)/(p*2^s)      /*鎖相環輸出USB控制頻率
    m=M(the value for divider M)+8,p=P(the value for divider P)+2,s=S
    其中m、p、s為鎖相環的預置值,控制輸出頻率, Fin為晶振頻率12 MHz。通過下面的宏定義分別給M、P、S賦值0x5c、0x01、0x01就能輕松完成時鐘配置。
    #define S3C2440_MPLL_400 MHz ((0x5c<<12)|(0x01<<4)|(0x01))
    #define S3C2440_UPLL_48 MHz ((0x38<<12)|(0x02<<4)|(0x02))
    #define S3C2440_CLKDIV 0x05 /* FCLK:HCLK:PCLK= 1:4:8, UCLK = UPLL
2.4.2 串口的配置
    S3C2440帶有3個UART,用異步通用串口uart0與上位機通信。串口時鐘用pclk時鐘,即1/2 hclk時鐘,1/8 fclk時鐘(mpll時鐘),get_PCLK()函數返回pclk時鐘頻率。串口0工作于中斷模式,通過FIFO緩存收發,沒有校驗位,1位停止位,通過設置ULCON0寄存器與UFCON0來配置。為了提高數據傳送的可靠性,使用了錯誤接收中斷機制,能夠檢測溢出錯誤、奇偶校驗錯誤和幀錯誤,相關錯誤狀態保存在錯誤狀態寄存器UTRSTAT0的對應位中。
    串口的波特率用115 200 b/s,通過給波特率除數寄存器UBRDIV0賦值,能夠確定串行發送接收波特率。計算公式如下:
    UBRDIVn=(int) (UART clock/(buad rate*16))-1;
    其中UART clock為pclk時鐘,buard rate為115 200。
2.5 編譯并調試
    為了在內存中運行,先要把鏈接腳本文件./Board/qq2440v3/U-boot.lds中的程序初始化運行地址.=0x0000,0000改為.=0x3300,0000,以方便直接在RAM中運行。在終端控制臺中先進入Uboot的根目錄,然后執行命令make qq2440v3_config,通過make all來編譯和連接程序。編譯沒有錯誤的情況下,會在Uboot的根目錄下生成u-boot、u-boot.srec和u-boot.bin三個文件,分別對應于ELF格式、S-Record格式和二進制格式。
    直接使用JTAG燒寫二進制u-boot.bin到SDRAM的0x3300,0000處,燒寫完成之后,將pc的指針指向該處運行,會在串口終端上顯示板子的自檢信息,并給出提示符等待用戶輸入命令,如圖5所示。

3 Uboot從Flash中啟動
  S3C2440既支持從Nor Flash中啟動,也支持從Nand Flash中啟動。Nor Flash的地址線與數據線分開,方便代碼存取且速度很快,上電復位時直接把Nor Flash映射到了0x0000,0000地址處。但是Nand Flash數據線與地址線復用,運行速度慢,為了提高Nand Flash啟動效率,S3C2440芯片加入了一個特殊機制,會在上電復位時,把Nand Flash前4 KB代碼硬拷貝到內部SRAM的4 KB空間,然后將SRAM的4 KB空間映射到0x0000,0000處,這樣直接在SRAM中啟動Uboot,節省了啟動時間。
3.1 從Nor Flash中運行
3.1.1添加Nor Flash驅動

 board/qq2440v3/Flash.c中的驅動只支持Nor Flash的AMDLV400和AMDLV800兩種芯片,不支持本文板子上的AM29LV160,更不支持Nand Flash,只能用CFI標準接口連接,在/drivers/cfiflash.c中定義了該接口標準下的讀寫函數的具體實現。要調用該驅動,應在配置頭文件/include/configs/qq2440v3.h中添加CFI的宏定義:
    #define CFG_FLASH_CFI_DRIVER 1
    并在board/qq2440v3/Makefile中去掉原來的Nor flash驅動的編譯,即:
    COBJS:= qq2440v3.o flash.o 變量中去掉flash.o的連接。
3.1.2 SDRam初始化并實現代碼從定位
    Uboot在Nor Flash中啟動后,在start.s階段除了要完成必要的寄存器設置外,還要完成SDRAM的初始化以及代碼從定位,即把Flash空間的Uboot映像搬運到SDRAM高地址空間中,然后在SDRAM中運行Uboot。可以直接從Nor Flash啟動Uboot,但從Nand Flash啟動要實現重定位,在這里就一起實現了。
    首先在.\include\configs\qq2430.h中去掉剛才添加宏定義define CONFIG_SKIP_LOWLEVEL_INIT,則會在start.s階段進入cpu_init_crit函數以完成I/D caches設置以及禁止MMU,隨后進入lowlevel_init完成內存寄存器組的設置,如SDRAM位寬、刷新率等的初始化工作。
    在.\include\configs\qq2430.h中去掉CONFIG_SKIP_
RELOCATE_UBOOT的宏定義,來完成整個代碼的重定位[5]。
     Uboot代碼區的長度為_bss_start-_armboot_start,其中_bss_start與_armboot_start變量保存的都是代碼段的起始地址與終止地址。_start+_bss_start-_armboot_start為代碼區結束的絕對地址,通過地址絕對尋址來復制代碼區的數據到內存中TEXT_BASE地址區域,其中TEXT_BASE在.\Board\QQ2440v3\Config.mk中被賦值,即TEXT_BASE=0x33000000,表示代碼重定位在SDRAM中的運行起始地址。
3.1.3 編譯并調試
    Uboot已經能夠成功在SDRAM中啟動運行了,為了能夠從Nor Flash中啟動,需要做如下工作。
    先要把鏈接腳本文件./Board/qq2440v3/U-boot.lds中的程序初始化運行地址.=0x3300,0000改為.=0x0000,0000,通過硬件開關選擇開機啟動方式為Nor Flash,完成Nor Flash映射到0地址處。然后在終端控制臺編譯連接,直到沒有錯誤。通過HJTAG燒錄進Nor Flash里面,開機運行后串口終端輸出界面如圖6所示。

3.2 從Nand Flash中運行
3.2.1添加Nand Flash驅動

    S3C2440支持從Nand Flash啟動,考慮到移植的通用性,對于沒有Nor Flash的板子,就需要從Nand Flash啟動。在.\drivers目錄下有兩種Nand的驅動,.\Nand和.\Nand_legacy兩種驅動可以選擇,其中.\Nand能夠自動識別很多型號的Nand Flash,并且是更新版本,因此選擇這種驅動。根據Nand.c中的
    #if(CONFIG_COMMANDS&CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
    #include <nand.h>
    條件編譯選擇Nand驅動,首先在板級配置頭文件qq2440v3.h中的宏定義CONFIG_COMMAND中添加CFG_CMD_NAND,并且不定義CFG_NAND_LEGACY。在start_armboot()函數中會對外設逐一初始化,Nand初始化代碼如下:
    #ifdefined(CFG_MAX_NAND_DEVICE) nand_init;
    #endif
    需要在板級配置頭文件qq2440v3.h中宏定義CFG_MAX_NAND_DEVICE,因為smdk2410開發板不支持Nand Flash,因此需要自己來編寫Nand Flash驅動函數board_nand_init來被nand_init以及nand_init_chip調用,以完成Nand Flash的硬件初始化,包括使能Nand Flash控制器、初始化ECC、使能片選信號、設置時序等。
3.2.2添加cmd命令
    為了豐富Nand與網卡功能,還需要在配置文件中添加Nand與網卡相關命令來調用相關函數。在板級配置頭文件qq2440v3.h中的CONFIG_COMMANDS宏定義中以邏輯“或”的形式添加CFG_CMD_NAND與CFG_CMD_NET,這樣便可以通過命令方式實現Nand Flash的讀寫以及網絡下載功能。
    Uboot的網絡功能很強大,可以方便地通過TFTP引導或者是NFS引導內核映像或者文件系統到SDRAM,然后直接go到此處執行,在SDRAM中調試完成后,再將映像文件燒錄到Flash中,不僅調試方便,而且還節省下載時間。
3.2.3 編譯并調試
    編譯過程跟Nor Flash啟動一樣,最后串口輸出信息如圖7所示。

    此時,整個Uboot的移植就算完成了,由于支持串口跟網卡驅動,可以很方便地用這個Uboot來通過網卡下載內核映像與文件系統到Flash,通過串口輸出信息調試Uboot。
4 Uboot引導Linux內核
4.1 內核啟動參數的傳遞

    Uboot在引導內核啟動時,通過標記列表的方式向內核傳遞啟動參數。這些啟動參數預先以環境變量的方式保存在Flash中,在./Lib_arm/Board.c中的初始化環境變量函數env_init()初始化,下面的函數來實現向kernel跳轉。
    theKernel (0, bd->bi_arch_number, bd->bi_boot_params); thekernel其實不是個函數,而是指向內核入口地址的指針,為0x30008000。這里把它強行轉化為帶三個參數的函數指針,會把三個參數保存到通用寄存器中,實現了向kernel傳遞信息的功能,R0賦值為0,R1賦值為機器號,R2賦值為啟動參數數據結構的首地址[6]。
   標記列表實際上是內存中的結構體組成的列表,在./Lib_arm/Armlinux.c中函數setup_start_tag()來創建標記列表。
4.2 tftp加載內核映像
 對于已經編譯好了的內核映像文件zImage,其格式是ELF的可執行文件,首先要把它轉化成U-boot格式的文件uImage,實際是添加了一個header定義,直接用tools目錄下的工具mkimage就可用實現,具體在終端中執行如下操作:
    ①arm-linux-objcopy -O binary -R .note -R .comment -S vmlinux linux.bin
  ②gzip -9 linux.bin
    ③mkimage -A arm -O linux -T kernel -C gzip -a 0x30008000 -e 0x30008040 -n "Linux Kernel Image" -d linux.bin.gz uImage
    先從內核文件中提取二進制文件,然后壓縮,最后構造文件頭信息,包括名稱、大小、類型、CRC校驗碼等,添加的頭信息占用0x40大小空間。完成后下載內核映像uImage,如下操作:
    開啟主機tftp服務,將uImage放置tftp目錄下,然后啟動Uboot,運行tftp下載,镲除、燒寫Nand Flash,具體如圖8所示。

    最后燒寫文件系統映像,與燒寫內核映像一樣,先tftp下載到內存,然后再燒寫,不同類型的文件系統nand燒寫命令不一樣,本文用到的是yaffs文件類型,則通過Nand write.yaffs 0x30000000 0x1d0000 $(filesize)命令來燒寫。
    本文研究了Uboot在基于S3C2440系統上的移植,并且提出了可行性方案,通過邊搭建硬件環境邊調試Uboot,使Uboot在嵌入式系統板上正常運行,實現了串口通信、網口下載、Flash燒錄等功能,并且成功引導了Linux系統,為后續的系統驅動程序開發奠定了基礎,使得Uboot的移植具有開發的通用性。

參考文獻
[1]  劉淼.嵌入式系統接口設計與Linux驅動程序開發[M]. 北京:北京航空航天大學出版社,2006.
[2] YAGHMOUR K. Building embedded Linux system[M]. [S.l.]:O’Reilly,2004.
[3] HENKEL J, XIAOBO SHARON HU, SHUVRA S. BHATTACHARYYA. Taking on the embedded system design challenge[J].IEEE Computer,2003,5(4):35-37.
[4] SD-Memory Card Specifications /Part1 Physical Layer  Specification Version 1.01[R]. [S.l.]:SD Group, 2001.
[5] SUMSUANG ELECTRONICS. S3C2410X User’s Manual[Z].Republic of Korea: Sumsang,2003.
[6] Configurations.Denx software engineering[EB/OL]. (2006-7-23)http://www.denx.de/wiki/DULG/Manual.

此內容為AET網站原創,未經授權禁止轉載。
主站蜘蛛池模板: 国产亚洲精品成人久久网站 | 日本免费人成黄页网观看视频 | 久久精品国产99久久久 | free性欧美hd另类精品 | 成人免费网站视频www | 亚洲中文字幕特级毛片 | 播放一级毛片 | 男女视频在线看 | 亚洲第一成年网站大全亚洲 | 亚洲天堂一区二区 | 在线毛片免费 | 午夜黄色福利视频 | 亚洲精品人成网线在线 | 日韩精品一区二区三区中文字幕 | 久久精品亚瑟全部免费观看 | 亚洲高清国产品国语在线观看 | 国内精品久久久久影院亚洲 | 精品午夜国产在线观看不卡 | 免费一区区三区四区 | 一区二区三区视频网站 | 亚洲一区二区三区高清视频 | 久久综合99re88久久爱 | 一级成人a毛片免费播放 | 久久久久久久久久久观看 | 一级片在线观看 | 亚洲香蕉影院 | 免费被黄网站在观看 | 日本欧美一区二区三区高清 | 久久久久国产 | 久久精品成人 | 成人爽a毛片在线视频网站 成人爽爽大片在线观看 | 亚洲男人的天堂成人 | 日本a级特黄三级三级三级 日本a一级片 | 精品视频网 | 亚洲性久久久影院 | 久久久久久久99精品免费观看 | 色伦网 | 好湿好紧好痛a级是免费视频 | 国内外成人免费在线视频 | 日韩毛片免费在线观看 | 美女视频很黄很a免费国产 美女视频黄.免费网址 |