分类: LINUX
2011-04-15 15:58:43
U-Boot系统移植
目的 |
制作一个引导程序可以初始化硬件设备、准备软件环境和调用操作系统(类似PC的Bios) |
参考:《嵌入式Linux应用开发完全手册》
1、硬件环境:
CPU |
S3C2440 |
|
SDRAM |
H57V2562GTR-60C |
64M |
NandFlash |
K9F2G08U0B |
256M |
NorFlash |
EN29LV160AB |
2M |
lCD |
天嵌4.3寸(TQ43) |
480*272 |
网卡 |
DM9000EP |
100M |
2、软件平台:
系统 |
Scientific Linux 版本6.0(Carbon) |
内核Linux 2.6.32-71.el6.i686 |
交叉编译工具 |
EABI4.3.3 |
|
源码 |
U-Boot1.1.6 |
|
3、源码解压后的目录:(红色平台依赖,绿色通用,黑色应用程序或工具和文档)
Board: |
U-boot支持的每个开发板的文件,都会以子目录的形式存放在 baord 目录下。 |
Common: |
存放U-Boot 支持的所有命令。无须大幅度修改,一般是加一些调试信息,打开或关闭一些宏。可增加自己的 u-boot 命令 |
Cpu: |
每个目录对应一个架构的cpu。 |
Disk: |
这是要对磁盘的支持。我们只移植 u-boot 的话,那这个对我们也没有意义。 |
Doc: |
参考文档的意思,这是最没用的,也是最有用的。 |
Driver: |
u-boot支持的所有的驱动代码。如果您需要添加自己的驱动代码,也可以放在这里。然后再 makefile 中加入相应的.o 文件名。 |
Dtt: |
数字温度测量器或传感器的驱动 |
Examples: |
可在U-Boot下运行的示例程序;如hello_world.c,timer.c; |
Fs: |
u-boot支持的文件系统。目前 已能支持包括cramfs、fat、fdos、jffs2 等。 |
Include: |
头文件以及对各种硬件平台的系统配置文件。对特定的开发板,都需要修改系统配置文件,它存放在 include 目录下的 configs 子目录中。 |
Lib_xxx: |
这是与体系结构相关的库文件。 |
Nand_spl: |
NAND存储器相关代码 |
Net: |
存放有关网络协议的实现的代码。比如 TFTP 协议的实现就在这里面。 |
Post: |
上电自检的目录。 |
Rtc: |
RTC驱动程序 |
Tools: |
生成 u-boot 的工具的目录。比如创建 bin 镜像文件等。 |
4、U-Boot的编译过程:
Stage1 |
#make distclean 清除之前编译产生的文件 |
Stage2 |
#make smdk2410_config |
分析过程,在toplevel Makefile |
smdk2410_config是Makefile的一个目标,定义如下: /******************************************************************************/ smdk2410_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0 unconfig: @rm -f $(obj)include/config.h $(obj)include/config.mk \ $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp /******************************************************************************/ 各项说明如下: arm: CPU的架构(ARCH) arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录 smdk2410: 开发板的型号(BOARD),对应于board/smdk2410目录 NULL: 开发者/或经销商(vender) s3c24x0: 片上系统(SOC)
/******************************************************************************/ MKCONFIG主要完成以下三个任务: 1、在include文件夹下建立相应的软连接 2、生成Makefile包含文件include/config.mk 3、生成include/config.h头文件 /******************************************************************************/ |
以下几步也在toplevel Makefile但不是分析编译过程 |
指定交叉编译器路径:改toplevel Makefile /******************************************************************************/ ifeq ($(ARCH),arm) #这里根据ARCH变量,指定编译器前缀。 CROSS_COMPILE = arm-linux- endif /******************************************************************************/ |
|
U-boot需要的目标文件: /******************************************************************************/ OBJS = cpu/$(CPU)/start.o # 顺序很重要,start.o必须放第一位 /******************************************************************************/ |
|
需要的库文件: /******************************************************************************/ LIBS = lib_generic/libgeneric.a LIBS += board/$(BOARDDIR)/lib$(BOARD).a LIBS += cpu/$(CPU)/lib$(CPU).a ............. LIBS += common/libcommon.a LIBS += $(BOARDLIBS) LIBS := $(addprefix $(obj),$(LIBS)) .PHONY : $(LIBS) /******************************************************************************/ |
|
最终生成的各种镜像文件: /******************************************************************************/ ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) all: $(ALL) $(obj)u-boot.hex: $(obj)u-boot $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ $(obj)u-boot.srec: $(obj)u-boot $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ $(obj)u-boot.bin: $(obj)u-boot $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ /*******************************************************************************/ |
Stage3 |
#make |
5、小结U-Boot ELF文件镜像的生成过程:
@依赖目标depend:
|
生成各个子目录的 .depend 文件(.depend列出每个目标文件的依赖文件)。生成方法,调用每个子目录的make_depend。 /***********************************************************************/ depend dep: for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir _depend ; done /***********************************************************************/ |
@依赖目标version:
|
生成版本信息到版本文件VERSION_FILE中。 /***********************************************************************/ version: @echo -n "#define U_BOOT_VERSION \"U-Boot " > $(VERSION_FILE); \ echo -n "$(U_BOOT_VERSION)" >> $(VERSION_FILE); \ echo -n $(shell $(CONFIG_SHELL) $(TOPDIR)/tools/setlocalversion \ $(TOPDIR)) >> $(VERSION_FILE); \ echo "\"" >> $(VERSION_FILE) /***********************************************************************/ |
@伪目标SUBDIRS:
|
执行tools ,examples ,post, post\cpu 子目录下面的make文件。 /***********************************************************************/ SUBDIRS = tools \ examples \ post \ post/cpu .PHONY : $(SUBDIRS) $(SUBDIRS): $(MAKE) -C $@ all /***********************************************************************/ |
@依赖目标$(OBJS):
|
目标即cpu/start.o /***********************************************************************/ $(OBJS): $(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@)) /***********************************************************************/ |
@依赖目标$(LIBS): |
这个目标太多,都是每个子目录的库文件*.a ,通过执行相应子目录下的make来完成 /***********************************************************************/ $(LIBS): $(MAKE) -C $(dir $(subst $(obj),,$@)) /***********************************************************************/ |
@依赖目标$(LDSCRIPT): |
对于smdk2410,LDSCRIPT即连接脚本文件是board/smdk2410/u-boot.lds,定义了连接时各个目标文件是如何组织的。 /***********************************************************************/ LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS) /***********************************************************************/ |
@执行连接命令: |
把start.o和各个子目录makefile生成的库文件按照LDFLAGS连接在一起,生成ELF文件u-boot 和连接时内存分配图文件u-boot.map。 /***********************************************************************/ cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \ --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \ -Map u-boot.map -o u-boot /***********************************************************************/ |
总结: |
MAKE工程的编译流程就是通过执行执行一个make *_config传入ARCH,CPU,BOARD,SOC参数,然后mkconfig根据参数将include头文件夹相应的头文件夹连接好,生成config.h。然后执行make分别调用各子目录的Makefile 生成所有的obj文件和obj库文件*.a.最后连接所有目标文件,生成镜像。不同格式的镜像都是调用相应工具由elf镜像生成。 |
6、U-Boot启动过程:(有两种启动方式:1、启动加载(bootloading) 2、下载downloading)
stage1 |
过程 |
调用的文件 |
1 |
定义入口 |
cpu/arm920t/start.s |
2 |
设异常向量表 |
cpu/arm920t/start.s |
3 |
设置CPU为SVC模式 |
cpu/arm920t/start.s |
4 |
关看门狗 |
cpu/arm920t/start.s |
5 |
禁止所有中断 |
cpu/arm920t/start.s |
6 |
设CPU速度和时钟及中断控制寄存器 |
cpu/arm920t/start.s |
7 |
禁止MMU和cache |
cpu/arm920t/start.s |
8 |
初始化内存控制器(SDRAM) |
cpu/arm920t/start.s 调用 board/smdk2410/lowlevel_init.s |
9 |
搬移ROM中代码到RAM |
cpu/arm920t/start.s |
10 |
设堆栈 |
cpu/arm920t/start.s |
11 |
进入C代码 |
lib_arm/board.c start_armboot( ) |
stage2 |
|
|
12 |
调用一系列初始化函数 |
lib_arm/board.c中start_armboot函数 |
13 |
初始化内存设备 |
|
14 |
初始化内存分配函数 |
|
15 |
若有NAND,初始化 |
flash_init |
16 |
若有显示器,初始化 |
env_relocate |
17 |
若有网络设备,填写IP及MAC地址 |
|
18 |
进入命令循环,接受用户命令 |
command/main.c |
注1:有些过程并不是必需的,以上是针对一般情况。
注2:具体的过程分析可借助Source Insight软件对cpu/arm920t/start.s进行分析。
/**************************************************************************************
未完,待续……
***************************************************************************************/