好多刚开始学习uboot移植的同学总是觉得uboot好难,但是再难的问题如果把它一步步拆开,一个个解决,问题也就将迎刃而解。做uboot移植,我们首先就得了解uboot的编译流程,这里以在iTOP4412精英版2G内存的板子上移植u-boot-2013.01.tar.bz2为例子,uboot可以到https://ftp.denx.de/pub/u-boot/网站进行下载,执行: tar jxvf u-boot-2013.01.tar.bz2进行解压。
解压完在u-boot-2013.01文件夹下有如下文件
先看看README文件,看它是如何说明uboot的使用,在3863行可以看到关于编译uboot的说明
首先是配置配置交叉编译器,然后执行make NAME_config,再执行make all。这里的NAME我们该怎么写呢?在3898行有说明,关于NAME的配置说明请参照boards.cfg文件。
打开boards.cfg文件
在第40行有Target ARCH CPU Board name Vendor SOC Options一个表头,即下面的内容是按照这个规则列出来的,Target就是对应我们上面的make NAME_config中的NAME,这个我们可以随便设置;ARCH是对应我们要移植目标板芯片的架构;CPU对应芯片核心型号;Board name对应板子的名称,这个可以自己随便设置,但是要对应到board/$(Vendor)/$(Board name)目录;Vendor是指芯片的供应商名称;SOC是对应芯片系列号;Options是额外配置项。iTOP4412的板子的芯片名称为exynos4412,根据芯片手册可知,它是属于三星公司提供的arm架构的armv7型号exynos系列芯片,即ARCH=arm,CPU=armv7,Vendor=samsung,SOC=exynos,其他几个是我们自己设定的,先看看board/$(Vendor)/目录下(即board/samsung/)有哪些文件
其中common目录下放的是samsung板子的一些通用接口,dts目录就是放dts(Device Tree Source 设备树资源)文件,关于dts就不在这里展开讲述,其他文件名都可以在boards.cfg文件中找到定义。通过查看boards.cfg文件中的定义可知origen的板子跟iTOP4412比较相似,我们就先用这个配置来编译。即make origen_config后再执行make。
那么在执行这两个命令的时候,整个工程是如何进行编译的呢?我们先来看看顶级目录下的Makefile文件,u-boot-2013的顶层Makefile只有smdk6400_noUSB_config和smdk6400_config的具体配置,那么其他的配置该怎么执行呢?
在第775行
%_config:: unconfig
@$(MKCONFIG) -A $(@:_config=)
这个就是对应其他配置的规则,%_config的%是通配符,只要字串中带有后缀_config的都会引用到这里,也就是执行make origen_config时首先匹配到这里。理解Makefile的规则的都知道Makefile的最基本规则就是
目标: 依赖
对应目标的操作规则
unconfig在770行有定义,就是删除之前的一些配置。接下来我们就看看@$(MKCONFIG) -A $(@:_config=)干了些啥。
在131行定义了MKCONFIG变量,就是顶级目录下的mkconfig脚本
@$(MKCONFIG) -A $(@:_config=)
相当于执行
mkconfig -A origen
在看看mkconfig脚本可以看看mkconfig -A origen干了些啥
这里第22行是我自己添加的log,看看@$(MKCONFIG) -A $(@:_config=)的时候传递了哪些参数,在23行到42行也可以看出该脚本只允许传递两个参数,第一个参数是:-A,第二个参数是我们的Target。参数条件必须落入第一个if分支,如果不能进去第一个分支就会报错。第一个if分支只要是通过我们传递的Target去boards.cfg文件中找出对应的列表,我们可以执行它上面的命令试试。
这里执行make origen_config的打印也验证了我们上面的参数,执行egrep命令也找出了origen对应的列表,然后将这些列表参数进行变量赋值
创建链接
赋值变量并写进include/config.mk文件
创建include/config.h文件,并往里面写一些宏定义和添加头文件包含
至此,mkconfig -A origen已经完成,也就是我们的make origen_config完成了以上工作。再用git status命令查看执行以上命令,对整个工程做了哪些修改
发现多了以上文件。
接下来分析make命令
首先在166行是判断include/config.mk是否存在,如果有就继续执行,如果没有则跳到722行,后面就报错退出了。也就是说在执行make之前,必须先执行make NAME_config进行配置。
在188行是配置交叉编译器,关于iTOP4412交叉编译器的构建可以参考iTOP4412交叉编译器构建这篇博客。
这段代码是分别去这些路径找链接脚本的,如果都找不到也会报错退出,至于链接脚本干啥用后面会接着讲。
找到链接脚本之后,接着就是设置编译顺序,其中$(CPUDIR)/start.o必须放第一位,因为uboot就是从这个文件启动的。
因为我们最终需要的是u-boot.bin文件,在444行找到了生成u-boot.bin目标的规则,依赖于u-boot,其中BOARD_SIZE_CHECK没有定义,也就是这行没有任何操作。
可能有些人不明白,为什么执行make的时候会到u-boot.bin这里?其实再追溯到上面429行就知道了,当我们执行make,但是后面不加任何目标的时候,就会在Makefile文件中找到all这个目标来执行,而all又依赖于$(ALL-y) $(SUBDIR_EXAMPLES),在412行又找到ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map,也就是在执行make的时候其实会生成好几个文件,但是只有u-boot.bin是我们目前关心的。
到这里我们已经成功地把u-boot.bin给编译出来了,但是它还不能启动。因为exynos4412芯片采用了Secure Boot技术,所以我们编译完u-boot.bin还需对u-boot.bin文件进行修改。修改步骤如下:
1.找到讯为电子提供uboot的源码,将根目录下的sdfuse_q文件夹拷贝到u-boot-2013.01目录下
2.修改Makefile,在u-boot.bin中添加规则
3.将编译出来的u-boot.bin拷贝到讯为电子提供的CodeSign4SecureBoot_SCP目录下,这里包含着exynos4412芯片BL1阶段的可执行程序,其实是由三星提供的无源码可执行程序。
4.合并文件
cat E4412_N.bl1.SCP2G.bin bl2.bin all00_padding.bin u-boot.bin tzsw_SMDK4412_SCP_2GB.bin > u-boot-iTOP-4412.bin
得到u-boot-iTOP-4412.bin文件
5.用dd命令将u-boot-iTOP-4412.bin文件写进SD卡
sudo dd if=u-boot-iTOP-4412.bin of=/dev/sdb seek=1
这个时候将SD卡插到板子上,把拨码开关拨到SD卡启动位置就可以启动了,因为我们只是用origen的配置文件,在iTOP4412上未必能真的启动
那么我们先修改代码点亮LED灯
修改arch/arm/cpu/armv7/start.S文件添加点亮LED程序
执行make重新编译,将合并的文件写进SD卡,重新启动板子,可以看到板子的LED亮了
到此,关于iTOP4412精英版2G内存的板子上移植u-boot-2013.01已经结束,整个教程比较长,希望以后能简洁明了,如果不对的地方也请指出。