u-boot初识

对于嵌入式系统的启动流程大概如下:

               上电 --》 bootloader 启动 --》 Linux内核 --》 挂载根文件系统 --》 启动应用程序

 

  一般来说,kernel是uboot从flash读到SDRAM中,然后再启动的。有时候uboot会通过cmdline传递一些参数给内核,比如我们工作中,uboot启动后会读取机顶盒中的配置分区,

然后把相应的值通过cmdline传给kernel,kernel再利用这些值设置相关的属性,供应用程序读取使用。

  但是在启动内核之前,其实uboot也会做很多的工作,比如:

  (1)读/写 flash的功能:开发过程中,有时候要重新烧写一个kernel,或者用tftp升级一些分区什么的,就要有写flash的功能

  (2)初始化时钟、初始化串口、初始化SDRAM和关看门狗等的硬件初始化

  (3)或者通过bootcmd自启动一些东西,比如开机logo、启动内核等等

 

1、uboot配置过程分析

(1)

当执行make xxxx_config进行配置的时候,会执行Makefile的xxxx_config目标,例如:

xxxx_config : unconfig
  @$(MKCONFIG)  $(@:_config=)  arm arm920t   #其中$(MKCONFIG)=./mkconfig,也就是执行当前目录的mkconfig文件,@代表目标名,_config等于空,所以xxxx_config被替换成xxxx

  所以,可以看成执行脚本并传递了几个参数,./mkconfig xxxx arm arm920t

 

(2)

mkconfig脚本会创建一些平台相关的mk文件和.h有文件之类的东西,比如

#平台相关的参数
echo
"ARCH = $2" > config.mk echo "CPU = $3" >> config.mk echo "BOARK= $4" >> config.mk
#生成平台对应的头文件
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include <configs/$1.h>" >>config.h

 

2、uboot的编译过程

编译的过程主要也是看Makefile文件:

(1)

ifeq ($(OBJTREE)/include/config.mk,$(wildcard $(OBJTREE)/include/config.mk))  #//就是配置的时候生成的文件,提供一些平台相关的参数,比如ARCH等

ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux-   #//定义交叉编译工具
endif

endif

export CROSS_COMPILE

# load other configuration
include $(TOPDIR)/config.mk  #//顶层的目录也有一个config.mk文件

OBJS  = cpu/$(CPU)/start.o

 

#//我们看到下面有很多的lib库文件,是模块目录里面的文件编译出来的一个.a文件

LIBS = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
LIBS += cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
endif
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \
fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a
LIBS += net/libnet.a
LIBS += disk/libdisk.a
LIBS += rtc/librtc.a
LIBS += dtt/libdtt.a
LIBS += drivers/libdrivers.a
LIBS += drivers/nand/libnand.a
LIBS += drivers/nand_legacy/libnand_legacy.a
LIBS += drivers/sk98lin/libsk98lin.a
LIBS += post/libpost.a post/cpu/libcpu.a
LIBS += common/libcommon.a

 

#//下面就是编译uboot执行的第一个目标all

ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)

all: $(ALL)

$(obj)u-boot.srec:    $(obj)u-boot 
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@

$(obj)u-boot.bin:    $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@

$(obj)u-boot.img:    $(obj)u-boot.bin
./tools/mkimage -A $(ARCH) -T firmware -C none \
-a $(TEXT_BASE) -e 0 \
-n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
sed -e 's/"[    ]*$$/ for $(BOARD) board"/') \
-d $< $@

$(obj)u-boot:    depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
-Map u-boot.map -o u-boot

 

(2)

第(1)步的最后面是编译过程中,一个链接的过程,其中会用到u-boot.lds,链接的时候会用到前面定义的OBJS和各种LIBS

 

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;

. = ALIGN(4);
.text :
{
cpu/arm920t/start.o (.text)
*(.text)
}

. = ALIGN(4);
.rodata : { *(.rodata) }

. = ALIGN(4);
.data : { *(.data) }

. = ALIGN(4);
.got : { *(.got) }

. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;

. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}

posted @ 2017-09-16 23:30  伊斯科明  阅读(169)  评论(0编辑  收藏  举报