前言:
本文是根据哔哩哔哩网站上“Arm(iMX6U)Linux系统移植和根文件系统构键篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。
引用:
正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com
《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》
正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档
正点原子imx6ull-mini-Linux驱动之Linux I2C 驱动实验(21)-CSDN博客
正文:
本文是 “Arm(iMX6U)Linux系统移植和根文件系统构键篇--4讲uboot目录分析。本节将参考正点原子的视频教程和配套的正点原子开发指南文档进行学习。
0. 概述
1 U-Boot 工程目录分析
本书我们以 EMMC 版本的核心板为例讲解,为了方便, uboot 启动源码分析就在 Windows下行,将正点原子提供的 uboot 源码进行解压,解压完成以后的目录如图 31.1.1 所示
图 31.1.1 是正点原子提供的未编译的 uboot 源码目录,我们在分析 uboot 源码之前一定要先在 Ubuntu 中编译一下 uboot 源码,因为编译过程会生成一些文件,而生成的这些恰恰是分析uboot 源码不可或缺的文件。使用上一章创建的 shell 脚本来完成编译工作,命令如下:
cd alientek_uboot //进入正点原子 uboot 源码目录
./mx6ull_alientek_emmc.sh //编译 uboot
cd ../ //返回上一级目录
tar -vcjf alientek_uboot.tar.bz2 alientek_uboot //压缩
最终会生成一个名为 alientek_uboot.tar.bz2 的压缩包,将 alientek_uboot.tar.bz2 拷贝到 windows系统中并解压,解压后的目录如图 31.1.2 所示:
对比图 31.1.2 和图 31.1.1,可以看出编译后的 uboot 要比没编译之前多了好多文件,这些文件夹或文件的含义见表 31.1.1 所示
文件夹 | 描述 | 备注 |
api | 与硬件无关的 API 函数 | uboot 自带 |
arch | 与架构体系有关的代码 | uboot 自带 |
board | 不同板子(开发板)的定制代码 | uboot 自带 |
cmd | 命令相关代码 | uboot 自带 |
common | 通用代码 | uboot 自带 |
configs | 配置文件 | uboot 自带 |
disk | 磁盘分区相关代码 | uboot 自带 |
doc | 文档 | uboot 自带 |
drivers | 驱动代码 | uboot 自带 |
dts | 设备树 | uboot 自带 |
examples | 示例代码 | uboot 自带 |
fs | 文件系统 | uboot 自带 |
include | 头文件 | uboot 自带 |
lib | 库文件 | uboot 自带 |
Licenses | 许可证相关文件 | uboot 自带 |
net | 网络相关代码 | uboot 自带 |
post | 上电自检程序 | uboot 自带 |
scripts | 脚本文件 | uboot 自带 |
test | 测试代码 | uboot 自带 |
tools | 工具文件夹 | uboot 自带 |
.config | 配置文件,重要的文件 | 编译生成的文件 |
.u-boot.xxx.cmd (一系列) | 这是一系列的文件,用于保存着一 些命令 | 编译生成的文件 |
config.mk | 某个 Makefile 会调用此文件 | uboot 自带 |
imxdownload | 正点原子编写的 SD 卡烧写软件 | 正点原子提供 |
Kbuild | 用于生成一些和汇编有关的文件 | uboot 自带 |
Kconfig | 图形配置界面描述文件 | uboot 自带 |
MAKEALL | 一个 shell 脚本文件,帮助编译 uboot 的 | uboot 自带 |
Makefile | 主 Makefile,重要文件! | uboot 自带 |
System.map | 系统映射文件 | 编译生成的文件 |
u-boot | 编译出来的 u-boot 文件 | 编译生成的文件 |
u-boot.xxx (一系列) | 生成的一些 u-boot 相关文件,包括 u-boot.bin、 u-boot.imx.等 | 编译生成的文件 |
表 31.1.1 中的很多文件夹和文件我们都不需要去关心,我们要关注的文件夹或文件如下
1、 arch 文件夹
这个文件夹里面存放着和架构有关的文件,如图 31.1.3 所示
从图 31.1.3 可以看出有很多架构,比如 arm、 avr32、 m68k 等,我们现在用的是 ARM 芯片,所以只需要关心 arm 文件夹即可,打开 arm 文件夹里面内容如图 31.1.4 所示:
图 31.1.4 只截取了一部分,还有一部分 mach-xxx 的文件夹。 mach 开头的文件夹是跟具体的设备有关的,比如“mach-exynos”就是跟三星的 exyons 系列 CPU 有关的文件。我们使用的是I.MX6ULL,所以要关注“imx-common”这个文件夹。另外“cpu”这个文件夹也是和 cpu 架构有关的,打开以后如图 31.1.5 所示:
从图 31.1.5 可以看出有多种 ARM 架构相关的文件夹,
- I.MX6ULL 使用的 Cortex-A7 内核,Cortex-A7 属于 armv7,所以我们要关心“armv7”这个文件夹。
- cpu 文件夹里面有个名“uboot.lds”的链接脚本文件,这个就是 ARM 芯片所使用的 u-boot 链接脚本文件!
- armv7 这个文件夹里面的文件都是跟 ARMV7 架构有关的,是我们分析 uboot 启动源码的时候需要重点关注的。
2、 board 文件夹
board 文件夹就是和具体的板子有关的,打开此文件夹,里面全是不同的板子,毫无疑问正点原子的开发板肯定也在里面(正点原子添加的), borad 文件夹里面有个名为“freescale”的文件夹,如图 31.1.6 所示:
所有使用 freescale 芯片的板子都放到此文件夹中, I.MX 系列以前属于 freescale,只是freescale 后来被 NXP 收购了。打开此 freescale 文件夹,在里面找到和 mx6u(I.MX6UL/ULL)有关的文夹,如图 31.1.7 所示:
图 31.1.7 中有 5 个文件夹,这 5 个文件夹对应 5 种板子,以“mx6ul”开头的表示使用I.MX6UL 芯片的板子,以 mx6ull 开头的表示使用 I.MX6ULL 芯片的板子。 mx6ullevk 是 NXP官方的I.MX6ULL开发板,正点原子的ALPHA开发板就是在这个基础上开发的,因此mx6ullevk也是正点原子的开发板。我们后面移植 uboot 到时候就是参考 NXP 官方的开发板,也就是要参考 mx6ullevk 这个文件夹来定义我们的板子。
3、 configs 文件夹
此文件夹为 uboot 配置文件, uboot 是可配置的,但是你要是自己从头开始一个一个项目的配置,那就太麻烦了,因此一般半导体或者开发板厂商都会制作好一个配置文件。我们可以在这个做好的配置文件基础上来添加自己想要的功能,这些半导体厂商或者开发板厂商制作好的配置文件统一命名为“xxx_defconfig”, xxx 表示开发板名字,这些 defconfig 文件都存放在 configs文件夹,因此, NXP 官方开发板和正点原子的开发板配置文件肯定也在这个文件夹中,如图31.1.8 所示:
图 31.1.8 中这 6 个文件就是正点原子 I.MX6U-ALPHA 开发板所对应的 uboot 默认配置文件。我们只关心 mx6ull_14x14_ddr512_emmc_defconfig 和 mx6ull_14x14_ddr256_nand_defconfig这两个文件,分别是正点原子 I.MX6ULL EMMC 核心板和 NAND 核心板的配置文件。使用“make xxx_defconfig”命令即可配置 uboot,比如:
make mx6ull_14x14_ddr512_emmc_defconfig
上述命令就是配置正点原子的 I.MX6ULL EMMC 核心板所使用的 uboot。
在编译 uboot 之前一定要使用 defconfig 来配置 uboot!
在 mx6ull_alientek_emmc.sh 中就有下面这一句:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_ddr512_emmc_
defconfig
这个就是调用 mx6ull_14x14_ddr512_emmc_defconfig 来配置 uboot,只是这个命令还带了一些其它参数而已。
4、 .u-boot.xxx_cmd 文件
.u-boot.xxx_cmd 是一系列的文件,这些文件都是编译生成的,都是一些命令文件,比如文件.u-boot.bin.cmd,看名字应该是和 u-boot.bin 有关的,此文件的内容如下:
cmd_u-boot.bin := cp u-boot-nodtb.bin u-boot.bin
.u-boot.bin.cmd 里面定义了一个变量: cmd_u-boot.bin,此变量的值为“cp u-boot-nodtb.bin u-boot.bin”,也就是拷贝一份 u-boot-nodtb.bin 文件,并且重命名为 u-boot.bin,这个就是 uboot.bin
的来源,来自于文件 u-boot-nodtb.bin。
那 么 u-boot-nodtb.bin 是 怎 么 来 的 呢 ? 文 件 .u-boot-nodtb.bin.cmd 就 是 用 于 生 成 uboot.nodtb.bin 的,此文件内容如下:
cmd_u-boot-nodtb.bin := arm-linux-gnueabihf-objcopy \ --gap-fill=0xff -j .text -j .secure_text \-j .rodata -j .hash -j .data -j .got -j .got.plt \-j .u_boot_list -j .rel.dyn -O binary u-boot u-boot-nodtb.bin
这里用到了 arm-linux-gnueabihf-objcopy,使用 objcopy 将 ELF 格式的 u-boot 文件转换为二进制的 u-boot-nodtb.bin 文件。
文件 u-boot 是 ELF 格式的文件,文件.u-boot.cmd 用于生成 u-boot,文件内容如下
cmd_u-boot := arm-linux-gnueabihf-ld.bfd -pie --gc-sections -Bstatic -Ttext 0x87800000 -o u-boot -T u-boot.lds arch/arm/cpu/armv7/start.o --start-group arch/arm/cpu/built-in.o arch/arm/cpu/armv7/built-in.o arch/arm/imx-common/built-in.o arch/arm/lib/built-in.o board/freescale/common/built-in.o board/freescale/mx6ullevk/built-in.o cmd/built-in.o common/built-in.o disk/built-in.o drivers/built-in.o drivers/dma/built-in.o drivers/gpio/built-in.o drivers/i2c/built-in.o drivers/mmc/built-in.o drivers/mtd/built-in.o drivers/mtd/onenand/built-in.o drivers/mtd/spi/built-in.o drivers/net/built-in.o drivers/net/phy/built-in.o drivers/pci/built-in.o drivers/power/built-in.o drivers/power/battery/built-in.o drivers/power/fuel_gauge/built-in.o drivers/power/mfd/built-in.o drivers/power/pmic/built-in.o drivers/power/regulator/built-in.o drivers/serial/built-in.o drivers/spi/built-in.o drivers/usb/dwc3/built-in.o drivers/usb/emul/built-in.o drivers/usb/eth/built-in.o drivers/usb/gadget/built-in.o drivers/usb/gadget/udc/built-in.o drivers/usb/host/built-in.o drivers/usb/musb-new/built-in.o drivers/usb/musb/built-in.o drivers/usb/phy/built-in.o drivers/usb/ulpi/built-in.o fs/built-in.o lib/built-in.o net/built-in.o test/built-in.o test/dm/built-in.o --end-group arch/arm/lib/eabi_compat.o -L /home/dimon/I.MX6ULL/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/4.9.4 -lgcc -Map u-boot.map
.u-boot.cmd 使用到了 arm-linux-gnueabihf-ld.bfd,也就是链接工具,使用 ld.bfd 将各个 builtin.o文件链接在一起就形成了 u-boot 文件。
uboot 在编译的时候会将同一个目录中的所有.c 文件都编译在一起,并命名为 built-in.o,相当于将众多的.c 文件对应的.o 文件集合在一起,这个就是 u-boot 文件的来源。
如果我们要用 NXP 提供的 MFGTools 工具向开发板烧写 uboot,此时烧写的是 u-boot.imx文件,而不是 u-boot.bin 文件。 u-boot.imx 是在 u-boot.bin 文件的头部添加了 IVT、 DCD 等信息。这个工作是由文件.u-boot.imx.cmd 来完成的,此文件内容如下:
cmd_u-boot.imx := ./tools/mkimage \-n board/freescale/mx6ullevk/imximage-ddr512.cfg.cfgtmp \-T imximage -e 0x87800000 -d u-boot.bin u-boot.imx >/dev/null
可以看出,这里用到了工具 tools/mkimage,而 IVT、 DCD 等数据保存在了文件board/freescale/mx6ullevk/imximage-ddr512.cfg.cfgtmp 中 ( 如 果 是 NAND 核 心 板 的 话 就 是imximage-ddr256.cfg.cfgtmp),工具 mkimage 就是读取文件 imximage-ddr512.cfg.cfgtmp 里面的信息,然后将其添加到文件 u-boot.bin 的头部,最终生成 u-boot.imx。
文件.u-boot.lds.cmd 就是用于生成 u-boot.lds 链接脚本的,由于.u-boot.lds.cmd 文件内容太多,这里就不列出来了。
uboot 根目录下的 u-boot.lds 链接脚本就是来源于 arch/arm/cpu/u-boot.lds文件。
cmd_u-boot.lds := arm-linux-gnueabihf-gcc -E -Wp,-MD,./.u-boot.lds.d \-D__KERNEL__ -D__UBOOT__ -D__ARM__ -marm -mno-thumb-interwork \-mabi=aapcs-linux -mword-relocations -fno-pic -mno-unaligned-access \-ffunction-sections -fdata-sections -fno-common -ffixed-r9 -msoft-float \-pipe -march=armv7-a -Iinclude -I./arch/arm/include -include ./include/linux/kconfig.h -nostdinc \-isystem /home/dimon/I.MX6ULL/gcc-linaro-4.9.4- 2017.01-x86_64_arm-linux-gnueabihf/bin/../lib/\gcc/arm-linux-gnueabihf/4.9.4/include \-include ./include/u-boot/u-boot.lds.h \-DCPUDIR=arch/arm/cpu/armv7 \-ansi -D__ASSEMBLY__ -x assembler-with-cpp \-P -o u-boot.lds arch/arm/cpu/u-boot.ldssource_u-boot.lds := arch/arm/cpu/u-boot.ldsdeps_u-boot.lds := \$(wildcard include/config/armv7/secure/base.h) \$(wildcard include/config/armv7/nonsec.h) \include/u-boot/u-boot.lds.h \include/config.h \$(wildcard include/config/imx/config.h) \$(wildcard include/config/mx6ull/evk/emmc/rework.h) \$(wildcard include/config/boarddir.h) \include/config_defaults.h \
还有一些其它的.u-boot.lds.xxx.cmd 文件,大家自行分析一下,关于.u-boot.lds.xxx.cmd 文件就讲解到这里。
5、 Makefile 文件
- 这个是顶层 Makefile 文件, Makefile 是支持嵌套的,也就是顶层 Makefile 可以调用子目录中的 Makefile 文件。
- Makefile 嵌套在大项目中很常见,一般大项目里面所有的源代码都不会放到同一个目录中,各个功能模块的源代码都是分开的,各自存放在各自的目录中。
- 每个功能模块目录下都有一个 Makefile,这个 Makefile 只处理本模块的编译链接工作,这样所有的编译链接工作就不用全部放到一个 Makefile 中,可以使得 Makefile 变得简洁明了。
uboot 源码根目录下的 Makefile 是顶层 Makefile,他会调用其它的模块的 Makefile 文件,比如 drivers/adc/Makefile。当然了,顶层 Makefile 要做的工作可远不止调用子目录 Makefile 这么简单,关于顶层 Makefile 的内容我们稍后会有详细的讲解。
6、 u-boot.xxx 文件
u-boot.xxx 同样也是一系列文件,包括 u-boot、 u-boot.bin、 u-boot.cfg、 u-boot.imx、 u-boot.lds、u-boot.map、 u-boot.srec、 u-boot.sym 和 u-boot-nodtb.bin,这些文件的含义如下:
- u-boot:编译出来的 ELF 格式的 uboot 镜像文件。
- u-boot.bin:编译出来的二进制格式的 uboot 可执行镜像文件。
- u-boot.cfg: uboot 的另外一种配置文件。
- u-boot.imx: u-boot.bin 添加头部信息以后的文件, NXP 的 CPU 专用文件。
- u-boot.lds:链接脚本。
- u-boot.map: uboot 映射文件,通过查看此文件可以知道某个函数被链接到了哪个地址上。
- u-boot.srec: S-Record 格式的镜像文件。
- u-boot.sym: uboot 符号文件。
- u-boot-nodtb.bin:和 u-boot.bin 一样, u-boot.bin 就是 u-boot-nodtb.bin 的复制文件。
7、 .config 文件
uboot 配置文件,使用命令“make xxx_defconfig”配置 uboot 以后就会自动生成, .config 内容如下:
可以看出.config 文件中都是以“CONFIG_”开始的配置项,这些配置项就是 Makefile 中的变量,因此后面都跟有相应的值, uboot 的顶层 Makefile 或子 Makefile 会调用这些变量值。在.config 中会有大量的变量值为‘y’,这些为‘y’的变量一般用于控制某项功能是否使能,为‘y’的话就表示功能使能,比如:
CONFIG_CMD_BOOTM=y
如果使能了 bootd 这个命令的话, CONFIG_CMD_BOOTM 就为‘y’。在 cmd/Makefile 中有如下代码:
ifndef CONFIG_SPL_BUILD# core commandobj-y += boot.oobj-$(CONFIG_CMD_BOOTM) += bootm.oobj-y += help.oobj-y += version.o
在示例代码 31.1.6 中,有如下所示一行代码
obj-$(CONFIG_CMD_BOOTM) += bootm.o
CONFIG_CMD_BOOTM=y,将其展开就是
obj-y += bootm.o
也就是给 obj-y 追加了一个“bootm.o”, obj-y 包含着所有要编译的文件对应的.o 文件,这里表示需要编译文件 cmd/bootm.c。相当于通过“CONFIG_CMD_BOOTD=y”来使能 bootm 这个命令,进而编译 cmd/bootm.c 这个文件,这个文件实现了命令 bootm。在 uboot 和 Linux 内核中都是采用这种方法来选择使能某个功能,编译对应的源码文件。
8、 README
README 文件描述了 uboot 的详细信息,包括 uboot 该如何编译、 uboot 中各文件夹的含义、相应的命令等等。建议大家详细的阅读此文件,可以进一步增加对 uboot 的认识。
关于 uboot 根目录中的文件和文件夹的含义就讲解到这里,接下来就要开始分析 uboot 的启动流程了.