天天看點

uboot引導linux核心

1.統一uboot和linux的機器碼

u-boot和linux對應每一個開發闆都有一個機器碼(即:MACH_TYPE),隻有uboot跟linux的MACH_TYPE一樣才能成功引導核心。否則引導的時候就會提示MACH_TYPE不比對!

如下圖。

uboot引導linux核心

在上面的列印資訊中,uboot的MACH_TYPE為SMDK2440 0000016a,而linux的MACH_TYPE為SMDK2410 00000c1,兩者不一樣導緻引導失敗。

(1)uboot的MACH_TYPE

uboot的MACH_TYPE定義在:include/asm/mach-types.h

uboot引導linux核心

引用在:board/fl2440/fl2440.c 的int board_init (void)函數中

uboot引導linux核心

如果是MACH_TYPE_SMDK2410則改為MACH_TYPE_SMDK2440即可。

(2)linux的MACH_TYPE

linux的MACH_TYPE定義在:arch/arm/tools/mach-types

uboot引導linux核心

引用在:arch/arm/mach-s3c2440/mach-smdk2440.c

uboot引導linux核心

如果是SMDK2410則改成SMDK2440即可。

除此之外,linux的入口代碼出也要修改:arch/arm/kernel/head.S

uboot引導linux核心

當uboot和linux的MACH_TYPE都改為SMDK 10008之後,就可以成功引導了。 

2. 通過J-link Commander把uboot.bin燒寫進SDRAM并運作

*要把uboot.bin下載下傳到SDRAM中運作,需要把uboot.bin中的SDRAM初始化注釋掉,在include/configs/fl2440.h中加入下面的宏定義。

uboot引導linux核心

(1)SDRAM的初始化

S3C2440内部隻有4k的RAM,而uboot.bin有幾百k,是以必須儲存到SDRAM中。RAM不需要初始化可以直接通路,而SDRAM需要程式進行初始化之後才能使用。是以,一般在RAM中先運作一段代碼對SDRAM進行初始化,然後在把uboot.bin下載下傳到SDRAM中運作。

(2) J-link Commander下載下傳運作

飛淩提供的SDRAM初始化程式是axf格式的2440Init.axf,是以直接用AXD加載代碼再點選運作即可。

如果SDRAM初始化程式是二進制檔案如2440Init.bin,那麼就啟動J-link Commander然後依次輸入下面指令進行操作:

speed 12000
loadbin d:\ 2440Init.bin 0
setpc 0
g
           

如果開發闆上本身自帶了一個bootloader已經初始化了SDRAM那麼,就不需要再次初始化。

通過上面幾種方式都可以初始化SDRAM,SDRAM初始化之後,就可以把uboot.bin下載下傳到SDRAM運作了,依次輸入下面指令進行操作:

h
loadbin d:\uboot.bin 0x33f80000
setpc 0x33f80000
g
           

3.uboot格式的核心映像uImage制作

uboot編譯完成後在tools/目錄下會有一個mkimage可執行程式,uImage就是通過這個程式生成的。

mkimage用法如下所示:

mkimage [-x] -A arch -O os -T type -C comp-a addr -e ep -n name -d data_file[:data_file...] image

(用[]括起來表示該項可選可不選)

選項參數:

-A:setarchitecture to 'arch'       //用于指定CPU類型,比如ARM

-O:set operatingsystem to 'os'     //用于指定作業系統,比如Linux

-T:set imagetype to 'type'         //用于指定image類型,比如Kernel

-C:setcompression type 'comp'      //指定壓縮類型

-a:set loadaddress to 'addr' (hex) //指定image的載入位址

-e:set entrypoint to 'ep' (hex)    //核心的入口位址,一般為image的載入位址+0x40(資訊頭的大小)

-n:set imagename to 'name'         //image在頭結構中的命名

-d:use imagedata from 'datafile'   //無頭資訊的image檔案名

-x:set XIP(execute in place)       //設定執行位置

這樣制作出來的uImage比zImage多了64個位元組,這64個位元組包含了核心的重要資訊。

示例如下:

mkimage -n 'linux-2.6.28.7' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage uImage
           

或者

mkimage -n 'linux-2.6.28.7' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage uImage
           

這兩者的入口位址-e相差了64個位元組,核心下載下傳到記憶體中的位置也是不一樣的,如果下載下傳的位置不對,則不能成功引導核心,導緻列印停在starting kernel …

*三個位址的概念:

核心載入位址:制作uImage的時候-a的參數,記作:load address。

核心入口位址:制作uImage的時候-e的參數,記作:entryaddress。

引導位址:bootm的參數,也就是下載下傳核心到記憶體中的起始位址,記作:bootmaddress。

(a)當bootm address =load address的時候,uboot直接跳轉到entryaddress執行而不會跳過前64個位元組的檔案頭,這種情況下制作uImage的時候必須滿足,entry address= loadaddress+0x40,否則引導不能成功。

(b)當bootm address!= load address的時候(注意bootm address加上核心大小不能覆寫掉load address),uboot會把除了uImage前64位元組檔案頭的其他部分複制到bootm address,再運作,這種情況下,制作uImage的時候entry address和load address可以相等。

4.通過nfs把核心映像uImage下載下傳到開發闆中運作

(1)nfs下載下傳可能會遇到的問題。

如果下載下傳的時候列印Loading:TTT然後失敗,很有可能是延時時間不夠引起的,需要修改:net/nfs.c

uboot引導linux核心

如果列印cannot umount那麼修改:net/nfs.c

uboot引導linux核心

(2)下載下傳

a.用交叉網線連接配接開發闆和電腦,網線不可過長,1米以内最好。在uboot指令行下輸入指令:dhcp。

b.在主機中安裝并配置好nfs server,然後啟動nfs server,下面是啟動的腳本。

#!/bin/sh
iptables -F
setenforce 0
        echo "iptables disabled!"
        echo "selinux disabled!"
systemctl start rpcbind.service
systemctl start nfs.service
        echo "rpcbind start!"
        echo "nfs start!"
           

c.下載下傳到記憶體

nfs 0x30008000 192.168.1.17:/home/zhw123/linux_Image/uImage
(如果load address=entry address,請用:
nfs 0x31000000 192.168.1.17:/home/zhw123/linux_Image/uImage )
           
uboot引導linux核心

設定bootargs,輸入指令:

setenv bootargs console=ttySAC0,115200 noinitrd root=/dev/nfs rw nfsroot=192.168.1.17:/home/zhw123/busybox/busybox-1.7.4/myrootfs1 ip=192.168.1.10:192.168.1.17:192.168.1.1:255.255.255.0::eth0:off  
           

然後,輸入

bootm 0x30008000
           

引導核心,(如果load address=entry address,請用:bootm 0x31000000 )

如下圖所示,核心被引導成功!

uboot引導linux核心

5.核心引導失敗解決

uboot引導linux核心

如果核心引導後列印資訊停在startingkernel . . .。

經過調試分析,有三種情況會導緻這個結果

a.三個位址的關系不對,見上面三個位址的關系。

b. 在include/configs/fl2440.h中添加宏定義:

#define CONFIG_SETUP_MEMORY_TAGS  1        /* 向核心傳遞記憶體分布資訊 */  
#define CONFIG_CMDLINE_TAG        1        /* 向核心傳遞指令行參數 */
           

c. 修改arch/arm/cpu/arm920t/cpu.c中的int cleanup_before_linux (void)函數:

注釋掉:icache_disable();//即不禁止指令cache。

uboot引導linux核心

經過調試發現icache不能被禁止,否則會出現int cleanup_before_linux(void)函數調用後傳回不到主函數,導緻核心不能引導!比如在arch/arm/lib/bootm.c的do_bootm_linux函數加入列印資訊:

uboot引導linux核心

發現,隻能列印出clean_before_linux而不會列印出ready_boot_linux。進一步在cleanup_before_linux函數中加入列印資訊發現,cleanup_before_linux确實執行完成并傳回,但是并沒有正确的傳回到調用它的主函數中!

uboot引導linux核心

列印資訊在這裡停止了,核心已經啟動,但是無列印資訊。很明顯是控制台的參數設定不正确引起的,确認linux的調試序列槽号和波特率,注意有些可能是ttyS0而有些可能是ttySAC0。

繼續閱讀