LV05-01-uboot-01-uboot简介
本文主要是uboot简介的相关笔记,其实之前学习STM32的时候就知道bootloader的概念,这个uboot其实就是一个bootloader,一个大型裸机程序罢了。若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
Windows版本 | windows11 |
Ubuntu版本 | Ubuntu16.04的64位版本 |
VMware® Workstation 16 Pro | 16.2.3 build-19376536 |
终端软件 | MobaXterm(Professional Edition v23.0 Build 5042 (license)) |
Linux开发板 | 正点原子 i.MX6ULL Linux 阿尔法开发板 |
uboot | NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03) |
linux内核 | linux-4.15(NXP官方提供) |
Win32DiskImager | Win32DiskImager v1.0 |
点击查看本文参考资料
分类 | 网址 | 说明 |
官方网站 | https://www.arm.com/ | ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档 |
https://www.nxp.com.cn/ | NXP官方网站 | |
https://www.nxpic.org.cn/ | NXP 官方社区 | |
https://u-boot.readthedocs.io/en/latest/ | u-boot官网 | |
https://www.kernel.org/ | linux内核官网 |
点击查看相关文件下载
分类 | 网址 | 说明 |
NXP | https://github.com/nxp-imx | NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库 |
https://elixir.bootlin.com/linux/latest/source | 在线阅读linux kernel源码 | |
nxp-imx/linux-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga | NXP linux内核仓库tags中的rel_imx_4.1.15_2.1.0_ga | |
nxp-imx/uboot-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga | NXP u-boot仓库tags中的rel_imx_4.1.15_2.1.0_ga | |
I.MX6ULL | i.MX 6ULL Applications Processors for Industrial Products | I.MX6ULL 芯片手册(datasheet,可以在线查看) |
i.MX 6ULL Applications ProcessorReference Manual | I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网) |
一、uboot简介
Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段 bootloader程序。这段 bootloader 程序会先初始化 DDR 等外设,然后将Linux内核从 flash(NAND、NOR FLASH、SD、MMC 等)拷贝到 DDR 中,最后启动 Linux 内核。
bootloader 的实际工作要复杂的多,但是它最主要的工作就是启动 Linux 内核, bootloader 和 Linux 内核的关系就像是 PC 上的 BIOS 和 Windows 的关系一样, bootloader 就相当于 BIOS。
目前有很多现成的 bootloader 软件可以使用,比如 U-Boot、 vivi、 RedBoot 等等,其中以 U-Boot 使用最为广泛,为了方便书写,后边的笔记会将 U-Boot 写为 uboot,毕竟是笔记,能理解就可以啦。
uboot 的全称是 Universal Boot Loader, 它是一个遵循 GPL 协议的开源软件, 是一个裸机代码,我们可以将它看作是一个裸机综合例程。现在的 uboot 已经支持液晶屏、网络、 USB 等高级功能。
二、uboot获取
1. uboot官网
uboot的官网在这里:U-Boot | DENX ,我们打开这个网页,如下图所示:
我们点击框选出来连接便会跳转到uboot的官方文档页面:
2. 获取原版uboot
2.1 官网获取
我们点击uboot官方文档中的【Build U-Boot】→【Obtaining the source】 ,便会看到uboot的下载方式:
其实我们也可以直接到这里选择相应的版本下载:Tags · U-Boot / U-Boot · GitLab (denx.de) 或者Tags · u-boot/u-boot (github.com)
2.2 ftp下载
我们还可以通过这里下载相应版本的uboot:Index of /pub/u-boot/ (denx.de)
3. 获取NXP原版uboot
一般来讲,我们不会直接用 uboot 官方的 U-Boot 源码的。 uboot 官方的 uboot 源码是给半导体厂商准备的,半导体厂商会下载 uboot 官方的 uboot 源码,然后将自家相应的芯片移植进去。也就是说半导体厂商会自己维护一个版本的 uboot,这个版本的 uboot 相当于是他们定制的。既然是定制的,那么肯定对自家的芯片支持会很全,虽然 uboot 官网的源码中一般也会支持他们的芯片,但是绝对是没有半导体厂商自己维护的 uboot 全面。我们可以从这里下载:Release rel_imx_4.1.15_2.1.0_ga: MLK-14707 fsl_esdhc: Fix eMMC 1.8v setting issue · nxp-imx/uboot-imx (github.com)
图中的 uboot 基本支持了 NXP 当前所有可以跑 Linux 的芯片,而且支持各种启动方式,比如 EMMC、NAND、 NOR FLASH 等等,这些都是 uboot 官方所不支持的。
三、不同的uboot代码
uboot代码种类 | 描述 |
---|---|
uboot 官方的 uboot 代码 | 由 uboot 官方维护开发的 uboot 版本,版本更新快,基本包含所 有常用的芯片。 |
半导体厂商的 uboot 代码 | 半导体厂商维护的一个 uboot,专门针对自家的芯片,在对自家芯片支持上要比 uboot 官方的好。 |
开发板厂商的 uboot 代码 | 开发板厂商在半导体厂商提供的 uboot 基础上加入了对自家开发 板的支持 |
四、工程目录
1. 有那些文件?
我们从下载一个原版的NXP的uboot(Release rel_imx_4.1.15_2.1.0_ga: MLK-14707 fsl_esdhc: Fix eMMC 1.8v setting issue · nxp-imx/uboot-imx (github.com)),方便后边移植,下载完毕后,我们会得到这样一个压缩包:
我们解压后,会得到如下目录及文件:
2. 编译?
NXP官方是出的有一款imx6ull的evk板子,我们可以编译适配这块板子的uboot,可以使用如下命令编译,
1 | make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean |
我们可以创建一个编译脚本,方便后边使用,脚本内容如下:
点击查看编译脚本内容
1 | !/bin/bash |
编译完成后会生成一些文件,如下:
显然是要比之前多了很多的。
3. 目录分析
3.1 概览
上边那么多目录,都有什么用?
我们来分析一下:
下面我们来分析一下其中一些后面可能会用到的文件。
3.2 arch 文件夹
这个文件夹里面存放着和架构有关的文件 :
比如 arm、 avr32、 m68k 等,我们现在用的是 ARM 芯片,所以只需要关心 arm 文件夹即可,打开 arm 文件夹里面内容如图 :
mach 开头的文件夹是跟具体的设备有关的,比如“mach-exynos”就是跟三星的 exyons 系列 CPU 有关的文件。我们使用的是 I.MX6ULL,所以要关注“imx-common”这个文件夹。另外“cpu”这个文件夹也是和 cpu 架构有关的,打开以后如图所示:
可以看出有多种 ARM 架构相关的文件夹, I.MX6ULL 使用的 Cortex-A7 内核,Cortex-A7 属于 armv7,所以我们要关心“armv7”这个文件夹。 cpu 文件夹里面有个名为“uboot.lds”的链接脚本文件,这个就是 ARM 芯片所使用的 u-boot 链接脚本文件! armv7 这个文件夹里面的文件都是跟 ARMV7 架构有关的是我们分析 uboot 启动源码的时候需要重点关注的。
3.3 board 文件夹
board 文件夹就是和具体的板子有关的,打开此文件夹,里面全是不同的板子,毫无疑问正点原子的开发板肯定也在里面(正点原子添加的),NXP官方的评估板也在里边。 borad 文件夹里面有个名为“freescale”的文件夹:
有使用 freescale 芯片的板子都放到此文件夹中, I.MX 系列以前属于 freescale,只是freescale 后来被 NXP 收购了。打开此 freescale 文件夹,在里面找到和 mx6u(I.MX6UL/ULL)有关的文件夹,如下图:
有 5 个文件夹,这 5 个文件夹对应 5 种板子,以“mx6ul”开头的表示使用I.MX6UL 芯片的板子,以 mx6ull 开头的表示使用 I.MX6ULL 芯片的板子。mx6ullevk 是 NXP官方的I.MX6ULL开发板,正点原子的ALPHA开发板就是在这个基础上开发的。我们后面移植uboot 到时候就是参考 NXP 官方的开发板,也就是要参考 mx6ullevk 这个文件夹来定义我们的板子。
3.4 configs 文件夹
此文件夹为 uboot 配置文件, uboot 是可配置的,但是你要是自己从头开始一个一个项目的配置,那就太麻烦了,因此一般半导体或者开发板厂商都会制作好一个配置文件。我们可以在这个做好的配置文件基础上来添加自己想要的功能,这些半导体厂商或者开发板厂商制作好的配置文件统一命名为 “ xxx_defconfig ” , xxx 表示开发板名字,这些 defconfig 文件都存放在 configs文件夹,因此, NXP 官方开发板的开发板配置文件肯定也在这个文件夹中
图中这 4 个文件中的mx6ull_14x14_evk_emmc_defconfig就是NXPimu6ull evk评估开发板所对应的 uboot 默认配置文件。使用“make xxx_defconfig”命令即可配置 uboot,比如 :
1 | make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig |
上述命令就是配置NXP官方的imx6ull evk评估板所使用的 uboot。在编译 uboot 之前一定要使用 defconfig 来配置 uboot!
3.5 .u-boot.xxx_cmd 文件
.u-boot.xxx_cmd 是一系列的文件,这些文件都是编译生成的,都是一些命令文件,比如文件.u-boot.bin.cmd,看名字应该是和 u-boot.bin 有关的,此文件的内容如下:
u-boot.bin.cmd 里面定义了一个变量: cmd_u-boot.bin,此变量的值为“cp u-boot-nodtb.binu-boot.bin”,也就是拷贝一份 u-boot-nodtb.bin 文件,并且重命名为 u-boot.bin,这个就是 u-boot.bin的来源,来自于文件 u-boot-nodtb.bin。 那 么 u-boot-nodtb.bin 是 怎 么 来 的 呢 ? 文 件 .u-boot-nodtb.bin.cmd 就 是 用 于 生 成 uboot.nodtb.bin 的,此文件内容如下:
这里用到了 arm-linux-gnueabihf-objcopy,使用 objcopy 将 ELF 格式的 u-boot 文件转换为二进制的 u-boot-nodtb.bin 文件。文件 u-boot 是 ELF 格式的文件,文件.u-boot.cmd 用于生成 u-boot,文件内容如下:
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 来完成的,此文件内容如下:
可以看出,这里用到了工具 tools/mkimage,而 IVT、 DCD 等数据保存在了文件 board/freescale/mx6ullevk/imximage.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文件。
3.6 Makefile 文件
这个是顶层 Makefile 文件, Makefile 是支持嵌套的,也就是顶层 Makefile 可以调用子目录中的 Makefile 文件。 Makefile 嵌套在大项目中很常见,一般大项目里面所有的源代码都不会放到同一个目录中,各个功能模块的源代码都是分开的,各自存放在各自的目录中。每个功能模块目录下都有一个 Makefile,这个 Makefile 只处理本模块的编译链接工作,这样所有的编译链接工作就不用全部放到一个 Makefile 中,可以使得 Makefile 变得简洁明了。
uboot 源码根目录下的 Makefile 是顶层 Makefile,他会调用其它的模块的 Makefile 文件,比如 drivers/adc/Makefile。当然了,顶层 Makefile 要做的工作可远不止调用子目录 Makefile 这么简单。
3.7 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 的复制文件。
3.8 .config 文件
uboot 配置文件,使用命令“make xxx_defconfig”配置 uboot 以后就会自动生成, .config 内容如下:
可以看出.config 文件中都是以“CONFIG_”开始的配置项,这些配置项就是 Makefile 中的变量,因此后面都跟有相应的值, uboot 的顶层 Makefile 或子 Makefile 会调用这些变量值。在.config 中会有大量的变量值为‘y’,这些为‘y’的变量一般用于控制某项功能是否使能,为‘y’的话就表示功能使能,比如:
1 | CONFIG_CMD_BOOTM=y |
如果使能了 bootd 这个命令的话, CONFIG_CMD_BOOTM 就为‘y’。在 cmd/Makefile 中有如下代码:
上边代码中有这么一句:
1 | obj-$(CONFIG_CMD_BOOTM) += bootm.o |
CONFIG_CMD_BOOTM=y,将其展开就是:
1 | 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 内核中都是采用这种方法来选择使能某个功能,编译对应的源码文件。
4. 创建VScode工程
4.1 屏蔽文件和目录?
我是通过windows下的VScode的SSH插件远程登录ubuntu来进行开发,使用VScode还是比较方便的,怎么用SSH插件连接ubuntu?可以看这篇笔记《LV02-03-连接远程服务器》。然后我们可以创建一个工作区:
工作区文件内容如下所示,后边会用到这个文件。
1 | { |
然后一定要打开这个工作区,后边的操作才能生效。这样一个完整的 VSCode 工程就建立起来了。但是这个 VSCode 工程包含了 uboot 的所有文件, uboot
中有些文件是不需要的,比如 arch 目录下是各种架构的文件夹 :
在 arch 目录下,我们只需要 arm 文件夹,所以需要将其它的目录从 VSCode 中给屏蔽掉,比如将 arch/avr32 这个目录给屏蔽掉。我们修改工程工作区文件:
1 | { |
其中”search.exclude”里面是需要在搜索结果中排除的文件或者文件夹, “files.exclude”是工程目录中需要排除的文件或者文件夹。我们需要将arch/avr32 文件夹下的所有文件从搜索结果和左侧的工程目录中都排除掉,就可以按上边的写法,”arch/avr32”: true,冒号前面的是要排除的文件或者文件夹,冒号后面为是否将文件排除, true 表示排除, false 表示不排除。 。我们可以看一下效果,这是屏蔽掉上边添加的内容的情况:
当把那两行去掉的时候,这个文件夹就会消失:
会发现,arch/avr32这个目录在工程中消失了,但是文件夹其实还在,只是不在工程中,这样我们屏蔽掉一些不用的文件以及目录,阅读工程源码的时候就会很方便啦。
4.2 工作区文件内容
我们把不需要的文件和目录都从工作区剔除,我们在工作区文件中添加以下内容即可:
1 | { |
上述代码用到了通配符“*”,比如“*/.o”表示所有.o 结尾的文件。“configs/[a-l]*”表示 configs 目录下所有以‘ a ’ ~ ‘ l ’开头的文件或者文件夹。 上述配置只是排除了一部分文件夹,我们在实际的使用中可以根据自己的实际需求来选择将哪些文件或者文件夹排除掉。排除以后我们的工程就会清爽很多,搜索的时候也不会跳出很多文件了。