北京哪个公司做网站,免费流量平台哪个最好,wordpress企业主题下载,wordpress作品集主题 免费以下内容源于朱有鹏嵌入式课程的学习与整理#xff0c;如有侵权请告知删除。
uboot来源于uboot官网#xff0c;或者SoC官方#xff08;研发s5pv210这款芯片的公司推出的开发板叫SMDKV210#xff09;#xff0c;或者具体开发板的官方#xff08;深圳市九鼎科技公司推出的…以下内容源于朱有鹏嵌入式课程的学习与整理如有侵权请告知删除。
uboot来源于uboot官网或者SoC官方研发s5pv210这款芯片的公司推出的开发板叫SMDKV210或者具体开发板的官方深圳市九鼎科技公司推出的、基于s5pv210芯片的X210开发板。本文以x210开发板为例详细分析uboot配置及编译阶段的流程。
uboot的主要目录与文件 主要文件包括/mkconfig/Makefile/config.mk。 主要文件夹有boardcpucommon、include。 board文件夹中每个子文件夹表示一个开发板cpu文件夹中每个子文件夹都是一个SoC系列。 uboot的配置与编译的步骤 1将源码解压在适当的目录下。 2配置即在uboot的根目录下执行“make x210_sd_config”。 3编译即在uboot的根目录下执行“make”或者“make -s”表示静默编译。 uboot的配置与编译的流程 下图是配置及编译阶段代码执行的具体流程。 对uboot主目录下的Makefile文件进行分析 1uboot的版本号。24~29行 VERSION 1
PATCHLEVEL 3
SUBLEVEL 4
EXTRAVERSION
U_BOOT_VERSION $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE $(obj)include/version_autogenerated.h 这四个变量的含义依次为主版本号、次版本号、再次版本号、附加的版本信息值为空可以给用户使用。U-Boot_VERSION这个变量的值为真正的uboot版本号易知其值为1.3.4。VERSION_FILE这个变量的值是一个.h文件注意是并行赋值的意思类似于Verilog语言中的。要注意:可以理解为串行赋值和的区别。$(obj)这个变量是在后面定义并赋值的其值是编译输出路径。version_autogenerated.h这个文件是在make之后自动生成的文件内容是一条宏这条宏给将其他.c文件提供uboot的版本号。2确定主机信息然后导出。31~43行 HOSTARCH : $(shell uname -m | \sed -e s/i.86/i386/ \-e s/sun4u/sparc64/ \-e s/arm.*/arm/ \-e s/sa110/arm/ \-e s/powerpc/ppc/ \-e s/ppc64/ppc/ \-e s/macppc/ppc/) HOSTARCH、HOSTOS分别表示主机的CPU架构和操作系统。makefile的函数调用与变量调用很类似格式是$( function arguments)其实上面一大段的意思是变量HOSTARCH的值是一个函数的返回值。shell是makefile中的一个函数$(shell XXX)会被解析成执行shell命令XXX此处是执行了一条 uname -m |sed -e ……符号 \是makefile的换行符。其中|是shell语法中的管道结构例如XXX | YYY 表达式XXX 的输出将作为表达式YYY的输入YYY的输出才是整句表达式的输出。uname -m 指令将输出负责编译的主机cpu架构比如ixx86sed -e是替换命令比如把ixx86替换为i386。由此可见这个HOSTARCH变量的值是负责编译的主机cpu架构。大部分情况下我们得到的都是i386。HOSTOS : $(shell uname -s | tr [:upper:] [:lower:] | \sed -e s/\(cygwin\).*/cygwin/)export HOSTARCH HOSTOS 这个HOSTOS变量和上一句HOSTARCH变量的原理类似管道第一部分uname -s会得到负责编译的主机的OS比如Linux。管道第二部分是将大写转换成小写。管道第三部分的意思是如果前面一个部分得到了cygwin系统则格式要转换一下。不必深究因为cygwin基本没人用……由此可见这个HOSTOS变量的值是负责编译的主机操作系统。大部分情况下我们得到的都是linux。导出两个变量到全局使其为环境变量让其他的文件也可以使用架构和系统信息。3实现静默编译功能。49~54行 # Allow for silent builds
ifeq (,$(findstring s,$(MAKEFLAGS)))
XECHO echo
else
XECHO :
endif 这整段是为了实现make的静默选项功能。其中findstring一个函数$(findstrings, $ (MAKEFLAGS))功能是从$(MAKEFLAGS)中找出字符‘s’。$(MAKEFLAGS)是make的flag选项如果在控制台中输入“make -s”则$(MAKEFLAGS)的值为‘s’。如果$(findstring $(MAKEFLAGS))没找到‘s’这个表达式的值为空则ifeq为真即make时无需静默。无需静默的实现方法是令变量XECHO值为关键字echo因为makefile中每次需要打印都会使用XECHO而不是直接使用echo本身。静默make的实现方法是令变量XECHO值为空当makefile需要打印时会调用XECHO由于其为空故无法打印make信息。注编译工具链的信息是永远打印的和make的静默选项无关。4设置各种路径。78~123行 makefile支持“单独外部路径编译”它的原理和keil把.o、.l、.bin、.a等中间文件放在单独的文件夹内的原理相同都是为了使源码更简洁明了防止被中间文件污染以及为了同时维护多个配置编译方式。有两种方式实现“单独外部路径编译”。方法一例如在控制台中输入“make O输出目录路径” 将输出文件夹的路径作为参数。方法二在Makefile中导出环境变量即“export BUILD_DIR输出目录路径”。方法一的优先级高会覆盖方法二而且方法一必须每次输入make时都要输入参数不论是make clean还是make config 的时候格式如“make O输出目录 disclean”。ifdef O
ifeq ($(origin O), command line)
BUILD_DIR : $(O)
endif
endififneq ($(BUILD_DIR),)
saved-output : $(BUILD_DIR) 上面这段是方法一的具体实现。如果make时输入参数“O输出目录”那么makefile会认为定义了变量O于是乎这段代码会开始执行。其中$(origin O)中origin是函数名$(origin O)的功能是返回变量O的来源由此可知如果O的来源是控制台命令则变量BUILD_DIR的值就是变量O的值。然后进行一个判断如果变量BUILD_DIR不为空则变量saved-output的值为BUILD_DIR即saved-output的值也是输出目录的路径。# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR}) 上面这句是shell语法中简写的if表达式其作用是当输出文件夹路径不存在时就创建它。其中包含两个表达式表达式1||表达式2。当表达式1为真时表达式2不会被解释器执行因为总结果一定为真尽管总的结果没有意义。唯有表达式1为假时解释器才会去执行表达式2这样就能用逻辑表达式来实现if语句的功能了。表达式1中方括号是固定用法是为了突出里面表达式是判断语句。-d是shell中判断路径是否存在的符号如果路径存在则为表达式1为真如果路径不存在表达式1为假解释器会执行表达式2即创建输出文件夹路径。# Verify if it was successful.
BUILD_DIR : $(shell cd $(BUILD_DIR) /bin/pwd)
$(if $(BUILD_DIR),,$(error output directory $(saved-output) does not exist))
endif # ifneq ($(BUILD_DIR),) 这几句代码是确保输出文件夹路径创建成功。的功能是连续执行两句语句当cd $(BUILD_DIR)执行完后执行/bin/pwd即打印当前路径。$(if xxxyyyzzz是makefile的判断函数如果xxx为真则执行yyy并返回值否则执行zzz并返回值。由此可知如果未成功创建BUILD_DIR就会输出错误打印信息。OBJTREE : $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE : $(CURDIR)
TOPDIR : $(SRCTREE)
LNDIR : $(OBJTREE)
export TOPDIR SRCTREE OBJTREE 这段代码是设置并导出了很多和路径有关的环境变量。如果BUILD_DIR不为空OBJTREE放产生的.o文件的值就为BUILD_DIR如果为空则OBJTREE的值就为CURDIR即current direction当前源码所在的目录。SRCTREE的值为当前源码所在目录TOPDIR的值为SRCTREE的值即当前源码所在目录LNDIR应该是放链接产生的文件的值和OBJTREE相同。MKCONFIG : $(SRCTREE)/mkconfig
export MKCONFIG 将变量MKCONFIG的值设置为当前源码目录下的mkconfig文件并导出为环境变量。这个shell脚本文件是正式make之前的配置脚本十分重要。ifneq ($(OBJTREE),$(SRCTREE))
REMOTE_BUILD : 1
export REMOTE_BUILD
endif 判断OBJTREE的值和SRCTREE的值是否不相等即判断是否使用了“单独外部路径编译”如果使用了这个功能则REMOTE_BUILD值为1并将其导出至全局。# $(obj) and (src) are defined in config.mk but here in main Makefile
# we also need them before config.mk is included which is the case for
# some targets like unconfig, clean, clobber, distclean, etc.
ifneq ($(OBJTREE),$(SRCTREE))
obj : $(OBJTREE)/
src : $(SRCTREE)/
else
obj :
src :
endif
export obj src 判断OBJTREE的值和SRCTREE的值是否不相等即判断是否使用了“单独外部路径编译”功能如果使用了这个功能 则将obj的值赋为OBJTREE的值将src的值赋为SRCTREE的值反之则值都为空。最后将他们全部导出至全局。5设置编译工具链。126~185行 ifeq ($(ARCH),powerpc)
ARCH ppc
endififeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk)) 开头三句是powerpc架构的名称转换。最后一句$(wildcard xxx) 参数xxx是一个文件名格式(可使用通配符)这个函数的返回值是一列和格式匹配且真实存在的文件的名称。但是这句应该没什么意义因为连endif都没有。# load ARCH, BOARD, and CPU configuration
include $(obj)include/config.mk
export ARCH CPU BOARD VENDOR SOC config.mk这个文件是在配置过程创建的 也就是“make x210_sd_config”这个目标在2588行时创建的。它会去执行/mkconfig脚本而/mkconfig脚本将创建include/config.mk并将参数填充进去。config.mk的内容分别定义了ARCH、CPU、BOARD、VENDOR、SOC这几个变量的值这些值来自主Makefile第2589行的配置项里的传参。ARCH arm
CPU s5pc11x
BOARD x210
VENDOR samsung
SOC s5pc110 通过把config.mk文件包含进来其内容将在本makefile中原地展开。主Makefile得到这几个变量值后再将它们导出到环境变量。ifndef CROSS_COMPILE
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE
else
ifeq ($(ARCH),ppc)
CROSS_COMPILE ppc_8xx-
endif
ifeq ($(ARCH),arm)
#CROSS_COMPILE arm-linux-
#CROSS_COMPILE /usr/local/arm/4.4.1-eabi-cortex-a8/usr/bin/arm-linux-
#CROSS_COMPILE /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux-
CROSS_COMPILE /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
endif
ifeq ($(ARCH),i386)
CROSS_COMPILE i386-linux-
endif
#中间略去
ifeq ($(ARCH),sparc)
CROSS_COMPILE sparc-elf-
endif # sparc
endif # HOSTARCH,ARCH
endif # CROSS_COMPILEexport CROSS_COMPILE 这上面一整段是配置交叉编译工具链的前缀即arm-none-linux-gnueabi- 一旦确定了前缀加上后缀就能定义在编译过程中用到的各种工具如ar、gcc等前缀的选择是通过前面获得的变量ARCH目标cpu的架构来判断的。# load other configuration
include $(TOPDIR)/config.mk 此处将/config.mk文件包含进来它将在原地展开继续对编译属性和链接属性进行设置。由于文件内容过多另辟文章讨论见博客uboot源码——根目录下的config.mk文件分析_天糊土的博客-CSDN博客注意此处的config.mk文件是源码自带的与x210_sd_config生成的include/config.mk不同。6设置规则。 OBJS cpu/$(CPU)/start.o
ifeq ($(CPU),i386)
OBJS cpu/$(CPU)/start16.o
OBJS cpu/$(CPU)/reset.o
endif
ifeq ($(CPU),ppc4xx)
OBJS cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc85xx)
OBJS cpu/$(CPU)/resetvec.o
endifOBJS : $(addprefix $(obj),$(OBJS)) 这里将众多.o文件赋给了OBJS变量这个变量会成为后面目标u-boot的依赖。其中用到了多次“”赋值符号此赋值符号的含义其实是在变量原本的值后面在续上新的值就是额外添加的意思。LIBS lib_generic/libgeneric.a
LIBS $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \board/$(VENDOR)/common/lib$(VENDOR).a; fi)
LIBS cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS cpu/$(CPU)/$(SOC)/lib$(SOC).a
endif
ifeq ($(CPU),ixp)
LIBS cpu/ixp/npe/libnpe.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 drivers/spi/libspi.a
ifeq ($(CPU),mpc83xx)
LIBS drivers/qe/qe.a
endif
ifeq ($(CPU),mpc85xx)
LIBS drivers/qe/qe.a
endif
LIBS drivers/rtc/librtc.a
#略去LIBS : $(addprefix $(obj),$(LIBS))
.PHONY : $(LIBS) $(VERSION_FILE)LIBBOARD board/$(BOARDDIR)/lib$(BOARD).a
LIBBOARD : $(addprefix $(obj),$(LIBBOARD))# Add GCC lib
PLATFORM_LIBS -L $(shell dirname $(CC) $(CFLAGS) -print-libgcc-file-name) -lgcc 将众多.a库文件赋给了LIBS变量以及将和板子有关的.a文件赋给了LIBBOARD变量这两个变量会成为后面目标u-boot的依赖。# The tools are needed early, so put this first
# Dont include stuff already done in $(LIBS)
SUBDIRS tools \examples \api_examples.PHONY : $(SUBDIRS)ifeq ($(CONFIG_NAND_U_BOOT),y)
NAND_SPL nand_spl
U_BOOT_NAND $(obj)u-boot-nand.bin
endififeq ($(CONFIG_ONENAND_U_BOOT),y)
ONENAND_IPL onenand_bl1
U_BOOT_ONENAND $(obj)u-boot-onenand.bin
endif__OBJS : $(subst $(obj),,$(OBJS))
__LIBS : $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD)) 根据autoconf.mk中nand和onenand的CONFIG做了一个判断是否使用相应的.bin文件。ALL $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND) $(obj)u-boot.dis
ifeq ($(ARCH),blackfin)
ALL $(obj)u-boot.ldr
endifall: $(ALL) 本段出现了顶层makefile的第一条规则即目标-依赖-操作故默认情况下将以all这个变量作为最终目标。由于本条规则没有任何操作 因此一旦把依赖也就是$(ALL)实现了整个makefile文件的最终目标就达成了。可以认为本makefile的终极目标其实是$(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 binary $ $#略$(obj)System.map: $(obj)u-boot$(NM) $ | \grep -v \(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\) | \sort $(obj)System.map这些都是为了产生最终文件的规则。# Auto-generate the autoconf.mk file (which is included by all makefiles)
#
# This target actually generates 2 files; autoconf.mk and autoconf.mk.dep.
# the dep file is only include in this top level makefile to determine when
# to regenerate the autoconf.mk file.
$(obj)include/autoconf.mk.dep: $(obj)include/config.h include/common.h$(XECHO) Generating $ ; \set -e ; \: Generate the dependancies ; \$(CC) -x c -DDO_DEPS_ONLY -M $(HOST_CFLAGS) $(CPPFLAGS) \-MQ $(obj)include/autoconf.mk include/common.h $$(obj)include/autoconf.mk: $(obj)include/config.h$(XECHO) Generating $ ; \set -e ; \: Extract the config macros ; \$(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h | \sed -n -f tools/scripts/define2mk.sed $sinclude $(obj)include/autoconf.mk.dep 本段的功能是根据include/configs/x210_sd.h来生成autoconf.mkmakefile利用这些autoconf.mk中的变量来指导编译过程的走向条件编译。7设置与cpu相关的伪目标。 由于这些代码都与cpu本身有关有2000多行且功能重复我们挑选板子上的s5pv210为例子来分析这行代码大概位于2589行。 x210_sd_config : unconfig$(MKCONFIG) $(:_config) arm s5pc11x x210 samsung s5pc110echo TEXT_BASE 0xc3e00000 $(obj)board/samsung/x210/config.mk 本段代码主要负责编译之前的配置过程即在控制台输入“make x210_sd_config”。其依赖是unconfig此变量代表未配置的意思通过这个方法我们便可以多次配置。MKCONFIG这个变量代表的是源码目录下最关键的一个shell文件即mkconfig这个shell文件负责了make之前的配置过程。行首的代表静默执行这段代码在执行$(MKCONFIG)前还把$(:_config)、arm、s5pc11x、x210、samsung、s5pc110这6个主要参数传给了mkconfig。其中参数$(:_config)是引用了一个替换函数将该规则中的目标用表示中的_config用空替换故$(:_config)的值为“x210_sd”。最后把TEXT_BASE的值填充入config.mk文件指定uboot的虚拟链接地址完成所有配置工作。关于mkconfig文件见博客uboot源码——根目录下的mkconfig文件分析_天糊土的博客-CSDN博客。