本文以smdk2410为例子说明uboot的生成过程
一 uboot生成
uboot生成步骤如下:
make smdk2410_defconfig
make all
二 uboot生成分析之make smdk2410_defconfig
主Makefile有如下定义:
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
注:u-boot-2015.04的配置与编译仿照linux重新设计,很多宏展开与linux相同,不再重新说明。
(1)目标
%config,即smdk2410_defconfig
(2)依赖
(2.1)scripts_basic
主Makefile有如下定义:
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount
可以转换为如下形式:
scripts_basic:
make -f scripts/Makefile.build obj=scripts/basic
rm -f .tmp_quiet_recordmcount
相当于make执行scripts/Makefile.build,并设置参数scripts/basic
在scripts/Makefile.build中有如下定义:
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y))
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target))
$(subdir-ym) $(always)
@:
其中:依赖仅仅always为fixdep,其他为空。
至于fixdep的生成过程,这里不详细说明,详见linux的make s3c2410_defconfig说明。
(2.2)outputmakefile
为空
(3)$(Q)$(MAKE) $(build)=scripts/kconfig $@
相当于make -f scripts/Makefile.build obj=scripts/kconfig smdk2410_defconfig
相当于make执行scripts/Makefile.build的smdk2410_defconfig标号,并设置obj为scripts/kconfig
其中scripts/Makefile.build包含了scripts/kconfig/Makefile,并在其中有这样的定义:
%_defconfig: $(obj)/conf
$(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
其中,SRCARCH := ..
可以转换为如下:
smdk2410_defconfig: scripts/kconfig/conf
scripts/kconfig/conf --defconfig=configs/smdk2410_defconfig Kconfig
相当于执行scripts/kconfig/conf程序,并输入参数--defconfig=configs/smdk2410_defconfig Kconfig
该程序会根据smdk2410的设置将配置信息综合写入主目录下的.config文件。
至于conf如何生成这里不再详述。
(4)分析总结
make smdk2410_defconfig执行如下操作:
(a)构造scripts/basic/fixdep
(b)构造scripts/kconfig/conf
(c)scripts/kconfig/conf --defconfig=configs/smdk2410_defconfig Kconfig
(5)scripts/kconfig/conf的分析
会依次解析configs/smdk2410_defconfig和Kconfig,生成symbol等列表,最后生成.config文件。
注:conf程序过于复杂,在不影响移植的情况下暂且不去分析该程序。
三 uboot生成分析之make all
主Makefile有如下定义:
all: $(ALL-y)
ALL-y += u-boot.srec u-boot.bin System.map binary_size_check
其中,我们主要分析u-boot.bin,其他暂时不分析。
主Makefile有如下定义:
u-boot.bin: u-boot FORCE
$(call if_changed,objcopy)
$(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))
$(BOARD_SIZE_CHECK)
(1)u-boot
主Makefile有如下定义:
u-boot: $(u-boot-init) $(u-boot-main) u-boot.lds
$(call if_changed,u-boot__)
(1.1)u-boot-init
主Makefile有如下定义:
u-boot-init := $(head-y)
主Makefile包含arch/arm/Makefile,在其中有如下定义:
head-y := arch/arm/cpu/$(CPU)/start.o
所以,u-boot-init即arch/arm/cpu/arm/start.o
(1.2)u-boot-main
主Makefile有如下定义:
u-boot-main := $(libs-y)
lib-y项目较多,具体就是一些目录下编译链接到一起的built-in.o,详见附录。
(1.3)u-boot.lds
主Makefile有如下定义:
u-boot.lds: $(LDSCRIPT) prepare FORCE
$(call if_changed_dep,cpp_lds)
(1.3.1)LDSCRIPT
主Makefile中有如下定义:
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
注:由于对于SMDK2410,LDSCRIPT和CONFIG_SYS_LDSCRIPT未定义,所以忽略部分内容。
(1.3.1.1)第一个if
首先看一下BOARDDIR定义的情况,config.mk中定义了它,但首先需要是否包含该目录。
主Makefile有如下定义:
ifneq ($(wildcard include/config/auto.conf),)
autoconf_is_old := $(shell find . -path ./$(KCONFIG_CONFIG) -newer
include/config/auto.conf)
ifeq ($(autoconf_is_old),)
include $(srctree)/config.mk
include $(srctree)/arch/$(ARCH)/Makefile
endif
endif
其中,文件include/config/auto.conf存在,KCONFIG_CONFIG为.config。
当.config比include/config/auto.conf新的时候,会返回.config。对于SMDK2410,.config先生成,autoconf_is_old为空。
因此包含了config.mk。在config.mk有如下定义:
VENDOR := $(CONFIG_SYS_VENDOR:"%"=%)
BOARD := $(CONFIG_SYS_BOARD:"%"=%)
ifneq ($(BOARD),)
ifdef VENDOR
BOARDDIR = $(VENDOR)/$(BOARD)
else
BOARDDIR = $(BOARD)
endif
endif
在include/config/auto.conf有如下定义:
CONFIG_SYS_BOARD="smdk2410"
CONFIG_SYS_VENDOR="samsung"
所以BOARDDIR=samsung/smdk2410,
这时LDSCRIPT := board/smdk2410/u-boot.lds,不存在这个文件,进入下一个if。
(1.3.1.2)第二个if
在主config.mk下有定义如下
CPU := $(CONFIG_SYS_CPU:"%"=%)
CPUDIR=arch/$(ARCH)/cpu$(if $(CPU),/$(CPU),)
在include/config/auto.conf有如下定义:
CONFIG_SYS_CPU="arm920t"
$(arm920t)为空
转化为如下形式:
CPUDIR=arch/arm/cpu
存在arch/arm/cpu/u-boot.lds这个文件,不会进入下个if,LDSCRIPT为arch/arm/cpu/u-boot.lds。
(1.3.2)prepare
主Makefile有如下定义
prepare: prepare0
prepare0: archprepare FORCE
$(Q)$(MAKE) $(build)=.
archprepare: prepare1 scripts_basic
prepare1: prepare2 $(version_h) $(timestamp_h) include/config/auto.conf
prepare2: prepare3 outputmakefile
prepare3: include/config/uboot.release
outputmakefile为空
其中,scripts_basic实质是生成fixdep docproc这个的过程,在配置已经生成,这里可以忽略了。
prepare这个伪目标执行的动作如下:
prepare0: include/config/uboot.release include/generated/version_autogenerated.h include/generated/timestamp_autogenerated.h include/config/auto.conf scripts_basic
make -f scripts/Makefile.build obj=.
又是要执行Makefile.build,这次包含了主目录下的Kbuild,其中always为include/generated/generic-asm-offsets.h,实质是生成该文件的过程,主目录下的Kbuild有该文件的标号,这里不详细说明了。
(1.3.3)$(call if_changed_dep,cpp_lds)
实质是执行了cmd_cpp_lds,然后生成一个依赖文件。
主Makefile有如下定义:
cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) -ansi
-D__ASSEMBLY__ -x assembler-with-cpp -P -o $@ $<
其中CPP为arm-linux-gcc -E -Wp,-MD,.u-boot.lds.d $(LDPPFLAGS) $(LDPPFLAGS) -ansi
-D__ASSEMBLY__ -x assembler-with-cpp -P -o u-boot.lds arch/arm/cpu/u-boot.lds
意思大概是将arch/arm/cpu/u-boot.lds拷贝到主目录下,并其在其中进行宏展开。
(1.4)$(call if_changed,u-boot__)
相当于执行cmd_u-boot__,在主Makefile有如下定义:
cmd_u-boot__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_u-boot) -o $@
-T u-boot.lds $(u-boot-init)
--start-group $(u-boot-main) --end-group
$(PLATFORM_LIBS) -Map u-boot.map
具体不展开了,这里可以清晰看出是将u-boot-init和u-boot-main内容按照u-boot.lds指定的方式链接,并生成u-boot.map文件。
(2)$(call if_changed,objcopy)
执行cmd_objcopy,主Makefile有如下定义:
cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
转换为:
arm-linux-objcopy -O binary u-boot u-boot.bin
实质是将elf格式的u-boot转换为计算机可以直接识别的二进制文件u-boot.bin
(3)后两个命令
由于没有对应宏定义,后两行实际未执行任何内容。
(4)u-boot-init u-boot-main的生成
(4.1)u-boot-main
主Makefile有如下定义:
u-boot-dirs := $(patsubst %/,%,$(filter %/, $(libs-y))) tools examples
可以知道u-boot-dirs为u-boot-main的内容的目录名,并加上tools和examples
$(sort $(u-boot-init) $(u-boot-main)): $(u-boot-dirs) ;
$(u-boot-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
以disk/built-in.o(u-boot-main中的一项)为例子说明(其他同理),并转化为:
disk: prepare scripts
make -f ./scripts/Makefile.build obj=disk
(4.1.1)依赖文件
perpare和scripts依赖文件,一再起前面说明,主要是生成一些准备文件。
(4.1.2)make -f ./scripts/Makefile.build obj=disk
再次执行scripts/Makefile.build下的__build。由于disk/Kbuild不存在,因此scripts/Makefile.build包含disk/Makfile。
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y))
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target))
$(subdir-ym) $(always)
@:
(4.1.2.1)obj-y以及生成过程
obj-y可以根据disk/Makfile和配置文件(应该是auto.conf和autoconf.mk)得知,obj-y为disk/part.o和disk/part_dos.o
scripts/Makefile.build有如如下定义:
$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
$(call cmd,force_checksrc)
$(call if_changed_rule,cc_o_c)
Kbulid中如下定义
cmd = @$(echo-cmd) $(cmd_$(1)) ##实质执行了cmd_force_checksrc
if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) )@set -e; $(rule_$(1))) ##如果改变执行cmd_cc_o_c
实质是执行如下动作:
cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
第一行是检测代码,CHECK实质是检测代码的工具,具体暂时不深入分析。
第二行是一个arm-linux-gcc生成.o文件的过程。
(4.1.2.2)builtin-target
在scripts/Makefile.build有如下定义:
ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)
builtin-target := $(obj)/built-in.o
endif
可以知道builtin-target := disk/built-in.o。builtin-target有如下定义:
$(builtin-target): $(obj-y) FORCE
$(call if_changed,link_o_target)
设置是执行cmd_link_o_target
cmd_link_o_target = $(if $(strip $(obj-y)),
$(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^)
$(cmd_secanalysis),
rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@)
能看处这里就是把obj-y(disk/part.o和disk/part_dos.o)链接成disk/built-in.o的过程。
(4.1.2.3)其他依赖
其他依赖均为空
(4.2)u-boot-init
参考上面u-boot-main的执行过程,如果是在arch/arm/cpu/arm920t执行相比disk目录执行,extra-y不再为空(arch/arm/cpu/arm920t/Makefile下有定义),而是start.o。并且在scripts/Makefile.build有如下定义:
$(obj)/%.o: $(src)/%.S FORCE
$(call if_changed_dep,as_o_S)
可以转化为:
arch/arm/cpu/arm920t/start.o: arch/arm/cpu/arm920t/start.S FORCE
$(call if_changed_dep,as_o_S)
相当于执行cmd_as_o_S
cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
这样便生成了start.o
附录A:
u-boot-init和u-boot-main的内容
u-boot-init:
arch/arm/cpu/arm920t/start.o
u-boot-main:
arch/arm/cpu/built-in.o arch/arm/cpu/arm920t/built-in.o arch/arm/lib/built-in.o board/samsung/common/built-in.o board/samsung/smdk2410/built-in.o common/built-in.o disk/built-in.o drivers/built-in.o drivers/dma/built-in.o drivers/gpio/built-in.o drivers/i2c/built-in.o drivers/mmc/built-in.o drivers/mtd/built-in.o drivers/mtd/nand/built-in.o drivers/mtd/onenand/built-in.o drivers/mtd/spi/built-in.o drivers/mtd/ubi/built-in.o drivers/net/built-in.o drivers/net/phy/built-in.o drivers/pci/built-in.o drivers/power/built-in.o drivers/power/battery/built-in.o drivers/power/fuel_gauge/built-in.o drivers/power/mfd/built-in.o drivers/power/pmic/built-in.o drivers/serial/built-in.o drivers/spi/built-in.o drivers/usb/eth/built-in.o drivers/usb/gadget/built-in.o drivers/usb/host/built-in.o drivers/usb/musb-new/built-in.o drivers/usb/musb/built-in.o drivers/usb/phy/built-in.o drivers/usb/ulpi/built-in.o fs/built-in.o lib/built-in.o net/built-in.o test/built-in.o test/dm/built-in.o
附录B
disk/part.c转化为disk/part.o的命令
arm-linux-gcc -Wp,-MD,disk/.part.o.d -nostdinc -isystem /home/zcy/arm-linux-gcc/opt/FriendlyARM/toolschain/4.4.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.4.3/include -Iinclude -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -DCONFIG_SYS_TEXT_BASE=0x0 -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -Os -fno-stack-protector -g -Wno-format-nonliteral -D__ARM__ -marm -mno-thumb-interwork -mabi=aapcs-linux -mword-relocations -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -msoft-float -pipe -march=armv4 -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(part)" -D"KBUILD_MODNAME=KBUILD_STR(part)" -c -o disk/part.o disk/part.c
上一篇:u-boot移植之三 uboot-2015.04的移植过程
下一篇:linux内核移植之一 linux-4.1.4的zImage生成(Makefile分析)
推荐阅读最新更新时间:2024-10-31 13:52
设计资源 培训 开发板 精华推荐
- AM2G-0507DH30Z ±7.2V 2 瓦 DC/DC 转换器的典型应用
- FT32_Simple
- DL18-0615 高精度VFD时钟
- 使用 ON Semiconductor 的 CAT4134 的参考设计
- AD5313 双轨至轨电压输出、10 位 DAC 的典型应用
- AM1/4S-4824SZ 24V 0.25 瓦 DC/DC 转换器的典型应用
- 用于开/关控制应用的 AM2G-1209SH30Z 9V 2 瓦 DC-DC 转换器的典型应用
- AM6TW-4809DH35Z ±9V 6 瓦双路输出 DC/DC 转换器的典型应用
- 使用 NXP Semiconductors 的 TL431AI 的参考设计
- unsurv offline:开源、隐私、紧凑型 GNSS 接收器,带有 ESP32 和 NFC(原理图和PCB等)
- MicroPython抢鲜玩 Python遇上MCU=? 由你定
- BeagleBone Black 开发板 DIY 创意设计大赛
- 看视频赢京东卡|泰克示波器视频学习中心重磅上线!
- 有奖直播:借助Maxim的模拟技术优化设计
- 报名、参会赢京东卡:意法半导体 NFC 研讨会2024-北京站
- 你评论,我送礼!《玩转TI MSP430 Launchpad》TI社区与EEWORLD联合首发!
- 帮忙他人,成就自我——EEWORLD问答榜(10期)
- 观看安森美半导体高灵敏度触摸传感器应用视频,轻松答题赢好礼!
- 如何用3个关键步骤,来确保下一代设计安全性,深入解读嵌入式设备DeepCover加密控制器,看视频答题赢好礼!