编译U-boot主要分两步:
make TQ210_config ;
make all;
第一步:
TQ210_config : unconfig
@$(MKCONFIG) $(@:_config=) arm s5pv210 TQ210 EmbedSky s5pv210
@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/EmbedSky/TQ210/config.mk(@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/$5/$1/config.mk)
unconfig:删除一次生成的config.h,config.mk ,config.tmp,autoconf.mk ,autoconf.mk.dep ,config.mk
@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 \
$(obj)board/$(VENDOR)/$(BOARD)/config.mk
@$(MKCONFIG) $(@:_config=) arm s5pv210 TQ210 EmbedSky s5pv210
等效于:./mkconfig TQ210 arm s5pv210 TQ210 EmbedSky s5pv210
BOARD_NAME=TQ210
echo "Configuring for ${BOARD_NAME} board..."
cd ./include以下均在include目录下操作
rm -f asm
ln -s asm-arm asm(ln -s asm-$2 asm)
rm -f asm-arm /arch(rm -f asm-$2/arch)
ln -s arch-s5pv210 asm-arm/arch(ln -s ${LNPREFIX}arch-$6 asm-$2/arch) ${LNPREFIX}未定义,为空
rm -f regs.h
ln -s s5pv210.h regs.h(ln -s $6.h regs.h)
rm -f asm-arm/arch(rm -f asm-$2/arch)
ln -s arch-s5pv210 asm-arm/arch(ln -s arch-$3 asm-$2/arch)
rm -f asm-arm/proc(rm -f asm-$2/proc)
ln -s proc-armv asm-arm/proc(ln -s ${LNPREFIX}proc-armv asm-$2/proc)
> config.mk
ARCH = arm
CPU = s5pv210
BOARD = TQ210
VENDOR = EmbedSky
SOC = s5pv210
#include <configs/TQ210 .h>" >>config.h 配置选项(echo "/* Automatically generated - do not edit */" >>config.h echo "#include <configs/$1.h>" >>config.h)
echo "TEXT_BASE = 0xc3e00000" > $(obj)board/EmbedSky/TQ210/config.mk 代码段地址
产生如下结果:
1)确定开发板名称BOARD_NAME=TQ210($1),会建立include/configs/BOARD_NAME .h文件,用来作为配置文件,并将#include <configs/TQ210 .h>" >>include/config.h
2)创建ARCH/SOC相关头文件的链接
3)将ARCH = arm; CPU = s5pv210;BOARD = TQ210 ;VENDOR = EmbedSky;SOC = s5pv210写入include目录下创建的 config.mk文件中
第二步 make all
配置完成后,执行make all 即可编译;
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
LDR = $(CROSS_COMPILE)ldr
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB = $(CROSS_COMPILE)RANLIB
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
OBJCFLAGS += --gap-fill=0xff
LDFLAGS += -Bstatic -T $(LDSCRIPT) $(PLATFORM_LDFLAGS)
all: $(ALL)
ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND) $(obj)u-boot.dis
include $(TOPDIR)/config.mk
CROSS_COMPILE = arm-linux-
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJCFLAGS += --gap-fill=0xff 段之间的空隙用0xff填充
VERSION_FILE = $(obj)include/version_autogenerated.h
SUBDIRS = tools examples api_examples
MAKE="make CROSS_COMPILE=${CROSS_COMPILE}"
完配置我们再回到Makefile中来看看编译与链接,面对Makefile的时候首先我们就会想到最后的目标文件u-boot.bin(通常情况下我们都是使用u-boot.bin的,因此这里我也只是介绍它,实际上可以烧到板子上的有很多种格式的,如.srec等等)是怎样产生的:
$(obj)u-boot.bin: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
$(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT)
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) \
-Map u-boot.map -o u-boot
depend dep: $(VERSION_FILE)
for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir _depend ; done
生成$(SUBDIRS)中的每个子目录的.depend文件,这个.depend文件中记录了每个目标文件的依赖文件,因此,修改了某一个文件后,基于这个.depend文件才可以对所有的依赖文件进行重新编译,生产的方法如上:进入子目录中执行make _depend
$(SUBDIRS): depend $(obj)include/autoconf.mk
$(MAKE) -C $@ all
进入cpu/$(cpu)目录中执行make
$(OBJS): depend $(obj)include/autoconf.mk
$(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))
对每个lib成员,都将进入响应的子目录执行MAKE命令
$(LIBS): depend $(obj)include/autoconf.mk
$(MAKE) -C $(dir $(subst $(obj),,$@))
$(LD) $(LDFLAGS) : arm-linux- ld += -Bstatic -T /board/$(BOARDDIR)/u-boot.-Ttext $(TEXT_BASE)确定了程序的布局及地址。
总结:1:首先编译cpu/$(CPU)/start.s,对于不同cpu还可能编译其他文件。
2:对平台相关的每个目录,每个通用目录都使用他们各自的makefile生成相应库。
3:将1.2步生成的.o .a文件按照board/$(BOAEDDIR)/config.mk文件中指定的代码段起始地址、board/$(BOAEDDIR)/u-boot.lds链接脚本进行连接。
4:第三步得到的是elf格式的uboot,用OBJCOPY转换成bin文件。