uboot源码中的README文档中介绍要使用uboot必须先进行配置后编译,即先执行make xxx_config命令,然后执行make命令,下面以make smdk2410_config指令为例来介绍uboot的配置过程。
解压uboot-1.1.6文件夹后,在顶层目录的Makefile中可以看到如下代码:
87 SRCTREE := $(CURDIR) 92 MKCONFIG := $(SRCTREE)/mkconfig 1879 smdk2410_config : unconfig 1880 @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
我们在u-boot-1.1.6的根目录下编译,那么第87行代表当前目录的变量$(CURDIR)即为u-boot-1.1.6的根目录,立即变量SRCTREE等于$(CURDIR),也表示uboot的根目录,所以第92行中的MKCONFIG就是根目录下的mkconfig文件。第1879和1880代码告诉我们,执行make smdk2410_config时就相当于执行一下指令:
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
这条语句中有个高级的语法$(var:a=b),意思是把变量"var"中所有的以字符串"a"结尾变量的结尾字符串"a"替换成字符串"b"。由上面的分析,$@代表的是目标"smdk2410_config", "_config="意思是_config等于空字符,所以$(@:_config=)就是将目标"smdk2410_config"中的"_config"去掉,结果为"smdk2410"。将这条语句中各处的变量展开,可以清楚的看到执行"make smdk2410_config"实际是执行下面命令:
./mkconfig smdk2410 arm arm920t smdk2410 NULL s3c24x0
$0 $1 $2 $3 $4 $5 $6
再来看看makconfig的作用,打开mkconfig脚本,可以清楚看到在文件开头的第6行给出了它的用法:
6 # Parameters: Target Architecture CPU Board [VENDOR] [SOC]
这里刚好与上面分析make smdk2410_config执行命令相对应,Parameters($0) Target($1) Architecture($2) CPU($3) Board($4) [VENDOR]($5) [SOC]($6)
下面来详细分析mkconfig的作用
11 APPEND=no # Default: Create new config file 12 BOARD_NAME="" # Name to print in make output 13 14 while [ $# -gt 0 ] ; do 15 case "$1" in 16 --) shift ; break ;; 17 -a) shift ; APPEND=yes ;; 18 -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;; 19 *) break ;; 20 esac 21 done 22 23 [ "${BOARD_NAME}" ] || BOARD_NAME="$1"
对于“./mkconfig smdk2410 arm arm920t smdk2410 NULL s3c24x0” 命令中没有"--","-a","-n","*"等符号,所以14~22行代码没有实现任何相应操作,第11和12行的变量仍然为原来定义是内容。执行完第23行语句时BOARD_NAME等于第一个参数"smdk2410"。
25 [ $# -lt 4 ] && exit 1 26 [ $# -gt 6 ] && exit 1 27 28 echo "Configuring for ${BOARD_NAME} board..."
第25,26行中,$#表示输入总参数个数,-lt为小于(less than),-gt为大于(greater than),&&表示左边命令为真则执行"exit 1",跳出执行。由于总参数个数为6,所以不满足25,26执行条件,所以不跳出继续执行,28行为打印配置信息,当执行"make smdk2410_config"时将自动打印此处信息。
30 # 31 # Create link to architecture specific headers 32 # 33 if [ "$SRCTREE" != "$OBJTREE" ] ; then /* 判断源代码目录和目标代码目录不相同 */ 34 mkdir -p ${OBJTREE}/include 35 mkdir -p ${OBJTREE}/include2 36 cd ${OBJTREE}/include2 37 rm -f asm 38 ln -s ${SRCTREE}/include/asm-$2 asm 39 LNPREFIX="../../include2/asm/" 40 cd ../include 41 rm -rf asm-$2 42 rm -f asm 43 mkdir asm-$2 44 ln -s asm-$2 asm 45 else /* 源代码目录和目标代码目录相同 */ 46 cd ./include 47 rm -f asm 48 ln -s asm-$2 asm 49 fi 50 51 rm -f asm-$2/arch 52 53 if [ -z "$6" -o "$6" = "NULL" ] ; then 54 ln -s ${LNPREFIX}arch-$3 asm-$2/arch 55 else 56 ln -s ${LNPREFIX}arch-$6 asm-$2/arch 57 fi 58 59 if [ "$2" = "arm" ] ; then 60 rm -f asm-$2/proc 61 ln -s ${LNPREFIX}proc-armv asm-$2/proc 62 fi
第33行判断源代码目录和目标文件目录是否一样,可以选择在其他的目录下进行编译,这里我们是直接在源代码文件中进行编译,这里第33行的if语句不满足条件,直接执行else分支语句。第46~48行是通过cd命令进入include目录,删除上一次配置的链接文件asm文件,然后再次建立asm文件,并使其链接向asm-$2目录,也就是asm-arm。第51行是删除asm-arm/arch,53行检测输入的第六个参数是否为空,若为空则执行if分支语句,否则执行else分支,我们输入的第六个参数为“s3c24x0”,不为空,也不为“NULL”所以执行else分支,即创建asm-arm/arch,并令其链接向arch-s3c24x0目录。第60~61行重新建立asm-arm/pro文件,并让它链接向proc-armv目录。
64 # 65 # Create include file for Make 66 # 67 echo "ARCH = $2" > config.mk /* 新建文件config.mk,内容为"ARCH =arm" */ 68 echo "CPU = $3" >> config.mk /* 追加内容"CPU =arm920t"到config.mk文件中 */ 69 echo "BOARD = $4" >> config.mk /* 追加内容"BOARD =smdk2410"到config.mk文件中 */ 70 71 [ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk /* $5参数为空,不执行追加内容 */ 72 73 [ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk /* 追加内容"SOC =S3C24x0到config.mk文件中"
第64~73行执行完后,在include文件夹中创建config.mk内容为:
ARCH = arm
CPU = arm920t
BOARD = smdk2410
SOC = s3c24x0
如下图所示:
75 # 76 # Create board specific header file 77 # 78 if [ "$APPEND" = "yes" ] # Append to existing config file 79 then 80 echo >> config.h 81 else 82 > config.h # Create new config file 83 fi 84 echo "/* Automatically generated - do not edit */" >>config.h 85 echo "#include <configs/$1.h>" >>config.h 86 87 exit 0
APPEND维持原值为"no",执行分支语句,创建config.h文件,第84~85为在创建config.h文件内追加信息,config.h内容如下图所示:
现在来总结一下,执行配置命令“make smdk2410_config”产生结果:
- 开发板名称BOARD_NAME等于$1(此处为smdk2410)
- 创建到平台/开发板相关头文件的链接
- 创建根目录下Makefile文件包含的文件include/config.mk
- 创建开发板相关的头文件include/config.h(此文件会在start.S中包含,很重要)