LV05-02-U-Boot-01-NXP-uboot

本文主要是uboot——NXP官方固件的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
PC端开发环境 Windows Windows11
Ubuntu Ubuntu20.04.2的64位版本
VMware® Workstation 17 Pro 17.6.0 build-24238078
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
Win32DiskImager Win32DiskImager v1.0
Linux开发板环境 Linux开发板 正点原子 i.MX6ULL Linux 阿尔法开发板
uboot NXP官方提供的uboot,使用的uboot版本为U-Boot 2019.04
linux内核 linux-4.19.71(NXP官方提供)
点击查看本文参考资料
分类 网址 说明
官方网站 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内核官网
其他网站 kernel - Linux source code (v4.15) - Bootlin linux内核源码在线查看
点击查看相关文件下载
分类 网址 说明
NXP https://github.com/nxp-imx NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库
nxp-imx/linux-imx/releases/tag/v4.19.71 NXP linux内核仓库tags中的v4.19.71
nxp-imx/uboot-imx/releases/tag/rel_imx_4.19.35_1.1.0 NXP u-boot仓库tags中的rel_imx_4.19.35_1.1.0
I.MX6ULL i.MX 6ULL Applications Processors for Industrial Products I.MX6ULL 芯片手册(datasheet,可以在线查看)
i.MX 6ULL Applications ProcessorReference Manual I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网)
Source Code https://elixir.bootlin.com/linux/latest/source linux kernel源码
https://elixir.bootlin.com/u-boot/latest/source uboot源码

一、uboot

前面我们简单学习过uboot相关的概念,此处再回顾一下,总的来说uboot的目的是为了正确引导内核的启动,它分为两个阶段,即boot + loader,boot阶段启动系统,初始化硬件设备,建立内存空间映射图,将系统的软硬件带到一个合适的状态,loader阶段将操作系统内核文件加载至内存,之后跳转到内核所在地址运行。

那么我们今天来编译uboot,后面会简单修改uboot的内容适配自己的开发板,因为在真正的生产环境中,uboot是使用芯片原厂做好的,只是根据需要修改一下uboot,而不会去大改uboot的源码,这样子没有必要也没有意义,因为uboot就是为了引导内核启动的,启动后uboot就没有什么作用了,与其将uboot改得乱七八糟还不如花时间去维护内核的稳定性。

二、uboot源码的下载

1. 源码版本选择

由于我使用的是ubuntu是20.04,所以太老版本的uboot编译的时候会报错,这是老版本的uboot因为用到的一些库在新版本的ubuntu中更新了,不再适用,这里我们直接下载一个比较新的版本,这里我选择uboot的2019.04版本(其实也尝试了更新的,但是吧,能力有限,老的东西都没明白,新的更不明白了,还是先用这个,熟练了再说更新的版本),我们可以去nxp的github仓库找一下:

image-20241102135824099

我们找到这个分支:nxp-imx/uboot-imx at imx_v2019.04_4.19.35_1.1.0 (github.com),我们打开提交记录来看一下:

image-20241102135858435

可以发现最新提交为:4d377539a1190e838eae5d8b8a794dde0696d572,我们就以这个版本为基础。我们看一下有没有tag,这样后面也好搞,我们去tag里翻一下,发现是有一个rel_imx_4.19.35_1.1.0的:

image-20241102135947763

我们点开看一下,从这里点开会发现它就是刚才的分支,那么tag页面怎么去?我们直接用下面这个地址:

1
https://github.com/nxp-imx/uboot-imx/releases/tag/<tag_name>

也就是:Release rel_imx_4.19.35_1.1.0: MLK-22866 imx8: Remove the optee shared memory from DDR banks · nxp-imx/uboot-imx (github.com)

image-20241102140008607

会发现这里的简短的提交记录和刚才是一样的,所以我们以后可以通过tag和提交记录或者分支来拉取这个版本的代码。是哪个版本的uboot?我们可以看一下里面的makefile文件:uboot-imx/Makefile at rel_imx_4.19.35_1.1.0 · nxp-imx/uboot-imx (github.com)

image-20241101222050551

会发现版本正确。

2. 下载源码

我们可以使用下面的命令来下载:

1
2
git clone -b rel_imx_4.19.35_1.1.0 --depth=1 https://github.com/nxp-imx/uboot-imx.git
git clone -b rel_imx_4.19.35_1.1.0 --depth=1 git@github.com:nxp-imx/uboot-imx.git

这里我们加上 –depth参数,毕竟我们对以往的提交记录并不怎么感兴趣,另外,以往上万条提交记录,这里全下载的话要很久的。其实我们也可以直接去tag页面点击Source Code下载压缩包。我这里直接搞完上传到自己的gitee仓库了,所以我这里从自己的gitee仓库拉一下:

1
git clone git@gitee.com:sumumm/u-boot.git
image-20241102141949663

图中这一次提交的时候仅仅是更新了nxp的官方uboot 2019.04源码,还未做任何移植和适配。其实直接拉取最新的也一样,这里后面适配会添加支持包的,原版的不会动。只是这里和原版的文件稍微有些区别:

image-20241102141744371

我的仓库中左侧设这几个文件没有,好像并不影响,这是因为这几个文件被git忽略了。

三、编译源码

1. 更新交叉编译工具链

这里是因为后面编译的时候有警告:

image-20241102103908357

我们直接到ARM官网去找:Downloads | GNU-A Downloads – Arm Developer

QQ_1730515632502

我这里也选这个2019年的版本:

image-20241102104819947

往下找到在linux中使用的版本:

image-20241102104947391

可以用下面的脚本来下载安装,或者看这里develop/arm-gcc.sh · 苏木/linux-shell-script - 码云 - 开源中国 (gitee.com)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/bin/sh

HOST=arm-linux-gnueabihf
SCRIPT_PATH=$(pwd)

#修改源码包解压后的名称
MAJOR_NAME=gcc-arm-linux-gnueabihf

#修改需要下载的源码版本前缀和后缀
OPENSRC_VER_PREFIX=8.3
OPENSRC_VER_SUFFIX=.0

PACKAGE_NAME=${MAJOR_NAME}-${OPENSRC_VER_PREFIX}${OPENSRC_VER_SUFFIX}

#定义压缩包名称
COMPRESS_PACKAGE=gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.xz

#定义编译后安装--生成的文件,文件夹位置路径
INSTALL_PATH=/opt/${PACKAGE_NAME}

#无需修改--下载地址
DOWNLOAD_LINK=https://developer.arm.com/-/media/Files/downloads/gnu-a/8.3-2019.03/binrel/${COMPRESS_PACKAGE}

#下载源码包
do_download_src () {
echo "\033[1;33mstart download ${COMPRESS_PACKAGE}...\033[0m"
if [ ! -f "${COMPRESS_PACKAGE}" ];then
if [ ! -d "${PACKAGE_NAME}" ];then
wget -c ${DOWNLOAD_LINK}
fi
fi
echo "\033[1;33mdone...\033[0m"
}

#解压源码包
do_tar_package () {
echo "\033[1;33mstart unpacking the ${PACKAGE_NAME} package ...\033[0m"

mkdir -p ${INSTALL_PATH}

if [ ! -d "${PACKAGE_NAME}" ];then
tar -xf ${COMPRESS_PACKAGE} -C ${INSTALL_PATH} --strip-components=1
fi
echo "\033[1;33mdone...\033[0m"
}

#删除下载的文件
do_delete_file () {
cd ${SCRIPT_PATH}
if [ -f "${PACKAGE_NAME}" ];then
sudo rm -f ${PACKAGE_NAME}
fi
}

do_download_src
do_tar_package
# do_delete_file

exit $?

安装完毕后记得添加环境变量,然后看一下版本信息:

1
2
3
4
5
6
7
8
sumu@sumu-virtual-machine:~$ arm-linux-gnueabihf-gcc -v
使用内建 specs。
COLLECT_GCC=arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/home/sumu/2software/gcc-arm-linux-gnueabihf-8.3.0/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/lto-wrapper
目标:arm-linux-gnueabihf
配置为:/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c,c++,fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)'
线程模型:posix
gcc 版本 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36))

2. 安装一些库

1
2
sudo apt-get install lib32ncurses5 lib32tinfo5 libc6-i386 # 野火的教程中需要安装的
sudo apt-get install libncurses5-dev                      # 正点原子教程需要安装的

我看了两个教程,他们安装的库名字有点不太一样,我安装的是libncurses5-dev这个,也没什么问题。

3. 编译源码

3.1 清理工程

1
2
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean # 清除生成的所有文件
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- clean # 清除部分文件

为什么有两个?他们有什么区别?(这里为方便演示,直接对工程编译后再清除,其实首次下载完源码不需要清除也没啥问题)编译完成的时候源码目录下文件如下:

image-20241118223813509
  • make clean

命令主要清除的是编译过程中生成的可执行文件以及配置文件。这些文件是具体编译任务的产物,例如.exe文件、.o文件等。清除这些文件有助于保持构建环境的干净,避免可能因残留文件导致的问题。然而,make clean并不会清除其他一些可能存在的文件,如日志文件、中间编译结果等,这使得它在彻底性上有所不足。

image-20241118223901534
  • make distclean

这个命令则更为彻底。它不仅清除可执行文件和配置文件,还会清除所有由make命令生成的文件。这包括了编译过程中产生的中间文件、日志文件、缓存文件等。通过执行make distclean,我们能够确保构建环境的完全清洁,为后续的构建过程提供一个干净、无残留的环境。然而,这也意味着清除了一些可能需要保留的文件,比如版本控制系统的缓存文件等。

image-20241118224126085

总结来说,make clean和make distclean的使用场景有所不同。make clean适用于在编译过程中需要局部清理,以排除残留文件影响的情况;而make distclean则适用于构建环境需要彻底清洁的情况,以准备进行新版本的构建或测试。在实际使用中,选择合适的命令可以提高构建过程的效率和准确性。

3.2 配置工程

1
2
#make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig 
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_defconfig

在编译uboot的时候需要我们自定义配置,而nxp官方会提供一些默认配置,这些配置在uboot /configs/目录下,如:

1
2
3
mx6ull_14x14_evk_defconfig
mx6ull_14x14_evk_emmc_defconfig
mx6ull_14x14_evk_nand_defconfig

这一些就是nxp官方为imx6ull提供的配置文件,可以编译生成从SD卡启动的uboot、从emmc启动的uboot以及从nand启动的uboot,我们可以根据需求选择不同的配置文件从而编译不同的uboot。

在运行以上配置命令后,Makefile会根据对应的配置文件的内容将配置更新到当前目录下的 .config 文件中,接下来的编译则是根据 .config 文件的配置进行编译的。

image-20241102092057899

3.3 开始编译

1
make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16

编译完成后,会得到这些文件:

image-20241102092215192

这里我们主要是用带有-dtb的这两个文件,imx文件就是bin文件在头部加入了IVT信息得到的,我们烧写到SD卡的时候也是用的imx文件。

u-boot.bin 是 U-Boot 的主要可执行文件。

u-boot.dtb 是描述硬件信息的设备树文件。

u-boot-dtb.bin 是包含了 U-Boot 和设备树的合并二进制文件。

u-boot-dtb.imx 是为 NXP i.MX 系列处理器生成的特定格式的启动镜像,包含了头部IVT DCD信息。

四、下载验证

1. ubuntu下烧写到SD卡

  • 确定SD卡在uboot中的节点:
1
ls /dev/sd*
image-20241102093014093
  • 烧写到sd卡中

我们在uboot下通过以下命令下载到SD卡中:

1
sudo dd if=u-boot-dtb.imx of=/dev/sdc bs=1k seek=1 conv=fsync

注意不能选错SD卡节点,否则可能会损坏电脑磁盘数据。这个命令直接从偏移1KB的位置开始烧写imx文件。

image-20241102093114942

2. 开发板验证

我们把alpha开发板拨码开关拨到从SD卡启动,连接好串口,上电,然后就会看到以下内容:

image-20241102093332377

一般来说,串口、USB这些在uboot过程中都被初始化好了,我们是从nxp官方拉的源码,所以这些基础的驱动肯定是没问题的,只要开发板串口这些和官方是对应的,就可以直接跑起来,另外正点原子这块板子的屏幕也是可以直接用的,只是分辨率会有些问题,网口是不能用的,后面需要移植。