5. Uboot的移植¶
该教程仅用于学习与参考,实际产品建议使用NXP官方或者我们提供的uboot源码
NXP提供的uboot下载链接:
https://github.com/Freescale/u-boot-fslc
野火提供的uboot下载链接:
https://gitee.com/Embedfire/ebf_linux_uboot
获取uboot源码具体参考 uboot 章节。
5.1. 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,不过,有很多现成的 bootloader 软件可以使用,比如 U-Boot、 vivi、 RedBoot 等等,其中以 U-Boot 使用最为广泛。
uboot 的全称是 Universal Boot Loader, uboot 是一个遵循 GPL 协议的开源软件, uboot 是一个裸机代码,可以看作是一个裸机综合例程。现在的 uboot 已经支持液晶屏、网络、 USB 等高级功能。 uboot 官网为 http://www.denx.de/wiki/U-Boot/
5.2. 下载安装编译镜像系统¶
使用平台:Ubuntu 18.04.5 LTS 版本
可以使用我们提供的虚拟机镜像 https://doc.embedfire.com/products/link/zh/latest/linux/ebf_i.mx6ull.html#id4
也可以自己下载ubuntu 18.04.5 LTS官方镜像搭建
https://mirrors.aliyun.com/ubuntu-releases/bionic/ubuntu-18.04.5-desktop-amd64.iso
5.3. 安装编译工具和依赖¶
使用apt工具能快速安装好我们需要的工具和依赖
1 | sudo apt install make git gcc-arm-none-eabi gcc bison flex libssl-dev dpkg-dev lzop libncurses5-dev
|
5.4. 获取uboot¶
5.4.1. 下载源代码¶
我们直接从uboot官方下载好最新的源码进行适配,将我们使用的旧版本uboot移植到新版本。
https://ftp.denx.de/pub/u-boot/ 或 ftp://ftp.denx.de/pub/u-boot/
截止至写本教程的时间最新版本为 u-boot-2021.10-rc4.tar.bz2
建议第一次移植使用和我一样的版本,后续再移植到自己需要的版本
下载u-boot-2021.10版本的源码 u-boot-2021.10-rc4.tar.bz2
解压源码
1 | tar -xjvf u-boot-2021.10-rc4.tar.bz2
|
获取“旧版本”的uboot,此处使用野火ebf_v2020_10_imx分支的uboot。
1 2 3 4 | git clone -b ebf_v2020_10_imx https://gitee.com/Embedfire/ebf_linux_uboot
#或者
git clone -b ebf_v2020_10_imx https://github.com/Embedfire/ebf_linux_uboot
|
5.5. 移植¶
一般人移植主要是想获取新版本的uboot,对于底层的官方适配我们不需要详细了解,如感兴趣我后期再编写一份uboot底层源码的适配分析。
提示
后续讲到的文件中可能已经添加了需要添加的内容,但仍作说明,旨在方便大家后续移植自己需要的uboot。
5.5.1. 头文件¶
从旧版本uboot的include/configs复制一份相应头文件到新版本include/configs目录下
1 | cp ebf_linux_uboot/include/configs/mx6ullfire.h u-boot-2021.10-rc4/include/configs/
|
mx6ullfire.h 头文件里包含了uboot的环境参数和一些配置信息。
5.5.2. 配置文件¶
emmc版本的配置文件为 mx6ull_fire_mmc_defconfig
nand版本的配置文件为 mx6ull_fire_nand_defconfig
将以上两版本的配置文件都复制到新版本uboot。
1 | cp ebf_linux_uboot/configs/mx6ull_fire_* u-boot-2021.10-rc4/configs/
|
这里有几个参数要注意一下
CONFIG_TARGET_MX6ULL_FIRE=y 这行参数与两处有相对应,下面会讲到,这里留意一下。
CONFIG_DEFAULT_DEVICE_TREE=”imx6ull-fire-mmc” 这行参数是设备树名称,要与uboot设备树对应,等会讲设备树复制的时候会讲到,也留意一下。
CONFIG_SYS_EXTRA_OPTIONS=”IMX_CONFIG=board/freescale/mx6ullfire/imximage.cfg” 这行参数是配置头部信息的,指向的是板子目录的cfg文件。
5.5.3. 单板目录和文件¶
1 | cp -rf ebf_linux_uboot/board/freescale/mx6ullfire/ u-boot-2021.10-rc4/board/freescale/
|
1 2 3 4 5 6 7 | ./mx6ullfire
├── imximage.cfg
├── Kconfig
├── MAINTAINERS
├── Makefile
├── mx6ullfire.c
└── plugin.S
|
mx6ullfire.c :里写了一些uboot启动代码和我们对板子引脚读取的代码。
plugin.S :用汇编写的设置ddr和时钟,一般不需要更改。
Makefile :里面修改C文件编译后的o文件,有多少个就写多少个o文件,注意与c文件名字相同。
Kconfig :U-Boot配置选项文件,定义了编译时需要配置哪些选项用于生成适用于该开发板的U-Boot程序。
1 2 3 4 5 6 7 8 9 10 11 12 | if TARGET_MX6ULL_FIRE (上面所说的两处对应其中的一处)
config SYS_BOARD
default "mx6ullfire" (目标文件夹)
config SYS_VENDOR
default "freescale" (路径)
config SYS_CONFIG_NAME
default "mx6ullfire" (头文件名称 注意:头文件在include/configs下名称为"头文件名称.h")
endif
|
imximage.cfg :NXP特有的文件,默认已添加头部信息。
1 | PLUGIN board/freescale/mx6ullfire/plugin.bin 0x00907000
|
以上命令是U-Boot启动时加载插件的命令。其中board/freescale/mx6ullfire/plugin.bin 是插件的二进制文件路径,0x00907000 是插件的加载地址。可以用于扩展U-Boot功能。
5.5.4. 添加Kconfig信息¶
修改文件目录为:arch/arm/mach-imx/mx6/Kconfig
在这个文件中添加我们的板子信息方便Makefile识别编译。
5.5.4.1. 添加板卡支持¶
在上述Kconfig文件中的config TARGET_MX6ULL_14X14_EVK配置的下面添加如下代码。
1 2 3 4 5 6 7 | config TARGET_MX6ULL_FIRE
bool "Support mx6ullfire"
depends on MX6ULL
select BOARD_LATE_INIT
select DM
select DM_THERMAL
imply CMD_DM
|
以上配置项定义了一个名为TARGET_MX6ULL_FIRE的目标设备,用于指定是否支持MX6ULL_FIRE开发板。
5.5.4.2. 添加配置选项¶
在上述Kconfig文件中的source “board/freescale/mx6ullevk/Kconfig”下添加如下代码
1 | source "board/freescale/mx6ullfire/Kconfig"
|
将MX6ULL-FIRE开发板的配置选项包含到上层Kconfig文件中,即可调用mx6ullfire中的Kconfig进行配置。
5.5.5. 添加设备树¶
5.5.5.1. 添加设备树信息¶
修改文件目录为:arch/arm/dts/Makefile
在上述Makefile文件中的dtb-$(CONFIG_MX6ULL) += 下面添加设备树
设备树的名字,参考config里的CONFIG_DEFAULT_DEVICE_TREE=”imx6ull-fire-mmc”,如果是nand版本则是”imx6ull-fire-nand”。
添加的内容:
imx6ull-fire-mmc.dtb
imx6ull-fire-nand.dtb
1 2 3 4 5 6 7 8 9 10 | dtb-$(CONFIG_MX6ULL) += \
imx6ull-14x14-evk.dtb \
imx6ull-fire-mmc.dtb \
imx6ull-fire-nand.dtb \
imx6ull-colibri.dtb \
imx6ull-myir-mys-6ulx-eval.dtb \
imx6ull-phytec-segin-ff-rdk-emmc.dtb \
imx6ull-dart-6ul.dtb \
imx6ull-somlabs-visionsom.dtb \
imx6ulz-14x14-evk.dtb
|
为什么在这添加,因为配置文件里设置了CONFIG_MX6ULL=y,该选项被启用,会生成针对该处理器的DTB文件。
5.5.5.2. 复制设备树源码¶
复制一份设备树源码到新版本的uboot。
将野火emmc版本和nand版本的设备树都复制到新版本uboot。
1 | cp ebf_linux_uboot/arch/arm/dts/imx6ull-fire-* u-boot-2021.10-rc4/arch/arm/dts/
|
5.5.5.3. 修改板卡soc文件¶
修改文件目录为:arch/arm/mach-imx/mx6/soc.c
在soc.c文件开头加上
1 | #include <asm/setup.h>
|
在soc.c文件末尾加上
1 2 3 4 5 6 7 8 9 10 11 12 | #ifdef CONFIG_SERIAL_TAG
void get_board_serial(struct tag_serialnr *serialnr)
{
struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
struct fuse_bank *bank = &ocotp->bank[0];
struct fuse_bank0_regs *fuse =
(struct fuse_bank0_regs *)bank->fuse_regs;
serialnr->low = fuse->uid_low;
serialnr->high = fuse->uid_high;
}
#endif
|
以上是一个获取板级信息的函数,该函数使用了SoC内部的OTP存储器,读取存储在OTP中的唯一设备标识符UID,并将其保存到Linux内核启动参数中的struct tag_serialnr结构体中,使其成为内核启动参数之一。
5.5.6. 设备树插件移植(野火特有)¶
5.5.6.1. 设备树插件配置¶
5.5.6.1.1. 复制源码¶
1 2 3 cp -rf ebf_linux_uboot/cmd/dtfile.c u-boot-2021.10-rc4/cmd/ cp -rf ebf_linux_uboot/include/dtoverlay.h u-boot-2021.10-rc4/include/ cp -rf ebf_linux_uboot/include/ramblockdev.h u-boot-2021.10-rc4/include/
dtfile.c 用于实现uboot命令dtfile。该命令用于在uboot中加载并解析设备树文件,并将其显示输出或保存到指定的文件中。
dtoverlay.h 用于定义设备树相关的数据结构和函数声明。
ramblockdev.h 用于定义RAM块设备。
5.5.6.1.2. 修改Makefile¶
修改文件目录为:cmd/Makefile
修改Makefile加入编译dtfile.c配置,使编译uboot时将该文件编译进去。
在obj-$(CONFIG_CMD_FDT) += fdt.o的下面添加
1 | obj-$(CONFIG_OF_LIBFDT) += dtfile.o
|
5.5.6.2. UID配置¶
5.5.6.2.1. 复制源码和添加源码¶
1 2 3 4 5 cp -rf ebf_linux_uboot/include/init.h u-boot-2021.10-rc4/include/ cp -rf ebf_linux_uboot/common/board_r.c u-boot-2021.10-rc4/common/board_r.c cp -rf ebf_linux_uboot/dtoverlay/ u-boot-2021.10-rc4/
init.h 用于声明uboot启动过程中的初始化函数和数据结构。
board_r.c 包含一些通用的板级初始化函数和一些通用的工具函数,可以用于不同的硬件平台。
dtoverlay 提供了设备树覆盖的功能,通过加载这些覆盖文件,可以在U-Boot运行时动态地修改设备树。
5.5.6.2.2. 修改顶层Makefile¶
修改文件目录为:u-boot-2021.10-rc4/Makefile
添加如下代码
1 | libs-y += dtoverlay/
|
添加dtoverlay目录下包含的所有库文件用于编译。
5.6. 编译及烧录¶
如何编译和烧录详细请看前面uboot的编译和uboot的烧录章节,下面以编译emmc版本为例。
1 2 3 4 5 6 | cd u-boot-2021.10-rc4/
sudo make distclean
#选择emmc版本的配置文件,如果是nand版本则是mx6ull_fire_nand_defconfig
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi- mx6ull_fire_mmc_defconfig
#编译uboot
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi-
|
编译生成的u-boot-dtb.imx就是我们需要的uboot文件。