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

未找到图片xiazai

建议第一次移植使用和我一样的版本,后续再移植到自己需要的版本

下载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/
单板目录mx6ullfire的结构
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程序。

以上Kconfig文件中指定mx6ullfire板卡的代码片段
 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特有的文件,默认已添加头部信息。

在imximage.cfg添加的头部信息
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
未找到图片dtfile

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目录下包含的所有库文件用于编译。

未找到图片makfile_dto

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文件。

5.7. 启动

未找到图片qd

启动后可以看到确实可以正常使用,也具有我们的定制功能。

提供一份移植好的“新版本”uboot源码供大家参考 u-boot-2021.10-rc4.tar.gz