| 
 | 
	
 
 本帖最后由 wyzhou 于 2020-6-22 17:53 编辑  
 
版权声明:本文为CSDN博主「如之」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 
原文链接:https://blog.csdn.net/benjorsun/article/details/80332491 
 
在开发altera soc cyclone v以及其它的soc时,我们需要先使用quartus 及其它组件qsys构建工程,然后soceds根据生成硬件配置文件handoff,生成uboot的头文件及相关配置,最后编译成我们需要的preloader及其及uboot。在使用bsp-editor生成相关文件后,在handoff与generated文件夹可以看到许多头文件与C语言文件,这些文件是用来更新uboot中相关文件的,主要涉及到系统配置,IO复用,DDR初始化等。下面从makefile入手,分析uboot的生成,更新,配置与编译流程。 
 
    在使用bsp-editor后,在工程的目录softeware下生成generated,spl_bsp及顶层makefile文件。我们在编译时,会执行: 
 
    make //生成preloader-mkimage.bin 
 
    make uboot  //生成uboot.bin 
 
    makefile主要是由一些有依赖关系构成的指令,这些指令来完成一些任务。当我们执行make时,通常是执行第一个目标,从文件中我们可以看到这个目标是: 
 
.PHONY: all 
 
all: spl mkpimage-spl 
 
这就是第一个目标all,从名字上我们也可以看出这个目标是生成spl程序的。这个程序是个伪目标,依赖于后面的spl与mkpimage-spl两个目标的执行,就是说这个all的就是执行spl mkpimage-spl两个目标,那么先来看spl这个目标。 
 
.PHONY: spl 
 
spl: $(PRELOADER.BINARY) 
 
spl依赖与PRELOADER.BINARY。继续往下递归找PRELOADER.BINARY。 
 
$(PRELOADER.BINARY): $(CONFIG) 
 
        $(MAKE) $(MAKE_ARGS) -C $(PRELOADER_SRC_DIR) spl/u-boot-spl.bin 
 
这个目标是要做事情的make的。但是它还依赖config这个目标,再次往下递归: 
 
.PHONY: config 
config: $(CONFIG) 
 
 
$(CONFIG): $(UPDATE_SRC) $(UNTAR_SRC) $(PATCH_APPLY) 
        $(MAKE) $(MAKE_ARGS) -C $(PRELOADER_SRC_DIR) $(SOCFPGA_BOARD_CONFIG) 
 
        $(stamp) 
 
这个目标依赖与UPDATE_SRC UNTAR_SRC PATCH_APPLY三个目标,这时就不再往下递归了,这三个目标可以看makefile源文件,就是解压uboot源文件,把handoff generated文件夹下的相应文件拷贝到uboot-socfpga/board/altera/socfpga与下面sdram子目录,最后执行补丁程序。主要来看CONFIG目标,就是执行uboot的config程序,make XXX_config。 
 
关于这个config是最具神秘色彩的,下面大体分析一下这个config到底做了些什么事。 
 
要知道make socfpga_config到底做了什么,需要打开uboot-socfpga目标下的顶层makefile。找到下面这一段: 
 
%_config::        unconfig 
 
        @$(MKCONFIG) -A $(@:_config=) 
 
后面这件事的unconfig的事不细说,也就是执行一些清理工作。接下来的是执行目录下面一个mkconfig的脚本。 
 
@$(MKCONFIG) -A $(@:_config=)等价于mkconfig -A socfpga_cyclone5,注意这里是去掉config的,这是@:_config=的作用,写到这里真觉得应该好好补补makefile与shell编程了。 
 
这一句就是级脚本mkconfig传递两个参数-A与socfpga_cyclone5_config。关于mkconfig的工作可以参考这篇博客: 
 
https://blog.csdn.net/xiaolongwoaini99/article/details/79094753 
 
if [ \( $# -eq 2 \) -a \( "$1" = "-A" \) ] ; then 
        # Automatic mode 
        line=`egrep -i "^[[:space:]]*${2}[[:space:]]" boards.cfg` || { 
                echo "make: *** No rule to make target \`$2_config'.  Stop." >&2 
                exit 1 
        } 
 
 
 
        set ${line} 
 
$# -eq 2及$1="-A"是说是传入参数个数为2,每一个参数是-A。从配置文件boards.cfg中查找$2,也就是socfpga_cyclone5的一行,取出来入在变量line中。如图所示: 
 
 
从上面看也就是想取出target arch cpu board_name vendor soc等变量,这个我们可以使用echo进行一次跟踪,在mkconfig中加入一句echo ${line},显示结果如下: 
 
 
 
而set ${line}的作用就是将line设置到环境变量,我们可以显示一下set的值: 
 
 
 
这时$1=socfpga_cyclone5 $2=arm $3=armv7 .... 
 
下面的就不再一一分析了,其它就是设备环境变量: 
 
arch=arm 
 
cpu=armv7 
 
soc=socfpga_cyclone5 
 
vendor=altera 
 
..... 
 
这些变量可以用来找到相应目录,比如board目录通过是boards/vendor/boardname构成,这就是通过上面的环境变量来构建的。接下来就是生成一个config.h文件,如下代码: 
 
echo "#define CONFIG_SYS_ARCH  \"${arch}\""  >> config.h 
echo "#define CONFIG_SYS_CPU   \"${cpu}\""   >> config.h 
echo "#define CONFIG_SYS_BOARD \"${board}\"" >> config.h 
 
 
[ "${vendor}" ] && echo "#define CONFIG_SYS_VENDOR \"${vendor}\"" >> config.h 
 
 
[ "${soc}"    ] && echo "#define CONFIG_SYS_SOC    \"${soc}\""    >> config.h 
 
 
cat << EOF >> config.h 
#define CONFIG_BOARDDIR board/$BOARDDIR 
#include <config_cmd_defaults.h> 
#include <config_defaults.h> 
#include <configs/${CONFIG_NAME}.h> 
#include <asm/config.h> 
#include <config_fallbacks.h> 
#include <config_uncmd_spl.h> 
 
EOF 
 
这样也就生成了配置文件,config流程也就结束了。再往后递归一步,也就是我们当前在执行make spl。那么他依赖config,config完成后,它会执行: 
 
.PHONY: spl 
spl: $(PRELOADER.BINARY) 
 
 
$(PRELOADER.BINARY): $(CONFIG) 
 
        $(MAKE) $(MAKE_ARGS) -C $(PRELOADER_SRC_DIR) spl/u-boot-spl.bin 
 
也就是说执行make spl/u-boot-spl.bin 
 
再看uboot目录下顶层文件Makefile,中有如下定义: 
 
$(obj)spl/u-boot-spl.bin:        $(SUBDIR_TOOLS) depend 
 
                $(MAKE) -C spl all 
 
该目标是进入spl目录,执行all目标。打开spl makefile。 
 
ALL-y        += $(obj)u-boot-spl.bin 
 
 
ifdef CONFIG_SAMSUNG 
ALL-y        += $(obj)$(BOARD)-spl.bin 
endif 
 
 
all:        $(ALL-y) 
 
 
ifdef CONFIG_SAMSUNG 
$(obj)$(BOARD)-spl.bin: $(obj)u-boot-spl.bin 
        $(OBJTREE)/tools/mk$(BOARD)spl \ 
                $(obj)u-boot-spl.bin $(obj)$(BOARD)-spl.bin 
endif 
 
 
$(obj)u-boot-spl.bin:        $(obj)u-boot-spl 
        $(OBJCOPY) $(OBJCFLAGS) -O binary $< $@ 
 
 
GEN_UBOOT = \ 
        cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) $(__START) \ 
                --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \ 
                -Map u-boot-spl.map -o u-boot-spl 
 
 
$(obj)u-boot-spl:        depend $(START) $(LIBS) $(obj)u-boot-spl.lds 
 
        $(GEN_UBOOT) 
 
这里对spl所依赖的文件进行了编译,并生成u-boot-spl文件。 
 
到此顶层文件的 
 
.PHONY: all 
 
all: spl mkpimage-spl 
中的spl目标执行完成,还有就是mkpimage-spl目标。这个就使用mkpimage工具将u-boot-spl转成preloader-mkimage.bin文件。 
 
接下来make uboot的过程同上分析。preloader与uboot所依赖的目标是不一样的,在个别文件上会有不同。这个以后有机会分析,也可以参考这个博客: 
 
https://blog.csdn.net/linuxarmsummary/article/details/44836293 
 
 |   
 
 
 
 |