uboot的配置(make xxx_config)和编译(make)工程解读

uboot编译三步走:

  1. make xxx_config
  2. make
  3. make install

 

第一步make xxx_config

这一步是产生板子的配置文件。

我们假设是配置ast2500evb板子,那么这里的配置命令就是 make ast2500evb_config

uboot/Makefile

uboot的配置(make xxx_config)和编译(make)工程解读_第1张图片

这里%_config中%表示通配任意字符,即匹配ast2500evb_config。

首先执行依赖target ‘unconfig’的命令:删除之前配置时产生的文件。

然后执行命令@$(MKCONFIG) -A $(@:_config=)

$(MKCONFIG)为uboot/mkconfig, .

uboot的配置(make xxx_config)和编译(make)工程解读_第2张图片 

${CURDIR}为makefile变量,表示当前目录

$(@:_config=)表示将target(即%_config)中的_config替换为=后面的(null), 实际这里就相当于执行mkconfig -A ast2500evb

我们接着看mkconfig文件。

uboot/mkconfig

uboot的配置(make xxx_config)和编译(make)工程解读_第3张图片

这是一个shell脚本。

uboot的配置(make xxx_config)和编译(make)工程解读_第4张图片

$#: 表示参数个数

$n:表示第n个参数

首先判断参数的个数是否为2(makefile调用时的格式为mkconfig -A ast2500evb,参数个数为2)。

然后使用egrep提取boards.cfg中的数据,egrep使用的正则表达式: "^[[:space:]]*${2}[[:space:]]"

注意,这个正则表达式中有shell变量${2},要先替换。替换后正则表达式为

"^[[:space:]]*ast2500evb[[:space:]]"。

egrep正则表达式匹配任何以一个或多个空白符开头后跟ast2500evb字符串再后跟一个空白符的行,或者以ast2500evb字符串开头后跟一个空白符的行。

boards.cfg为输入文件。

boards.cfg描述了板子的arch, cpu, soc, board等信息。

对于我们的例子而言,egrep输出ast2500evb arm arm1176 ast2500evb – ast2500.

之后,通过set将这些信息赋值给$1, $2, $3…

这样之后,

$1 代表target  ast2500evb;

$2代表arch arm;

$3代表cpu arm1176;

$4代表board ast2500evb

$5代表vendor –

$6代表soc ast2500

然后将这些信息设置为相应的变量:

uboot的配置(make xxx_config)和编译(make)工程解读_第5张图片

注意,55行的${1%_config},%_config表示去掉_config以及其右边的字符串,即表示将$1中的_config以及_config右边的所有字符串去掉。

接下去,创建特定的文件和目录。

uboot的配置(make xxx_config)和编译(make)工程解读_第6张图片

$SRCTREE: 表示当前工程的顶层目录uboot/

$OBJTREE: 表示build目录,该目录由make -O=xxx来指定,如果没有指定,则默认为$SRCTREE.

$SRCTREE和$OBJTREE都定义在uboot/Makefile中。

uboot的配置(make xxx_config)和编译(make)工程解读_第7张图片

假定$SRCTREE == $OBJTREE, 即我们make时没有指定-O=xxx参数。

那么mkconfig会在uboot/include下面创建一个asm软链接,链接到../arch/arm/include/asm

然后删除之前创建的链接文件uboot/include/asm/arch(uboot/arch/arm/include/asm/arch), 并创建本次配置的arch链接文件.

uboot的配置(make xxx_config)和编译(make)工程解读_第8张图片

接着创建asm/proc链接文件:

uboot的配置(make xxx_config)和编译(make)工程解读_第9张图片

之后,创建uboot/include/config.mk文件,文件内容为

ARCH   =

CPU   =

BOARD   =

SOC   =

uboot的配置(make xxx_config)和编译(make)工程解读_第10张图片

并配置板子目录变量为ast2500evb

uboot的配置(make xxx_config)和编译(make)工程解读_第11张图片

然后创建uboot/include/config.h文件,并写入定义行注释代码。

uboot的配置(make xxx_config)和编译(make)工程解读_第12张图片

接着向config.h写入内容:

uboot的配置(make xxx_config)和编译(make)工程解读_第13张图片

174-177行写入一些预定义的宏,这些宏由boards.cfg中的最后一列(Options)而来。

比如:

那么174-177行就向config.h写入如下宏:

#define CONFIG_AT91SAM9260

#define CONFIG_SYS_USE_DATAFLASH_CS0

由于ast2500evb没有Options,故174-177行不执行。

对于ast2500evb是写入如下定义:

uboot的配置(make xxx_config)和编译(make)工程解读_第14张图片

config_cmd_defaults.h locates at uboot/include/config_cmd_defaults.h

config_defaults.h locates at uboot/include/config_defaults.h

configs/ast2500evb.h locates at uboot/configs/ast2500evb.h

asm/config.h locates at uboot/arch/arm/include/asm/config.h

config_fallbacks.h locates at uboot/include/config_fallbacks.h

config_uncmd_spl.h locates at uboot/include/config_uncmd_spl.h

到这里,make menuconfig就执行结束了。

总结一下,make ast2500evb_config会创建

uboot/include/asm   ->  uboot/arch/arm/include/asm

uboot/include/asm/arch  ->  uboot/arch/arm/include/asm/arch-ast2500

uboot/include/asm/proc  ->  uboot/arch/arm/include/asm/proc-armv

uboot/include/config.mk

uboot/include/config.h

 

第二步 make

执行make时,默认的target是all, uboot/Makefile中有两处定义了all:

这里,第二个all会覆盖第一个all。故执行make或make all时,对应uboot/Makefile:448处的all.

从448行,我们知道,执行make的时候,它的依赖为$(ALL-y)和$(SUBDIR_EXAMPLES)。我们主要来看一下$(ALL-y)都是些啥:

uboot的配置(make xxx_config)和编译(make)工程解读_第15张图片

$(ALL-y)包含了u-boot.srec, u-boot.bin, System.map. 我们的例子中ast2500evb没有配置CONFIG_NAND_U_BOOT, CONFIG_ONENAND_U_BOOT, CONFIG_SPL, CONFIG_OF_SEPARATE, CONFIG_SPL等。

u-boot.srec, u-boot.bin都是基于u-boot的格式转换。u-boot.bin为“裸”的二进制格式,可以直接被cpu执行(只有*.txt, *.bss之类的段,没有其他的header之类的,比如elf header等)。其他的*.srec, *.hex是有文件格式的,就像有文件头描述之类的一样,该类文件需要解析成bin文件才能被cpu执行。

uboot的配置(make xxx_config)和编译(make)工程解读_第16张图片

u-boot这个又依赖于伪目标depend,$(SUBDIR_TOOLS) ,$(OBJS) ,$(LIBBOARD) ,$(LIBS) ,$(LDSCRIPT) ,$(obj)u-boot.lds

u-boot是通过链接程序ld,将*.o, *.a, *.so等,以及链接脚本u-boot.lds生成的elf可执行文件(linux os可识别的可执行文件格式,含有elf header)。

这个u-boot直接给cpu是无法执行的,因为cpu可不认elf header。

所以,u-boot.bin就是将u-boot中的text, bss之类的段提取出来的纯可执行的二进制文件。

下面是u-boot的elf header和文件内容:

uboot的配置(make xxx_config)和编译(make)工程解读_第17张图片

uboot的配置(make xxx_config)和编译(make)工程解读_第18张图片

uboot的配置(make xxx_config)和编译(make)工程解读_第19张图片

我们来看看u-boot.bin中的内容:

uboot的配置(make xxx_config)和编译(make)工程解读_第20张图片

从下面的对比来看,u-boot.bin中的内容就是u-boot中offset 0x10000开始处的内容。

uboot的配置(make xxx_config)和编译(make)工程解读_第21张图片

我们接着来介绍下u-boot的依赖depend,$(SUBDIR_TOOLS) ,$(OBJS) ,$(LIBBOARD) ,$(LIBS) ,$(LDSCRIPT) ,$(obj)u-boot.lds.

depend是用来生成依赖关系的。比如源文件*.c引用了头文件*.h,depend的作用就是用于生成*.c依赖*.h这样的依赖关系,有了这个依赖关系后,当*.h有变化时,make就会重新编译对应的*.c文件。

$(SUBDIR_TOOLS)就是tools.

$(OBJS)就是*.o, 它包含哪些呢?

uboot/Makefile

uboot的配置(make xxx_config)和编译(make)工程解读_第22张图片

这里的CPUDIR是在uboot/config.mk中定义的,uboot/config.mk在uboot/Makefile中包含。

uboot/Makefile

uboot/config.mk

uboot的配置(make xxx_config)和编译(make)工程解读_第23张图片

CPUDIR就是uboot/arch/arm/cpu/arm1176, 这里$(ARCH), $(CPU)就是在由make ast2500evb_config生成的uboot/include/config.mk中定义。

因此, $(OBJS)为uboot/arch/arm/cpu/arm1176/start.o.

补充一下,uboot/include/config.mk 164和165行的文件是在depend的依赖中生成的。

uboot/Makefile

uboot的配置(make xxx_config)和编译(make)工程解读_第24张图片

$(LIBBOARD): 就是 uboot/board/ast2500evb/libast2500evb.o

uboot/Makefile

$(LIBS): 就是下列各种*.o

uboot/Makefile

uboot的配置(make xxx_config)和编译(make)工程解读_第25张图片

$(LDSCRIPT): 就是指定连接器脚本,即uboot/board/ast2500evb/u-boot.lds

uboot/Makefile

uboot的配置(make xxx_config)和编译(make)工程解读_第26张图片

u-boot.lds文件中定义了程序的入口、代码段、数据段地址等信息:

uboot的配置(make xxx_config)和编译(make)工程解读_第27张图片

至此,我们大概了解了这几个依赖:depend,$(SUBDIR_TOOLS) ,$(OBJS) ,$(LIBBOARD) ,$(LIBS) ,$(LDSCRIPT) ,$(obj)u-boot.lds。

我们接着看依赖$(OBJS)。

$(OBJS)是通过进入到$(CPUDIR)目录(CPUDIR=uboot/arch/arm/cpu/arm1176)中执行make而得到的。

uboot/arch/arm/cpu/arm1176/Makefile

uboot的配置(make xxx_config)和编译(make)工程解读_第28张图片

uboot/config.mk中定义了*.o生成的规则。

uboot/config.mk

uboot的配置(make xxx_config)和编译(make)工程解读_第29张图片

我们看下一个$(LIBBOARD)

$(LIBBOARD) = uboot/board/ast2500evb/libast2500evb.o

uboot/Makefile

$(LIBBOARD)这个target是通过进入其所在目录(uboot/board/ast2500evb),执行make而得到的。

uboot/board/ast2500evb/Makefile

uboot的配置(make xxx_config)和编译(make)工程解读_第30张图片

类似地,$(LIBS)也是分别进入目标所在的目录,执行make操作而得到。

 

最后,我们来看一下$(ALL-y)的一个依赖System.map是如何生成的。

System.map是通过u-boot这个elf可执行文件而来的。

uboot/Makefile

System.map是一个map文件,记录了符号和地址信息。

 

第三步 make install

(略)

 

 

 

 

 

 

你可能感兴趣的:(uboot,uboot)