i.MX6Q - u-boot_2016
飞凌嵌入式开发板 OKMX6Q_C 1G-DDR, 8G-EMMC版本。
# U-boot-2016.03
# 配置
make mx6q-c-sabresd_defconfig
# 编译
make -j4
# 结果:
# u-boot u-boot.bin u-boot.imx u-boot-nodtb.bin
# u-boot.lds u-boot.map System.map u-boot.sym
#
第一:分析 生成的文件的关系
1、u-boot u-boot.bin u-boot-nodtb.bin u-boot.imx
先看文件大小属性:
-rwxrwxr-x 1 hp hp 2.8M Sep 26 06:43 u-boot
-rwxrwxr-x 1 hp hp 481K Sep 26 06:43 u-boot.bin
-rw-rw-r-- 1 hp hp 487K Sep 26 06:43 u-boot.imx
-rwxrwxr-x 1 hp hp 481K Sep 26 06:43 u-boot-nodtb.bin
u-boot.bin和u-boot-nodtb.bin大小相同,diff工具比较完全相同。说明两个是同一个文件。
u-boot文件是最大的,包含一些debug信息等。u-boot.bin u-boot.imx u-boot-nodtb.bin是由u-boot生成的。
最终烧录到emmc中的是 u-boot.imx。可以猜测u-boot.imx是由u-boot.bin生成的, 而u-boot.imx多出的数据跟NXP相关。这里先说生成命令,如下:
./tools/mkimage -n board/freescale/mx6sabresd/mx6q_sabresd_c_1g.cfg.cfgtmp -T imximage -e 0x17800000 -d u-boot.bin u-boot.imx
2、u-boot.lds u-boot.map System.map u-boot.sym
u-boot.lds是u-boot的链接脚本,u-boot.map 即是按照u-boot.lds编译生成的map信息。
System.map 只有各符号和对应的地址,应该是由u-boot.map生成而来。
u-boot.sym 内容较System.map多一些,猜测也是由u-boot.map生成而来。
u-boot.map u-boot.sym System.map 都是由u-boot.lds生成而来。
那u-boot.lds怎么来的呢?
这里先说下结论,这里的源u-boot.lds位置在 arch/arm/cpu/u-boot.lds,不同架构位置可能不同。
第二:简单分析配置具体的动作
问题1:执行命令 make mx6q-c-sabresd_defconfig 系统做了什么?
# 打开命令细节显示开关, V=1
# 重新执行命令
hp:~/imx6q/u-boot-2016.03$ make mx6q-c-sabresd_defconfig V=1
make -f ./scripts/Makefile.build obj=scripts/basic
cc -Wp,-MD,scripts/basic/.fixdep.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -o scripts/basic/fixdep scripts/basic/fixdep.c
rm -f .tmp_quiet_recordmcount
make -f ./scripts/Makefile.build obj=scripts/kconfig mx6q-c-sabresd_defconfig
cc -Wp,-MD,scripts/kconfig/.conf.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -D_GNU_SOURCE -DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1 -DLOCALE -c -o scripts/kconfig/conf.o scripts/kconfig/conf.c
cc -Wp,-MD,scripts/kconfig/.zconf.tab.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -D_GNU_SOURCE -DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1 -DLOCALE -Iscripts/kconfig -c -o scripts/kconfig/zconf.tab.o scripts/kconfig/zconf.tab.c
cc -o scripts/kconfig/conf scripts/kconfig/conf.o scripts/kconfig/zconf.tab.o
scripts/kconfig/conf --defconfig=arch/../configs/mx6q-c-sabresd_defconfig Kconfig
#
# configuration written to .config
#
可以看出执行完 make mx6q-c-sabresd_defconfig 后,系统其实执行了如下:
1、make -f ./scripts/Makefile.build obj=scripts/basic
2、make -f ./scripts/Makefile.build obj=scripts/kconfig mx6q-c-sabresd_defconfig
由上可知:
第一条指令生成了,scripts/basic/fixdep 。
第二条指令生成了,scripts/kconfig/conf 。
最后生成 .config 的命令是:
scripts/kconfig/conf --defconfig=arch/../configs/mx6q-c-sabresd_defconfig Kconfig
scripts/kconfig/conf 传入两个参数,--defconfig=arch/../configs/mx6q-c-sabresd_defconfig 和 Kconfig 。
所以可以理解为,执行完配置命令(make mx6q-c-sabresd_defconfig), 先编译生成可执行文件 scripts/kconfig/conf 。由scripts/kconfig/conf生成最终需要的 .config 。而arch/…/configs/mx6q-c-sabresd_defconfig 是一个配置文件,打开内容如下:
hp:~/imx6q/u-boot-2016.03$ cat configs/mx6q-c-sabresd_defconfig
CONFIG_ARM=y
CONFIG_ARCH_MX6=y
CONFIG_TARGET_MX6SABRESD=y
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6sabresd/mx6q_sabresd_c_1g.cfg,MX6Q,SYS_USE_SPINOR,MAIN_BOARD_IS_C,CPU_TYPE_IS_Q"
CONFIG_CMD_GPIO=y
第三:分析 编译过程
首先,编译执行的命令: make -j4 ,后面 -j 指同时几个cpu编译。所以编译指令是 make 。也就是执行命令的编译目标。打开Makefile, 寻找默认的目标(也是第一个编译目标):
# That's our default target when none is given on the command line
PHONY := _all
_all:
但是默认目标并没有任何执行命令。继续搜索以及依赖, 结果如下:
PHONY += all
ifeq ($(KBUILD_EXTMOD),)
_all: all
else
_all: modules
endif
.......
all: $(ALL-y)
# Always append ALL so that arch config.mk's can add custom ones
ALL-y += u-boot.srec u-boot.bin u-boot.sym System.map u-boot.cfg binary_size_check
ALL-$(CONFIG_ONENAND_U_BOOT) += u-boot-onenand.bin
ifeq ($(CONFIG_SPL_FSL_PBL),y)
ALL-$(CONFIG_RAMBOOT_PBL) += u-boot-with-spl-pbl.bin
else
ifneq ($(CONFIG_SECURE_BOOT), y)
# For Secure Boot The Image needs to be signed and Header must also
# be included. So The image has to be built explicitly
ALL-$(CONFIG_RAMBOOT_PBL) += u-boot.pbl
endif
endif
ALL-$(CONFIG_SPL) += spl/u-boot-spl.bin
ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot.img
ALL-$(CONFIG_TPL) += tpl/u-boot-tpl.bin
ALL-$(CONFIG_OF_SEPARATE) += u-boot.dtb
ifeq ($(CONFIG_SPL_FRAMEWORK),y)
ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb.img
endif
ALL-$(CONFIG_OF_HOSTFILE) += u-boot.dtb
ifneq ($(CONFIG_SPL_TARGET),)
ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
endif
ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf
ALL-$(CONFIG_EFI_APP) += u-boot-app.efi
ALL-$(CONFIG_EFI_STUB) += u-boot-payload.efi
ifneq ($(BUILD_ROM),)
ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
endif
# enable combined SPL/u-boot/dtb rules for tegra
ifeq ($(CONFIG_TEGRA)$(CONFIG_SPL),yy)
ALL-y += u-boot-tegra.bin u-boot-nodtb-tegra.bin
ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb-tegra.bin
endif
# Add optional build target if defined in board/cpu/soc headers
ifneq ($(CONFIG_BUILD_TARGET),)
ALL-y += $(CONFIG_BUILD_TARGET:"%"=%)
endif
可以看出 u-boot.bin 是必须编译的。下面找出u-boot.bin目标的定义
ifeq ($(CONFIG_OF_SEPARATE),y)
u-boot-dtb.bin: u-boot-nodtb.bin dts/dt.dtb FORCE
$(call if_changed,cat)
u-boot.bin: u-boot-dtb.bin FORCE
$(call if_changed,copy)
else
u-boot.bin: u-boot-nodtb.bin FORCE
$(call if_changed,copy)
endif
根据 CONFIG_OF_SEPARATE 的定义,u-boot.bin的定义有两个,由最后生成的结果看,这里的配置文件是没有定义 CONFIG_OF_SEPARATE 的。所以接下来搜索 u-boot-nodtb.bin 的定义。
u-boot-nodtb.bin: u-boot FORCE
$(call if_changed,objcopy)
$(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))
$(BOARD_SIZE_CHECK)
这里可以看出 u-boot.bin和u-boot-nodtb.bin 是同一个文件,都是从 u-boot 生成来的。
接下来搜索 u-boot 的定义:
u-boot: $(u-boot-init) $(u-boot-main) u-boot.lds FORCE
$(call if_changed,u-boot__)
接下来就是 ( u − b o o t − i n i t ) 、 (u-boot-init)、 (u−boot−init)、(u-boot-main)和 u-boot.lds的定义:
u-boot-init := $(head-y)
u-boot-main := $(libs-y)
head-y的定义全局搜索,跟架构有关,所以这里使用的是arch/arm/Makefile 中定义的 head-y, 如下:
head-y := arch/arm/cpu/$(CPU)/start.o
libs-y 的定义就在根目录下的Makefile中,如下:
libs-y += lib/
libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
libs-$(CONFIG_OF_EMBED) += dts/
libs-y += fs/
libs-y += net/
libs-y += disk/
libs-y += drivers/
libs-y += drivers/dma/
libs-y += drivers/gpio/
libs-y += drivers/i2c/
libs-y += drivers/mmc/
libs-y += drivers/mtd/
libs-$(CONFIG_CMD_NAND) += drivers/mtd/nand/
libs-y += drivers/mtd/onenand/
libs-$(CONFIG_CMD_UBI) += drivers/mtd/ubi/
libs-y += drivers/mtd/spi/
libs-y += drivers/net/
libs-y += drivers/net/phy/
libs-y += drivers/pci/
libs-y += drivers/power/ \
drivers/power/fuel_gauge/ \
drivers/power/mfd/ \
drivers/power/pmic/ \
drivers/power/battery/ \
drivers/power/regulator/
libs-y += drivers/spi/
libs-$(CONFIG_FMAN_ENET) += drivers/net/fm/
libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
libs-$(CONFIG_ALTERA_SDRAM) += drivers/ddr/altera/
libs-y += drivers/serial/
libs-y += drivers/usb/dwc3/
libs-y += drivers/usb/emul/
libs-y += drivers/usb/eth/
libs-y += drivers/usb/gadget/
libs-y += drivers/usb/gadget/udc/
libs-y += drivers/usb/host/
libs-y += drivers/usb/musb/
libs-y += drivers/usb/musb-new/
libs-y += drivers/usb/phy/
libs-y += drivers/usb/ulpi/
libs-y += cmd/
libs-y += common/
libs-$(CONFIG_API) += api/
libs-$(CONFIG_HAS_POST) += post/
libs-y += test/
libs-y += test/dm/
libs-$(CONFIG_UT_ENV) += test/env/
libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
libs-y := $(sort $(libs-y))
libs-y := $(patsubst %/, %/built-in.o, $(libs-y))
u-boot.lds的定义如下:
u-boot.lds: $(LDSCRIPT) prepare FORCE
$(call if_changed_dep,cpp_lds)
# If board code explicitly specified LDSCRIPT or CONFIG_SYS_LDSCRIPT, use
# that (or fail if absent). Otherwise, search for a linker script in a
# standard location.
ifndef LDSCRIPT
#LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot.lds.debug
ifdef CONFIG_SYS_LDSCRIPT
# need to strip off double quotes
LDSCRIPT := $(srctree)/$(CONFIG_SYS_LDSCRIPT:"%"=%)
endif
endif
# If there is no specified link script, we look in a number of places for it
ifndef LDSCRIPT
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/$(CPUDIR)/u-boot.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/arch/$(ARCH)/cpu/u-boot.lds
endif
endif
这里没有定义LDSCRIPT,也没有定义 CONFIG_SYS_LDSCRIPT。
wildcard意思是展开宏。
ifeq ($(wildcard $(LDSCRIPT)),) 这句话意思是判断 LDSCRIPT 宏展开是否为空。
所以这里其实在按顺序寻找链接文件的。
首先是 $(srctree)/board/$(BOARDDIR)/u-boot.lds, 然后是$(srctree)/$(CPUDIR)/u-boot.lds, 最后是$(srctree)/arch/$(ARCH)/cpu/u-boot.lds。
这里前两个都不存在,最后一个目录存在,所以链接用的u-boot.lds 使用的是 $(srctree)/arch/$(ARCH)/cpu/u-boot.lds 。
在这里就是arch/arm/cpu/u-boot.lds。