U-boot
源代碼下載:ftp://ftp.denx.de/pub/u-boot/
啟動過程分析:1.小于8Kb的程序:IROM從nand讀8K數據到ISRAM中運行;
2.大于8kb程序(主要指u-boot):IROM從nand讀前8k數據到SRAM中主要做兩件事:
第一:初始化DRAM;
第二:將剩下的代碼搬運到DRAM運行。
3.在DRAM中就可以引導系統啟動了。
BL0:IROM,出廠已固化代碼
BL1:ISRAM的前16kb,u-boot-spl.bin
BL2:ISRAM的后80kb,u-boot.bin
ISRAM是內置內存,不用初始化就可以使用;
DRAM是外接內存,需要初始化才能使用。
uboot有兩種模式:
1.啟動加載模式:存儲在nand上,上電將操作系統加載到DRAM運行。正常啟動時的模式,自動加載linux內核。
2.下載模式:調試模式,通過網絡或串口從主機獲得文件,控制啟動流程。按下任意鍵進入下載模式。
bootloader有兩個階段:
1.第一階段代碼用匯編:arch/arm/cpu/armv7/start.S和board/samsung/smart210/lowlevel_init.S,從ISRAM運行。
第一:建立中斷向量表和異常向量表
第二:獲取啟動參數,設置SVC32模式,拷貝前8k代碼到ISRAM。
第三:cpu_init_crit:
關I/D cache,關看門狗,清TLB,關MMU等
第四:cpu_init_crit調用lowlevel_init.S:
設置TCPZ,禁止中斷,初始化系統時鐘、內存、串口、nand等
第五:設置棧,判斷啟動開關,sd卡啟動就跳轉到board_init_f,nand啟動就跳轉到board_init_f_nand。
第六:搬運代碼,從sd卡或nand到DRAM(內存)。
第七:初始化棧,清bss段,跳轉到board_init_r,完了啟動過程結束。
2.第二階段代碼用c:arch/arm/lib/board.c和common/main.c,從內存運行。
board_init_f:
為gd數據結構分配地址并清零;
執行init_fnc_ptr函數指針數組中的各個初始化函數;
分配DRAM高64kb為TLB,用于uboot;
分配DRAM下一個單元為uboot代碼段,數據段,bss段;
開辟malloc空間存放bd,gd,3個字大小的異常堆空間;
將relocate地址傳給gd結構體變量,用于返回start.S。
board_init_r:在內存中運行
對gd,bd數據結構賦值初始化;
各種外設初始化;
進入main_loop,(main_loop函數在common/main.c中定義,進入main.c)
common/main.c:引導內核
u-boot源代碼支持一部分官方的評估開發板,不需要修改u-boot。由于我們用的cpu和官方的測試版的cpu相同,所以cpu部分u-boot不需要修改,其他部分需要修改。SMDK指三星的評估板
移植關心的文件夾:
board文件夾 :和開發板相關的,是移植需要修改的。
arch/arm/文件夾 :和處理器相關的,主流的cpu都是支持的.
lib文件夾 :u-boot的通用的自己的庫。
arch/arm/lib文件夾 :根據arm處理器創建的庫。
include/configs文件夾:里面是頭文件,需要修改。
drivers文件夾 :驅動文件夾.
common文件夾 :u-boot核心代碼。
net文件夾 :網絡協議相關代碼。
tools文件夾 :u-boot提供的編譯運行等輔助工具。
1.u-boot啟動過程:
start.S :arch/arm/cpu/armv7/start.S,程序的入口;
board.c :arch/arm/lib/board.c,不用修改,可以用于所有arm;
main.c :common/main.c,與硬件無關,不用修改,所有開發板通用,用來啟動內核。
arch/arm/cpu/armv7/start.S調用board/samsung/smart210/lowlevel_init.s進行初始化(主要初始化內存DRAM)。
arch/arm/lib/board.c初始化和硬件相關的函數,調用相關的初始化函數進行初始化開發板上資源。
common/main.c是整個u-boot程序的主函數,主要負責運行維護uboot的shell命令行。
2.添加和開發板相關的程序和頭文件
在boart/sumsung/下面新建一個文件夾smart210
參考board/sumsung/smdkv210文件夾中的文件修改成smart210可用文件。
第一、修改arch/arm/cpu/armv7/start.S
#include
#include
#include
定義代碼段的鏈接地址
.globl _TEXT_BASE
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
定義當前程序的開始地址,一般是在DRAM中
.globl _armboot_start
_armboot_start:
.word _start
#endif
第二、修改board/samsung/smart210/lowlevel_init.S
#include
#include "smart210_val.h"
第二、修改和開發板相關的代碼
board/sumsung/smart210/smart210.c
參看smdkc100,主要進行一些cpu控制器和資源的初始化工作。
#include
include/s5pc110.h包含下面兩個
include/s5pc110.h
arch/arm/include/asm/arch/hardware.h(arch是arch-s5pc1xx的鏈接)
第四、include/configs/smart210.h
配置文件,添加需要的宏定義。
#defineCONFIG_SAMSUNG 1
#define CONFIG_S5P 1
#define CONFIG_S5PC110 1
#define CONFIG_SMART210 1
#define CONFIG_MACH_TYPE MACH_TYPE_SMART210
#define CONFIG_SYS_TEXT_BASE 0x23E00000 //定義代碼段的鏈接地址
#defineMACH_TYPE_SMART210 3466
配合文件中主要有另類宏:
1.CONFIG_開頭的用于cpu、soc、board等的時鐘設置、設備驅動等。
2.CFG_開頭的用于malloc緩沖池的大小、uboot提示符、uboot下載文件時的默認地址、flash的其實地址等。
3.uboot的配置和編譯:
添加目標板的信息到/boards.cfg:
# Target ARCH CPU Boardname Vendor SoC Options
webee210 arm armv7 webee210 samsung s5pc1xx
make distclean #清除之前編譯結果
make clean
修改/Makefile文件:
unconfig:
@rm -f $(obj)include/config.h $(obj)include/config.mk \
$(obj)board*/config.tmp \
$(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep \
$(obj)board/$(VENDOR)/$(BOARD)/config.mk
smart210_config: unconfig
@$(MKCONFIG) $(@:_config=) arm armv7 smart210samsung s5pc1xx
@echo"TEXT_BASE = 0xc3e00000" >$(obj)board/samsung/smart210/config.mk
make smart210_config
$(@:_config=)表示$@這個目標的_config換成空,得到開發板名稱smart210.
執行make smart210_config實際上調用uboot根目錄下mkconfig(注意這個腳本的權限)這個shell腳本,該腳本將開發板六個信息寫入include/config.mk文件和include/config.h文件中.
include/config.mk:
ARCH = arm
CPU =armv7
BOARD = smart210
VENDOR = samsung
SOC =s5pc1xx
OPTIONS =
include/config.h:
#define CONFIG_BOARDDIR board/samsung/smart210
#include
#include
#include
#include
修改board/sumsung/smart210/Makefile
因為在這個文件夾添加了開發板相關的程序,所有需要修改相應的Makefile文件。
參考smdk2410的Makefile
COBJS :=smart210.o
arch/arm/config.mk已經配置好交叉編譯:
CROSS_COMPILE ?= arm-linux-
arch/arm/cpu/armv7/u-boot.lds定義了起始地址和入口函數:
. =0x00000000;
. = ALIGN(4);
.text :
{
arch/arm/cpu/armv7/start.o (.text)
*(.text)
}
include/configs/smart210.h定義了定義了TEXT_BASE:
#defineCONFIG_SYS_TEXT_BASE 0x23E00000
make
執行/Makefile文件,完成了uboot的編譯。
生成以下的文件:
u-boot.bin:二進制可執行文件可以直接燒寫
u-boot.elf:elf格式的可執行文件
u-boot.srec:motorolas-record格式的可執行文件
u-boot.lds
u-boot.map
4.燒寫uboot到開發板的nand有兩種方法:
第一、先燒寫到SD卡,
注意手冊給的sd卡的分區:(512b為一個block)
512b(保留區,0block)+8kb(BL1,1-16block)+16Kb(EN環境變量,17-48block)+512kb(BL2,也就是u-boot.bin,從49block開始)+linux內核+根文件系統
cat /proc/partitions #找出SD卡對應的設備,一般為/dev/sdb
dmesg | tail
sudo dd bs=512 if=/dev/zero of=/dev/sdbcount=2400
sudo dd bs=512 iflag=dsync oflag=dsync if=spl/smart210-spl.binof=/dev/sdb seek=1
sudo dd ba=512 iflag=dsync oflay=dsyncif=smart210-uboot.bin of=/dev/sdb seek=49
再使用uboot命令,燒寫到nand:
tftp 21000000 smart210-uboot.bin
nand erase.chip
nand write 21000000 0 3c1f4
第二、使用jtag直接燒寫到nand中
5.uboot常用命令:
bdinfo:打印目標板配置信息
flinfo:獲取可用的flash信息
help:打印幫助信息
base:打印或設置地址偏移
crc:crc32的校驗和計算,用于計算某一段存儲區的校驗和。
cmp:測試兩個存儲器區域是否相同。
cp:拷貝存儲區。
md:存儲區顯示,顯示某些區域的值。
mm:存儲區修改,修改累加地址的值。
mtest:存儲區測試,測試寫操作是夠成功,只能測試rom。
mw:內存填充,
nm:內存修改,修改同一地址的值。
era:擦除flash存儲器某個區域
erase all:擦除整個存儲器
protect:使能或禁止flash保護功能,更改某一區域的只讀屬性。
bootm:從存數器啟動應用程序鏡像
go:開始某地址處的應用程序。
loadb:經由串口線加載二進制文件(kermit模式)
tftpboot:使用tftp協議由網絡加載映像文件
printenv:打印環境變量,ipaddr,hostname,netmask。
setenv:設置環境變量
saveenv:保存環境變量到存儲器(sd和nand)
bootm工作原理:
用于啟動操作系統鏡像,從鏡像頭獲取操作系統類型,所使用的文件壓縮方法,加載和入口點地址等信息。加載鏡像文件到指定的存儲器,甚至解壓。也可以傳遞要求的啟動參數并在入口點啟動操作系統。第一個參數是待加載的映像的存儲地址,之后可以添加操作系統需要的參數。
bootm用于linux操作系統:
傳遞一個可選的參數,作為initrd ramdisk映像的起始地址,bootm命令有三個步驟組成:
1.linux內核映像被解壓縮并拷貝到DRAM
2.ramdisk映像被加載到DRAM
3.控制權交給linux內核,并傳遞ramdisk映像的位置和大小信息。
5.怎樣用u-boot來啟動linux內核(前提是內核已經燒寫到nand)
nand read 讀入的內存目的地址 讀入的nand的地址 讀入的大小
bootm 內核的入口地址
|