1、uboot 配置 编译 连接全过程uboot 配置 编译 连接全过程 分类: Uboot 2011-11-14 20:48 415人阅读 评论(1) 收藏 举报 根据README中 Porting Guide 的指示精神,我们要在新板子上移植UBoot,最快速的办法就是查看当前UBoot代码中是否有对相似于待移植板子的其他板子的支持(这应该又是一个可考虑成为习惯甚至本能的做法。也即拿到不熟悉的软件包后,看看里面有没有自己熟悉的、或者和自己目前要做的东西很相似的部分,从这个部分入手往往能很快的解决问题)。很幸运,我们在里面找到了三星公司所生产的SMDK2410参考板,这是三星公司早先为推销其生产
2、的ARM9芯片-S3C2410所推出的一块PCB参考设计板(推出时随板子附加了很多的软硬件资料)。知道这个后,我们很高兴,因为我们知道我们板子上的CPUS3C2440正是S3C2410的升级版。所以,在真正动手移植之前,分析一下新版本UBoot中如何支持SMDK2410的,自然成为接下来要做的事情。UBoot本身是用GNU工具链开发的,那这就意味着其代码包里面必然会有很多的Makefile文件,因为GNU Make正是用来管理软件项目编译的GNU工具。而且,正如我们前面说的,UBoot能支持如此多的CPU体系结构和操作系统,那它就必定会有很多的配置选项用于配置。所以分析支持SMDK2410参考
3、板的具体代码之前,我们必须先弄懂UBoot的配置编译过程。我们只有对此了然于胸了,才能比较顺利的完成移植。所幸的是,不像Linux内核代码,UBoot的代码量并不多,分析起来并不痛苦。作为UBoot学习移植系列的第一篇文章,我在这里就以SMDK2410板子的支持作为例子,分析新版本UBoot(2010.06)的配置编译过程。作为前提,你应该知道一些GNU Make以及一些Bash Shell Script的知识。从UBOOT用户的角度来讲,其编译配置过程倒是非常的简单,只需要在命令行中切换到UBoot目录下输入两个命令:csicongjuliantec u-boot-2010.06$ make
4、 ARCH=arm CROSS_COMPILE=arm-linux- smdk2410_configcsicongjuliantec u-boot-2010.06$ make ARCH=arm CROSS_COMPILE=arm-linux-第一个命令完成UBoot for smdk2410参考板的配置,第二个命令则真正编译出所需要的 UBoot 二进制映像文件,编译出来之后我们需要将其下载到FLASH中。在这两个命令中,参数ARCH表示我们要给具有何种体系结构的CPU编译UBoot,因为不管SMDK2410参考板上的CPUS3C2410,还是我手头板子上的CPU,皆为ARM9芯片,所以这里显
5、然应该为arm;CROSS_COMPILE为交叉编译工具链各工具的名称前缀。我们需要用到arm-linux-gcc作为编译器、arm-linux-ld为链接器。所以这里取值为 arm-linux- 。 在第一个命令中,我们以 smdk2410_config 作为本次 make 的目标。查找UBoot项目顶层 Makefile 得到关于此目标的规则如下:smdk2410_config : unconfig $(MKCONFIG) $(:_config=) arm arm920t smdk2410 samsung s3c24x0根据 Makefile 规则的定义,GNU Make在处理这条规则的时
6、候,先判断其依赖也就是 unconfig 是否需要更新。而我们在同一Makefile中找到 unconfig 的规则为(482行):unconfig: rm -f $(obj)include/config.h $(obj)include/config.mk $(obj)board/*/config.tmp$(obj)board/*/*/config.tmp $(obj)include/autoconf.mk$(obj)include/autoconf.mk.dep由于目录下没有一个叫 unconfig 的文件存在,所以和 unconfig 相关的这条规则总是得到处理,也就是其中的 rm 命令总
7、是得到执行,该命令的目的是删除一些配置编译过程中产生的文件。在这些文件中,与本文讨论密切相关的是前面两个,以及后面两个。前面两个是用第一条命令来配置UBoot的过程中产生的,后面则是用第二条命令来编译UBoot的过程中产生的。这条规则先把他们全部删除。注意rm命令前面的符号是取消该命令执行时的回显。执行完对依赖unconfig的处理,GNU Make 回到对 smdk2410_config 的处理。它接下来执行命令: $(MKCONFIG) $(:_config=) arm arm920t smdk2410 samsung s3c24x0在这条命令中,$(MKCONFIG) 指代的就是 UBo
8、ot 根目录下的 mkconfig 脚本,因为你可以在同一Makefile中找到该变量的定义:MKCONFIG := $(SRCTREE)/mkconfigexport MKCONFIG其中 $(SRCTREE) 指代的就是UBoot 根目录。另外在上面的命令中,$(:_config=) 的部分实际上是处理自动变量 $,也就是第一次 make 的目标 smdk2410_config,这里将其中_config的部分用空来代替。去掉_config的部分后,剩余的 smdk2410 也就是三星参考板的名称。所以最后上面的命令也就可直接写作: ./mkconfig smdk2410 arm arm92
9、0t smdk2410 samsung s3c24x0很清楚,执行 mkconfig 脚本,并传之以所在的目录名称,sansung 是产商名称,s3c24x0是对应的SOC芯片名称。有人对arm920和s3c24x0两者所指东西混淆不清,我自己在平时为方便起见也经常混用这两个词,有时候也将它们统称为CPU。但实际上,更精确的说法认为arm920t是arm9类型的CPU核,而s3c2410则是用该核搭配另外一些外设做在一块芯片内形成的SOC芯片。由于三星本身出了很多使用arm920tCPU核的芯片,如s3c2400、s3c2410以及s3c2440,所以在UBoot代码中,用s3c24x0来统称
10、这一类SOC芯片。mkconfig 脚本是 bash 脚本。对应于smdk2410参考板,其主要做三件事情:1,在include目录下制作一些软连接,参见代码:# Create link to architecture specific headers#if $SRCTREE != $OBJTREE ; then mkdir -p $OBJTREE/include mkdir -p $OBJTREE/include2 cd $OBJTREE/include2 rm -f asm ln -s $SRCTREE/arch/$2/include/asm asm LNPREFIX=$SRCTREE/a
11、rch/$2/include/asm/ cd ./include rm -f asm ln -s $SRCTREE/arch/$2/include/asm asmelse cd ./include rm -f asm ln -s ./arch/$2/include/asm asmfirm -f asm/archif -z $6 -o $6 = NULL ; then ln -s $LNPREFIXarch-$3 asm/archelse ln -s $LNPREFIXarch-$6 asm/archfiif $2 = arm ; then rm -f asm/proc ln -s $LNPRE
12、FIXproc-armv asm/procfi由于我们编译UBoot时,通常都是在UBoot原有目录下编译的,并且针对smdk2410参板,$2=arm,$6=s3c24x0,所以,以上代码的效果等同于我们用下面这些命令来手工创建软连接。csicongjuliantec include$ ln -s ./arch/arm/include/asm ./asmcsicongjuliantec include$ ln -s arch-s3c24x0 ./asm/archcsicongjuliantec include$ ln -s proc-armv ./asm/proc2, 在include目录下
13、制作顶层Makefile要包含的文件 include/config.mk,参见代码:# Create include file for Make#echo ARCH = $2 config.mkecho CPU = $3 config.mkecho BOARD = $4 config.mk $5 & $5 != NULL & echo VENDOR = $5 config.mk $6 & $6 != NULL & echo SOC = $6 config.mk很明显,制作出来的文件 include/config.mk,其内容非常简单,只包括 ARCH、CPU、BOARD、VENDOR、SOC等
14、变量的定义。后面我们会知道,这个文件虽然简单,但是却决定了顶层 Makefile的一大部分逻辑框架。3, 在include目录下制作产生特定于smdk2410参考板的头文件 include/config.h,参见代码:# Assign board directory to BOARDIR variableif -z $5 -o $5 = NULL ; then BOARDDIR=$4else BOARDDIR=$5/$4fi# Create board specific header file#if $APPEND = yes # Append to existing config filet
15、hen echo config.helse config.h # Create new config filefiecho /* Automatically generated - do not edit */ config.hfor i in $TARGETS ; do echo #define CONFIG_MK_$i 1 config.h ;donecat config.h#define CONFIG_BOARDDIR board/$BOARDDIR#include #include #include EOF需要说明的是,上面一行 config.h 的作用是创建一个空文件。有的同志可能不
16、太知道,你可以在shell提示符下试验一下,其效果就和用 touch 命令一样。这段代码会创建文件include/config.h,其内容如下:/* Automatically generated - do not edit */#define CONFIG_BOARDDIR board/samsung/smdk2410#include #include #include 至此,针对smdk2410参考板来配置新版本的UBoot代码完成了,接下来,我们能使用上面的第二个命令来编译可以该参考板上引导Linux内核的UBoot了。在讨论编译UBoot的第二个命令之前,你需要稍微看一下 UBoot
17、顶层Makefile的内容,其实里面最重要的部分就是一个条件判断结构,抽出代码如下:.ifeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk)./A else # !config.mkall $(obj)u-boot.hex $(obj)u-boot.srec $(obj)u-boot.bin $(obj)u-boot.img $(obj)u-boot.dis $(obj)u-boot $(filter-out tools,$(SUBDIRS) $(TIMESTAMP_FILE) $(VERSION_FILE) gdbt
18、ools updater env depend dep tags ctags etags cscope $(obj)System.map: echo System not configured - see README &2 exit 1tools: $(MAKE) -C toolstools-all: $(MAKE) -C tools HOST_TOOLS_ALL=yendif # config.mk./B ?.这个判断结构,其实就是看是否存在文件 include/config.mk,如果存在的,则说明第一步的配置过程已经完成,因为这个文件正式配置过程中产生的。所以此时GNU Make就会处
19、理上面代码中的 A 部分,否则就会处理else后面、endif前面的部分。从这里我们可以看出,如果不对UBoot进行配置,而直接去编译,那么它会给出一个警告,并要求我们去看README。上面中的 B 部分就是UBoot中对各种所支持板子的规则定义,其中包括了我们前面提到过的对应于smdk2410_config 的规则。 上面代码中的 A 部分是整个顶层 Makefile 的精华所在,其中包含了生成UBoot二进制映像的大部分规则定义,也是我们关注的重点。好了,知道这样一个框架后,我们再回头来看看第二个命令的编译过程。在开头提到的第二个命令中,我们并没有给 make 指定一个目标,所以按照 GN
20、U Make 的规定,它将去着手处理默认规则,也即出现在顶层Makefile第一个规则 all ,如下:# Always append ALL so that arch config.mks can add custom onesALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND)all: $(ALL)这条规则里面并没有命令,所以GNU Make在处理的时候,会依次去处理ALL中的这五个目标。而针对smdk2410参考板,没有定义CONFIG_NAND_U_BOOT
21、和CONFIG_ONENAND_U_BOOT,所以依据下面的规则,后面两个目标:$(U_BOOT_NAND) $(U_BOOT_ONENAND)将为空。ifeq ($(CONFIG_NAND_U_BOOT),y)NAND_SPL = nand_splU_BOOT_NAND = $(obj)u-boot-nand.binendififeq ($(CONFIG_ONENAND_U_BOOT),y)ONENAND_IPL = onenand_iplU_BOOT_ONENAND = $(obj)u-boot-onenand.binONENAND_BIN ?= $(obj)onenand_ipl/one
22、nand-ipl-2k.binendif所以对UBoot的这次编译过程,将会在UBoot顶层目录中生成三个文件,u-boot.srec、u-boot.bin 以及 System.map。其中u-boot.bin正式我们所需要的二进制映像文件,我们可以把它直接下载到板子的FLASH上用于引导Linux操作系统。对于第一个文件 u-boot.srec,其对应的规则为: $(obj)u-boot.srec: $(obj)u-boot $(OBJCOPY) -O srec $ $(obj)include/autoconf.mk: $(obj)include/config.h $(XECHO) Gene
23、rating $ ; set -e ; : Extract the config macros ; $(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | sed -n -f tools/scripts/define2mk.sed $.tmp & mv $.tmp $处理 autoconf.mk 的规则看起来有点繁,但实际上它是以tools/scripts/define2mk.sed作为sed脚本来调用sed程序,其功能是将C语言中定义的宏配置转换成Makefile能理解的变量定义形式。就smdk2410参考板来说我们可以举个例子:在 include/configs/smdk2410.h 文件中有宏 CONFIG_S3C2410 的定义:#define CONFIG_S3C2410 1 /* specifically a SAMSUNG S3C2410 SoC */那么这里的这个命令就会将其转换成如下的形式写到 include/autoconfi.mk 文件中去。CONFIG_S3C2410=y最终出来的 include/autoconf.mk 文件中都是类似的变量定义。从下面的代码中可以看出这个文件将会被顶层 M
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1