uboot 配置 编译 连接全过程.docx
- 文档编号:7709931
- 上传时间:2023-01-25
- 格式:DOCX
- 页数:16
- 大小:293.79KB
uboot 配置 编译 连接全过程.docx
《uboot 配置 编译 连接全过程.docx》由会员分享,可在线阅读,更多相关《uboot 配置 编译 连接全过程.docx(16页珍藏版)》请在冰豆网上搜索。
uboot配置编译连接全过程
uboot配置编译连接全过程
分类:
Uboot2011-11-1420:
48415人阅读评论
(1)收藏举报
根据README中PortingGuide的指示精神,我们要在新板子上移植UBoot,最快速的办法就是查看当前UBoot代码中是否有对相似于待移植板子的其他板子的支持(这应该又是一个可考虑成为习惯甚至本能的做法。
也即拿到不熟悉的软件包后,看看里面有没有自己熟悉的、或者和自己目前要做的东西很相似的部分,从这个部分入手往往能很快的解决问题)。
很幸运,我们在里面找到了三星公司所生产的SMDK2410参考板,这是三星公司早先为推销其生产的ARM9芯片-S3C2410所推出的一块PCB参考设计板(推出时随板子附加了很多的软硬件资料)。
知道这个后,我们很高兴,因为我们知道我们板子上的CPU——S3C2440正是S3C2410的升级版。
所以,在真正动手移植之前,分析一下新版本UBoot中如何支持SMDK2410的,自然成为接下来要做的事情。
UBoot本身是用GNU工具链开发的,那这就意味着其代码包里面必然会有很多的Makefile文件,因为GNUMake正是用来管理软件项目编译的GNU工具。
而且,正如我们前面说的,UBoot能支持如此多的CPU体系结构和操作系统,那它就必定会有很多的配置选项用于配置。
所以分析支持SMDK2410参考板的具体代码之前,我们必须先弄懂UBoot的配置编译过程。
我们只有对此了然于胸了,才能比较顺利的完成移植。
所幸的是,不像Linux内核代码,UBoot的代码量并不多,分析起来并不痛苦。
作为UBoot学习移植系列的第一篇文章,我在这里就以SMDK2410板子的支持作为例子,分析新版本UBoot(2010.06)的配置编译过程。
作为前提,你应该知道一些GNUMake以及一些BashShellScript的知识。
从UBOOT用户的角度来讲,其编译配置过程倒是非常的简单,只需要在命令行中切换到UBoot目录下输入两个命令:
[csicong@juliantecu-boot-2010.06]$makeARCH=armCROSS_COMPILE=arm-linux-smdk2410_config
[csicong@juliantecu-boot-2010.06]$makeARCH=armCROSS_COMPILE=arm-linux-
第一个命令完成UBootforsmdk2410参考板的配置,第二个命令则真正编译出所需要的UBoot二进制映像文件,编译出来之后我们需要将其下载到FLASH中。
在这两个命令中,参数ARCH表示我们要给具有何种体系结构的CPU编译UBoot,因为不管SMDK2410参考板上的CPU——S3C2410,还是我手头板子上的CPU,皆为ARM9芯片,所以这里显然应该为arm;CROSS_COMPILE为交叉编译工具链各工具的名称前缀。
我们需要用到arm-linux-gcc作为编译器、arm-linux-ld为链接器。
。
。
所以这里取值为arm-linux-。
在第一个命令中,我们以smdk2410_config作为本次make的目标。
查找UBoot项目顶层Makefile得到关于此目标的规则如下:
smdk2410_config:
unconfig
@$(MKCONFIG)$(@:
_config=)armarm920tsmdk2410samsungs3c24x0
根据Makefile规则的定义,GNUMake在处理这条规则的时候,先判断其依赖——也就是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命令总是得到执行,该命令的目的是删除一些配置编译过程中产生的文件。
在这些文件中,与本文讨论密切相关的是前面两个,以及后面两个。
前面两个是用第一条命令来配置UBoot的过程中产生的,后面则是用第二条命令来编译UBoot的过程中产生的。
这条规则先把他们全部删除。
注意rm命令前面的@符号是取消该命令执行时的回显。
执行完对依赖——unconfig的处理,GNUMake回到对smdk2410_config的处理。
它接下来执行命令:
@$(MKCONFIG)$(@:
_config=)armarm920tsmdk2410samsungs3c24x0
在这条命令中,$(MKCONFIG)指代的就是UBoot根目录下的mkconfig脚本,因为你可以在同一Makefile中找到该变量的定义:
MKCONFIG:
=$(SRCTREE)/mkconfig
exportMKCONFIG
其中$(SRCTREE)指代的就是UBoot根目录。
另外在上面的命令中,$(@:
_config=)的部分实际上是处理自动变量$@,也就是第一次make的目标smdk2410_config,这里将其中"_config"的部分用空来代替。
去掉"_config"的部分后,剩余的smdk2410也就是三星参考板的名称。
所以最后上面的命令也就可直接写作:
./mkconfigsmdk2410armarm920tsmdk2410samsungs3c24x0
很清楚,执行mkconfig脚本,并传之以所在的目录名称,sansung是产商名称,s3c24x0是对应的SOC芯片名称。
有人对arm920和s3c24x0两者所指东西混淆不清,我自己在平时为方便起见也经常混用这两个词,有时候也将它们统称为CPU。
但实际上,更精确的说法认为arm920t是arm9类型的CPU核,而s3c2410则是用该核搭配另外一些外设做在一块芯片内形成的SOC芯片。
由于三星本身出了很多使用arm920tCPU核的芯片,如s3c2400、s3c2410以及s3c2440,所以在UBoot代码中,用s3c24x0来统称这一类SOC芯片。
mkconfig脚本是bash脚本。
对应于smdk2410参考板,其主要做三件事情:
1,在include目录下制作一些软连接,参见代码:
#
#Createlinktoarchitecturespecificheaders
#
if["$SRCTREE"!
="$OBJTREE"];then
mkdir-p${OBJTREE}/include
mkdir-p${OBJTREE}/include2
cd${OBJTREE}/include2
rm-fasm
ln-s${SRCTREE}/arch/$2/include/asmasm
LNPREFIX=${SRCTREE}/arch/$2/include/asm/
cd../include
rm-fasm
ln-s${SRCTREE}/arch/$2/include/asmasm
else
cd./include
rm-fasm
ln-s../arch/$2/include/asmasm
fi
rm-fasm/arch
if[-z"$6"-o"$6"="NULL"];then
ln-s${LNPREFIX}arch-$3asm/arch
else
ln-s${LNPREFIX}arch-$6asm/arch
fi
if["$2"="arm"];then
rm-fasm/proc
ln-s${LNPREFIX}proc-armvasm/proc
fi
由于我们编译UBoot时,通常都是在UBoot原有目录下编译的,并且针对smdk2410参板,"$2"="arm","$6"="s3c24x0",所以,以上代码的效果等同于我们用下面这些命令来手工创建软连接。
[csicong@juliantecinclude]$ln-s../arch/arm/include/asm./asm
[csicong@juliantecinclude]$ln-sarch-s3c24x0./asm/arch
[csicong@juliantecinclude]$ln-sproc-armv./asm/proc
2,在include目录下制作顶层Makefile要包含的文件include/config.mk,参见代码:
#
#CreateincludefileforMake
#
echo"ARCH=$2">config.mk
echo"CPU=$3">>config.mk
echo"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等变量的定义。
后面我们会知道,这个文件虽然简单,但是却决定了顶层Makefile的一大部分逻辑框架。
3,在include目录下制作产生特定于smdk2410参考板的头文件include/config.h,参见代码:
#AssignboarddirectorytoBOARDIRvariable
if[-z"$5"-o"$5"="NULL"];then
BOARDDIR=$4
else
BOARDDIR=$5/$4
fi
#
#Createboardspecificheaderfile
#
if["$APPEND"="yes"]#Appendtoexistingconfigfile
then
echo>>config.h
else
>config.h#Createnewconfigfile
fi
echo"/*Automaticallygenerated-donotedit*/">>config.h
foriin${TARGETS};do
echo"#defineCONFIG_MK_${i}1">>config.h;
done
cat<
#defineCONFIG_BOARDDIRboard/$BOARDDIR
#include
#include
#include
EOF
需要说明的是,上面一行">config.h"的作用是创建一个空文件。
有的同志可能不太知道,你可以在shell提示符下试验一下,其效果就和用touch命令一样。
这段代码会创建文件include/config.h,其内容如下:
/*Automaticallygenerated-donotedit*/
#defineCONFIG_BOARDDIRboard/samsung/smdk2410
#include
#include
#include
至此,针对smdk2410参考板来配置新版本的UBoot代码完成了,接下来,我们能使用上面的第二个命令来编译可以该参考板上引导Linux内核的UBoot了。
在讨论编译UBoot的第二个命令之前,你需要稍微看一下UBoot顶层Makefile的内容,其实里面最重要的部分就是一个条件判断结构,抽出代码如下:
...
ifeq($(obj)include/config.mk,$(wildcard$(obj)include/config.mk))
...//A
else#!
config.mk
all$(obj)u-boot.hex$(obj)u-boot.srec$(obj)u-boot.bin\
$(obj)u-boot.img$(obj)u-boot.dis$(obj)u-boot\
$(filter-outtools,$(SUBDIRS))$(TIMESTAMP_FILE)$(VERSION_FILE)gdbtools\
updaterenvdependdeptagsctagsetagscscope$(obj)System.map:
@echo"Systemnotconfigured-seeREADME">&2
@exit1
tools:
$(MAKE)-Ctools
tools-all:
$(MAKE)-CtoolsHOST_TOOLS_ALL=y
endif#config.mk
...
...//Bé?
¨å?
?
...
这个判断结构,其实就是看是否存在文件include/config.mk,如果存在的,则说明第一步的配置过程已经完成,因为这个文件正式配置过程中产生的。
所以此时GNUMake就会处理上面代码中的A部分,否则就会处理else后面、endif前面的部分。
从这里我们可以看出,如果不对UBoot进行配置,而直接去编译,那么它会给出一个警告,并要求我们去看README。
上面中的B部分就是UBoot中对各种所支持板子的规则定义,其中包括了我们前面提到过的对应于smdk2410_config的规则。
上面代码中的A部分是整个顶层Makefile的精华所在,其中包含了生成UBoot二进制映像的大部分规则定义,也是我们关注的重点。
好了,知道这样一个框架后,我们再回头来看看第二个命令的编译过程。
在开头提到的第二个命令中,我们并没有给make指定一个目标,所以按照GNUMake的规定,它将去着手处理默认规则,也即出现在顶层Makefile第一个规则all,如下:
#AlwaysappendALLsothatarchconfig.mk'scanaddcustomones
ALL+=$(obj)u-boot.srec$(obj)u-boot.bin$(obj)System.map$(U_BOOT_NAND)$(U_BOOT_ONENAND)
all:
$(ALL)
这条规则里面并没有命令,所以GNUMake在处理的时候,会依次去处理ALL中的这五个目标。
而针对smdk2410参考板,没有定义CONFIG_NAND_U_BOOT和CONFIG_ONENAND_U_BOOT,所以依据下面的规则,后面两个目标:
$(U_BOOT_NAND)$(U_BOOT_ONENAND)将为空。
ifeq($(CONFIG_NAND_U_BOOT),y)
NAND_SPL=nand_spl
U_BOOT_NAND=$(obj)u-boot-nand.bin
endif
ifeq($(CONFIG_ONENAND_U_BOOT),y)
ONENAND_IPL=onenand_ipl
U_BOOT_ONENAND=$(obj)u-boot-onenand.bin
ONENAND_BIN?
=$(obj)onenand_ipl/onenand-ipl-2k.bin
endif
所以对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)-Osrec$<$@
这其实是二进制代码的SRecord格式表示。
这种格式最先用在摩托罗拉6800处理器上,专门用于处理二进制数据在不同设备之间的传输上。
但是就用GNU工具进行smdk2410参考板的开发来说,是用不到的。
我们只需要最原始的二进制数据映像u-boot.bin即可,里面包含纯粹的二进制指令和数据,并没有用过任何格式包装过。
不过先不管到底u-boot.srec有没有用,根据上面处理u-boot.srec的规则定义,在处理u-boot.srec之前,先要处理u-boot(它是一个ELF格式可执行文件),查找对应的规则定义如下:
GEN_UBOOT=\
UNDEF_SYM=`$(OBJDUMP)-x$(LIBBOARD)$(LIBS)|\
sed-n-e's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
cd$(LNDIR)&&$(LD)$(LDFLAGS)$$UNDEF_SYM$(__OBJS)\
--start-group$(__LIBS)--end-group$(PLATFORM_LIBS)\
-Mapu-boot.map-ou-boot
$(obj)u-boot:
depend$(SUBDIRS)$(OBJS)$(LIBBOARD)$(LIBS)$(LDSCRIPT)$(obj)u-boot.lds
$(GEN_UBOOT)
ifeq($(CONFIG_KALLSYMS),y)
smap=`$(callSYSTEM_MAP,u-boot)|\
awk'$$2~/[tTwW]/{printf$$1$$3"\"}'`;\
$(CC)$(CFLAGS)-DSYSTEM_MAP="\"$${smap}\""\
-ccommon/system_map.c-o$(obj)common/system_map.o
$(GEN_UBOOT)$(obj)common/system_map.o
endif
由上面的规则可知,目标u-boot的依赖有很多个,为:
depend$(SUBDIRS)$(OBJS)$(LIBBOARD)$(LIBS)$(LDSCRIPT)$(obj)u-boot.lds。
$(GEN_UBOOT)是该规则命令集的第一个部分。
而对于SMDK2410参考板来说,CONFIG_KALLSYMS并未定义,所以该规则的命令实际上只有实际上只有变量$(GEN_UBOOT)所指代的部分。
此规则处理的第一个目标为depend,查找同一Makefile可得出规则如下:
#Explicitlymake_dependinsubdirscontainingmultipletargetstoprevent
#parallelsub-makescreating.dependfilessimultaneously.
dependdep:
$(TIMESTAMP_FILE)$(VERSION_FILE)$(obj)include/autoconf.mk
fordirin$(SUBDIRS)$(CPUDIR)$(dir$(LDSCRIPT));do\
$(MAKE)-C$$dir_depend;done
该规则先会处理三个依赖,$(TIMESTAMP_FILE)、$(VERSION_FILE)以及$(obj)include/autoconf.mk。
前两个分别生成UBoot本次编译的时间戳头文件和版本头文件。
而后者则由一个稍微复杂一点的规则处理,如下所示:
#
#Auto-generatetheautoconf.mkfile(whichisincludedbyallmakefiles)
#
#Thistargetactuallygenerates2files;autoconf.mkandautoconf.mk.dep.
#thedepfileisonlyincludeinthistoplevelmakefiletodeterminewhen
#toregeneratetheautoconf.mkfile.
$(obj)include/autoconf.mk.dep:
$(obj)include/config.hinclude/common.h
@$(XECHO)Generating$@;\
set-e;\
:
Generatethedependancies;\
$(CC)-xc-DDO_DEPS_ONLY-M$(HOSTCFLAGS)$(CPPFLAGS)\
-MQ$(obj)include/autoconf.mkinclude/common.h>$@
$(obj)include/autoconf.mk:
$(obj)include/config.h
@$(XECHO)Generating$@;\
set-e;\
:
Extracttheconfigmacros;\
$(CPP)$(CFLAGS)-DDO_DEPS_ONLY-dMinclude/common.h|\
sed-n-ftools/scripts/define2mk.sed>$@.tmp&&\
mv$@.tmp$@
处理autoconf.mk的规则看起来有点繁,但实际上它是以tools/scripts/define2mk.sed作为sed脚本来调用sed程序,其功能是将C语言中定义的宏配置转换成Makefile能理解的变量定义形式。
就smdk2410参考板来说我们可以举个例子:
在include/configs/smdk2410.h文件中有宏CONFIG_S3C2410的定义:
#defineCONFIG_S3C24101/*specificallyaSAMSUNGS3C2410SoC*/
那么这里的这个命令就会将其转换成如下的形式写到include/autoconfi.mk文件中去。
CONFIG_S3C2410=y
最终出来的include/autoconf.mk文件中都是类似的变量定义。
从下面的代码中可以看出这个文件将会被顶层M
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- uboot 配置 编译 连接全过程 连接 全过程