在这篇文字里,我就要分析一下在第一篇文字里被忽略的部分了。这部分是在$(OBJTREE)/include/config.mk文件已经存在的 情况下才执行的。
__________________________________________________
# load ARCH, BOARD, and CPU configuration
include $(OBJTREE)/include/config.mk
export ARCH CPU BOARD VENDOR SOC
ifndef CROSS_COMPILE
ifeq ($(HOSTARCH),ppc)
CROSS_COMPILE =
else
ifeq ($(ARCH),ppc)
CROSS_COMPILE = powerpc-linux-
endif
ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux-
endif
ifeq ($(ARCH),i386)
ifeq ($(HOSTARCH),i386)
CROSS_COMPILE =
else
CROSS_COMPILE = i386-linux-
endif
endif
ifeq ($(ARCH),mips)
CROSS_COMPILE = mips_4KC-
endif
ifeq ($(ARCH),nios)
CROSS_COMPILE = nios-elf-
endif
ifeq ($(ARCH),nios2)
CROSS_COMPILE = nios2-elf-
endif
ifeq ($(ARCH),m68k)
CROSS_COMPILE = m68k-elf-
endif
ifeq ($(ARCH),microblaze)
CROSS_COMPILE = mb-
endif
ifeq ($(ARCH),blackfin)
CROSS_COMPILE = bfin-elf-
endif
ifeq ($(ARCH),avr32)
CROSS_COMPILE = avr32-
endif
endif
endif
export CROSS_COMPILE
____________________________________________________
注意开头一句中的include,它是把后面跟的文件内容给加到它出现的地方,这里就是把$(OBJTREE)/include /config.mk文件的内容加入到了这里,所以就得到了ARCH,BOARD与CPU的值,如果VENDOR与SOC也定义了,也会得到它们的值。
后面接着的一大段,就是在判断没有定义CROSS_COMPILE变量的情况下,根据各种情况对这个变量的值进行判断。这个值就是交叉编译工具的开 头部分的名称。如果不清楚什么是交叉编译工具,就需要查查相关的资料了。
在这里,我建议在编译的时候,还是把这个变量的值给置上,置上当前系统里 交叉编译工具相应的值,因为很难指望这些个判断就能把你现在系统里的值给判断对了。置变量的方法有-很多,其中一个,就是在make命令后跟上变量的赋 值,例如:make CROSS_COMPILE=arm-linux-gnueabi-,或是把CROSS_COMPILE设成一个系统变量,然后直接make CROSS_COMPILE=${CROSS_COMPILE}-这样来设置。
____________________________________________________
# load other configuration
include $(TOPDIR)/config.mk
____________________________________________________
这里把$(TOPDIR)/config.mk这个文件的内容包含进来了。
还有个语句需要提前说明一下,就是sinclude,它也是把后 面所跟的文件给包含进来。它与include的区别就是,include后面跟的文件,一定是存在的,如果不存在,执行就会出错误;那么sinclude 后面所跟的文件,可以不存在,如果文件存在则包含进来,如果不存在,则什么也不做。
在这里提这一句,是因为 在$(TOPDIR)/config.mk这个文件里,用到了这个命令,在这里提一下,是可以做个比较,这样便于记忆。
按理说,下面应该分析$(TOPDIR)/config.mk这个文件了,不过这个文件对移植的影响,源码的影响也不是特别大,所以就不做特别细致 的分析了,大概介绍一下这个文件的功能。
这个文件的功能就是给各个在编译过程中的变量赋值,包括编译执行的函数与编译的时候所带的参数等等。还会根据是否定义了 ARCH,CPU,SOC,VENDOR,BOARD来决定是否包含相应位置的config.mk文件,这些个文件里,也是定义了相应的平台在编译的时候 应该加的参数。所以如果你为你自己的开发板取了别的名字了,那么就要检查一下这个文件,看一下相应的位置上的config.mk文件有没有,内容是否为你 要想的。
____________________________________________________
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),mpc83xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc85xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc86xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),bf533)
OBJS += cpu/$(CPU)/start1.o cpu/$(CPU)/interrupt.o cpu/$(CPU)/cache.o
OBJS += cpu/$(CPU)/cplbhdlr.o cpu/$(CPU)/cplbmgr.o cpu/$(CPU)/flush.o
endif
OBJS := $(addprefix $(obj),$(OBJS))
LIBS = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
LIBS += cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).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 += disk/libdisk.a
LIBS += rtc/librtc.a
LIBS += dtt/libdtt.a
LIBS += drivers/libdrivers.a
LIBS += drivers/nand/libnand.a
LIBS += drivers/nand_legacy/libnand_legacy.a
LIBS += drivers/sk98lin/libsk98lin.a
LIBS += post/libpost.a post/cpu/libcpu.a
LIBS += common/libcommon.a
LIBS += $(BOARDLIBS)
LIBS := $(addprefix $(obj),$(LIBS))
.PHONY : $(LIBS)
# Add GCC lib
PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
# The "tools" are needed early, so put this first
# Don't include stuff already done in $(LIBS)
SUBDIRS = tools /
examples /
post /
post/cpu
.PHONY : $(SUBDIRS)
ifeq ($(CONFIG_NAND_U_BOOT),y)
NAND_SPL = nand_spl
U_BOOT_NAND = $(obj)u-boot-nand.bin
endif
__OBJS := $(subst $(obj),,$(OBJS))
__LIBS := $(subst $(obj),,$(LIBS))
____________________________________________________
这段代码,其实也是定义变量,根据不同的条件,给变量定义不同的值。这些变量都是在后面编译的时候,写到运行命令参数里面的,这些变量的意义,还有 各种参数的意义,可以查看相应的工具的参数手册来得到,由于跟移植没有什么太大的关系,就不做一一说明了。
这段代码不难理解,就是需要注意一下各 个变量值所添加的顺序,第一个添加的,编译的时候,变量进行替换,就会被放在前面,然后就会被首先编译,连接,以此类推。可以看到,最先执行的就是 start.o这个文件里的内容,这个文件是由start.S来生成的。
____________________________________________________
ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)
all: $(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)u-boot.img: $(obj)u-boot.bin
./tools/mkimage -A $(ARCH) -T firmware -C none /
-a $(TEXT_BASE) -e 0 /
-n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | /
sed -e 's/"[ ]*$$/ for $(BOARD) board"/') /
-d $< $@
$(obj)u-boot.dis: $(obj)u-boot
$(OBJDUMP) -d $< > $@
$(obj)u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*/(__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
$(OBJS):
$(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))
$(LIBS):
$(MAKE) -C $(dir $(subst $(obj),,$@))
$(SUBDIRS):
$(MAKE) -C $@ all
$(NAND_SPL): version
$(MAKE) -C nand_spl/board/$(BOARDDIR) all
$(U_BOOT_NAND): $(NAND_SPL) $(obj)u-boot.bin
cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin
version:
@echo -n "#define U_BOOT_VERSION /"U-Boot " > $(VERSION_FILE); /
echo -n "$(U_BOOT_VERSION)" >> $(VERSION_FILE); /
echo -n $(shell $(CONFIG_SHELL) $(TOPDIR)/tools/setlocalversion /
$(TOPDIR)) >> $(VERSION_FILE); /
echo "/"" >> $(VERSION_FILE)
gdbtools:
$(MAKE) -C tools/gdb all || exit 1
updater:
$(MAKE) -C tools/updater all || exit 1
env:
$(MAKE) -C tools/env all || exit 1
depend dep:
for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir _depend ; done
tags ctags:
ctags -w -o $(OBJTREE)/ctags `find $(SUBDIRS) include /
lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) /
fs/cramfs fs/fat fs/fdos fs/jffs2 /
net disk rtc dtt drivers drivers/sk98lin common /
/( -name CVS -prune /) -o /( -name '*.[ch]' -print /)`
etags:
etags -a -o $(OBJTREE)/etags `find $(SUBDIRS) include /
lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) /
fs/cramfs fs/fat fs/fdos fs/jffs2 /
net disk rtc dtt drivers drivers/sk98lin common /
/( -name CVS -prune /) -o /( -name '*.[ch]' -print /)`
$(obj)System.map: $(obj)u-boot
@$(NM) $< | /
grep -v '/(compiled/)/|/(/.o$$/)/|/( [aUw] /)/|/(/./.ng$$/)/|/(LASH[RL]DI/)' | /
sort > $(obj)System.map
______________________________________________________
这里就是定义了各种目标的target。我们最终想要的目标就是$(obj)u-boot,然后看后面的,它都信赖了好多其它的目标,然后这些个目 标,也是在此处定义的,然后有相应的$(MAKE)来执行相应的操作,所以这样就实现了一个Makefile文件,套很多个其它的Makefile文件来 编译整个工程的情况。
现在整个编译的过程就分析清楚了,那么开始移植就是对代码的整个熟悉的过程了。最先开始执行的就是start.S的内容,移值就需要先分析 它。
其实要想自己写这样的一个文件,难度还是比较大的,首先要熟悉这种比较特别的汇编语法,然后需要了解与处理器相关的各种状态寄存器的定义。但 是如果只是做修改,难度就小多了,拿着ARM处理器汇编语言的手册,再参考三星提供的S3C2440的板子的说明,一步步检查源码,修改相应的参数,以符 合自己的板子的需要就行了,如果有兴趣,也可以弄清楚各种参数的具体的意义,各种状态寄存器的格式定义,这也是比较有意思的。
我自己的移植也刚则开始,目前还没有遇到很棘手的问题,现在最担心的,就是我买的开发板上的各种重要的状态寄存器的地址与S3C2440这块板子上 的不一样,因为我的这块板子也没有相应的说明书,只给了三星的S3C2440的说明书,万一不一致,我就完蛋了,希望这种局面不要发生,阿门。
等我自己的u-boot移植成功后,我就要去给自己找个嵌入式相关的工作了,实在比较喜欢这个行当的这种比较富有挑战性的工作,哈哈哈哈:)
现在这系列的文章,暂时告一段落,已经写完的,算是一个上部吧,等我自己的移植工作做完了,我就开始接着写u-boot-1.1.6源码浅析 (五),从五开始,就要分析源码的具体的内容了,只要于移植相关的,都会做出说明,包括各种寄存器的状态的定义,至于会告诉你去哪里查这个东西,怎么查, 怎么看明白。
好了,这系列的说明上部,就到此为止,再见。