7. 定制自己的Uboot单板

7.1. 简介

我们提供的uboot中默认都是我们的开发板,虽说我们可以直接在我们的开发板上直接修改,使 uboot 可以完整的运行在我们的板子上。但是从学习的角度来讲,这样我们就不能了解到 uboot 是如何添加新平台的。接下来我们就参考我们的IMX6ULL开发板,学习如何在 uboot 中添加自己的开发板或者开发平台

7.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

7.3. 安装编译工具和依赖

使用apt工具能快速安装好我们需要的工具和依赖

1
  sudo apt install make git gcc-arm-none-eabi gcc bison flex libssl-dev dpkg-dev lzop libncurses5-dev

7.4. 获取uboot

7.4.1. 下载源代码

下载我们的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

7.5. 添加开发板默认配置文件

重要

下面以mmc版本为例,如果是nand版本把“mmc”改为“nand”即可。“name”可改为自己定义的名字。

先在 configs 目录下创建默认配置文件,复制 mx6ull_fire_mmc_defconfig,然后重命名为 mx6ull_name_mmc_defconfig,命令如下:

1
2
3
4
5
  cd configs/
  cp mx6ull_fire_mmc_defconfig mx6ull_name_mmc_defconfig

  #若为nand版本则是以下命令,后续“mmc”版本和“nand”版本区别说明不再重复
  cp mx6ull_fire_nand_defconfig mx6ull_name_nand_defconfig

然后将文件mx6ull_name_mmc_defconfig中的CONFIG_SYS_EXTRA_OPTIONS内容改成如下

1
  CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ull_name/imximage.cfg"

board/freescale/mx6ull_name就是我们后续要添加的单板目录。

7.5.1. 添加头文件

复制一份include/configs/mx6ullfire.h更名为include/configs/mx6ull_name.h

1
  cp include/configs/mx6ullfire.h include/configs/mx6ull_name.h

更改

1
2
3
4
5
      #ifndef __MX6ULLFIRE_CONFIG_H
      #define __MX6ULLFIRE_CONFIG_H
      改为:
      #ifndef __MX6ULL_NAME_CONFIG_H
      #define __MX6ULL_NAME_CONFIG_H

以下是部分代码分析

 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
      #define PHYS_SDRAM_SIZE SZ_512M
      ....
      #define CONFIG_SYS_MALLOC_LEN           (16 * SZ_1M)
      ....
      #define CONFIG_MXC_UART_BASE            UART1_BASE
      ....
      #define CONFIG_SYS_FSL_ESDHC_ADDR       USDHC2_BASE_ADDR
      ....
      #CONFIG_EXTRA_ENV_SETTINGS              "....."
      ....
      #define CONFIG_BOOTCOMMAND              "....."
      ....
      #define CONFIG_SYS_LOAD_ADDR            CONFIG_LOADADDR
      #define CONFIG_SYS_HZ                   1000
      #define PHYS_SDRAM                      MMDC0_ARB_BASE_ADDR
      ....
      #define CONFIG_SYS_INIT_SP_OFFSET \
              (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
      #define CONFIG_SYS_INIT_SP_ADDR \
              (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
      #define CONFIG_MMCROOT                  "/dev/mmcblk1p2"  /* USDHC2 */
      #define CONFIG_FEC_ENET_DEV             1
      #if (CONFIG_FEC_ENET_DEV == 0)
      #define CONFIG_ETHPRIME                 "eth0"
      #elif (CONFIG_FEC_ENET_DEV == 1)
      #define CONFIG_ETHPRIME                 "eth1"
  • PHYS_SDRAM_SIZE :设置了SDRAM的内存大小

  • CONFIG_SYS_MALLOC_LEN :为malloc内存池大小,这里设置为16MB

  • CONFIG_MXC_UART_BASE :这里使用串口1,基地址为 UART1_BASE, UART1_BASE 定义在文件arch/arm/include/asm/arch-mx6/imx-regs.h 中, imx-regs.h 是 I.MX6ULL 寄存器描述文件,根据imx-regs.h 可得到 UART1_BASE 的值如下

1
2
3
4
      UART1_BASE= (ATZ1_BASE_ADDR + 0x20000)
          =AIPS1_ARB_BASE_ADDR + 0x20000
          =0x02000000 + 0x20000
          =0X02020000

可以看到在手册中UART1的基地址

未找到图片uart1
  • CONFIG_SYS_FSL_ESDHC_ADDR:宏CONFIG_SYS_FSL_ESDHC_ADDR为 EMMC 所使用接口的寄存器基地址,也就是 USDHC2 的基地址

  • CONFIG_EXTRA_ENV_SETTINGS : 通 过 条 件 编 译 来 设 置 宏 CONFIG_EXTRA_ENV_SETTINGS,宏CONFIG_EXTRA_ENV_SETTINGS 也是设置一些环境变量,此宏会设置bootargs这个环境变量

  • CONFIG_BOOTCOMMAND:设置宏 CONFIG_BOOTCOMMAND,此宏就是设置环境变量bootcmd的值。

  • CONFIG_SYS_LOAD_ADDR:表示 linux kernel 在DRAM中的加载地址,也就是 linux kernel 在 DRAM 中的存储首地址,CONFIG_LOADADDR=0X80800000

  • CONFIG_SYS_HZ:宏 CONFIG_SYS_HZ 为系统时钟频率,这里为 1000Hz。

  • PHYS_SDRAM:为 I.MX6ULL 的 DRAM 控制器 MMDC0 所管辖的 DRAM 范围起始地址,也就是 0X80000000

  • CONFIG_SYS_SDRAM_BASE:为 DRAM 的起始地址。

  • CONFIG_SYS_INIT_RAM_ADDR:为 I.MX6ULL 内部 IRAM 的起始地址(也就是 OCRAM 的起始地址),为 0X00900000

  • CONFIG_SYS_INIT_RAM_SIZE:为 I.MX6ULL 内部 IRAM 的大小(OCRAM的大小),为 0X00040000=128KB

  • CONFIG_SYS_INIT_SP_OFFSET和CONFIG_SYS_INIT_SP_ADDR:CONFIG_SYS_INIT_SP_OFFSET 和 CONFIG_SYS_INIT_SP_ADDR 与初始 SP 有关,第一个为初始 SP 偏移,第二个为初始 SP 地址

  • CONFIG_MMCROOT :设置进入 linux 系统的根文件系统所在的分区,这里设置为”/dev/mmcblk1p2”,也就是 EMMC 设备的第 2 个分区。第 0 个分区保存 uboot,第 1 个分区保存 linux 镜像和设备树,第 2 个分区为 Linux 系统的根文件系统

  • CONFIG_FEC_ENET_DEV:指定 uboot 所使用的网口, I.MX6ULL 有两个网口,为 0 的时候使用 ENET1,为 1 的时候使用 ENET2

  • CONFIG_VIDEO:用于开启 LCD,CONFIG_VIDEO_LOGO 使能 LOGO 显示, CONFIG_CMD_BMP 使能 BMP 图片显示指令。这样就可以在 uboot 中显示图片了,一般用于显示 logo。

关于 mx6ull_name_emmc.h 就讲解到这里,其中以 CONFIG_CMD 开头的宏都是用于使能相应命令的,其他的以 CONFIG 开头的宏都是完成一些配置功能的。以后会频繁的和mx6ull_name_emmc.h 这个文件打交道。

7.5.2. 添加单板目录和文件

uboot 中每个板子都有一个对应的文件夹来存放板级文件,比如开发板上外设驱动文件等等。 NXP 的 I.MX 系列芯片的所有板级文件夹都存放在 board/freescale 目录下,在这个目录下有个名为 mx6ullfire的文件夹,这个文件夹就是我们IMX6LL的开发板的板级文件夹。复制 mx6ullfire,将其重命名为 mx6ull_name,命令如下:

1
2
  cd board/freescale/
  cp -rf mx6ullfire mx6ull_name

进入mx6ull_name目录中,将其中的mx6ullfire.c文件重命名为mx6ull_name.c,命令如下:

1
2
   cd mx6ull_name/
   mv mx6ullfire.c mx6ull_name.c

将mx6ull_name.c里面的mx6ullfire.h头文件修改为mx6ull_name.h

1
   #include <configs/mx6ull_name.h>

mx6ull_name单板目录文件结构如下:

1
2
3
4
5
6
7
      ./mx6ull_name
          ├── imximage.cfg
          ├── Kconfig
          ├── MAINTAINERS
          ├── Makefile
          ├── mx6ull_name.c
          └── plugin.S
  • mx6ull_name.c :里写了一些uboot启动代码和我们对板子引脚读取的代码

  • plugin.S :用汇编写的设置ddr和时钟,一般不需要更改

  • Makefile :里面修改C文件编译后的o文件,有多少个就写多少个o文件,注意与c文件名字相同

将Makefile里面的mx6ullfire.o修改为mx6ull_name.o

1
  obj-y  := mx6ull_name.o
  • Kconfig :(目录:board/路径/目标文件夹/Kconfig)

将Kconfig修改为以下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
   if TARGET_MX6ULL_FIRE  //上面所说的两处对应其中的一处

      config SYS_BOARD
              default "mx6ull_name" //目标文件夹

      config SYS_VENDOR
              default "freescale" //路径

      config SYS_CONFIG_NAME
              default "mx6ull_name" //头文件名称 注意:头文件在include/configs下名称为"头文件名称.h"

   endif
  • imximage.cfg :(目录:board/路径/目标文件夹)(NXP特有的文件,只需要修改一处即可,这是添加头部信息的)

将imximage.cfg文件里面的PLUGIN board/freescale/mx6ullfire/plugin.bin 0x00907000 修改为以下内容,更改单板目录:

1
   PLUGIN  board/freescale/mx6ull_name /plugin.bin 0x00907000

7.5.3. 配置文件

emmc版本为 mx6ull_fire_mmc_defconfig

nand版本为 mx6ull_fire_nand_defconfig

以下以emmc版本为例:

1
  cp configs/mx6ull_fire_mmc_defconfig configs/mx6ull_name_defconfig

这里有几个参数要注意一下

  • CONFIG_TARGET_MX6ULL_FIRE=y 这行参数与两处有相对应,下面会讲到,这里留意一下。

  • CONFIG_DEFAULT_DEVICE_TREE= 这行参数是设备树名称,要与uboot设备树对应,将其修改为如下配置:

1
  CONFIG_DEFAULT_DEVICE_TREE="imx6ull-name-mmc"

因为后续准备使用的设备树为imx6ull-name-mmc.dts。

  • CONFIG_SYS_EXTRA_OPTIONS= 这行参数是配置头部信息的,指向的是板子目录的cfg文件,将其修改为如下配置,改为我们单板目录。

1
  CONFIG_SYS_EXTRA_OPTIONS=="IMX_CONFIG=board/freescale/mx6ull_name/imximage.cfg"

7.5.4. 添加Kconfig信息

在这个文件中添加我们的板子信息方便Makefile识别编译

修改文件目录为:arch/arm/mach-imx/mx6/Kconfig

7.5.4.1. 修改U-Boot图形界面配置文件

在config TARGET_MX6ULL_14X14_EVK配置的下面添加如下代码

1
2
3
4
5
6
7
   config TARGET_MX6ULL_FIRE
      bool "Support mx6ull_name"
      depends on MX6ULL
      select BOARD_LATE_INIT
      select DM
      select DM_THERMAL
      imply CMD_DM

在source “board/freescale/mx6ullevk/Kconfig”下添加如下代码

1
   source "board/freescale/mx6ull_name/Kconfig"

7.5.5. 添加设备树

7.5.5.1. 添加设备树信息

修改文件目录为:arch/arm/dts/Makefile

在dtb-$(CONFIG_MX6ULL) += 下面添加(为什么在这添加,因为配置文件里设置了CONFIG_MX6ULL=y)

设备树的名字,参考config里的CONFIG_DEFAULT_DEVICE_TREE=”imx6ull-name-mmc”

添加内容:imx6ull-name-mmc.dtb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
  dtb-$(CONFIG_MX6ULL) += \
      imx6ull-14x14-evk.dtb \
      imx6ull-fire-mmc.dtb \
      imx6ull-fire-nand.dtb \
      imx6ull-name-mmc.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

7.5.5.2. 复制设备树源码

1
  cp arch/arm/dts/imx6ull-fire-mmc.dts arch/arm/dts/imx6ull-name-mmc.dts

7.5.6. 编译

1
2
3
4
  make distclean
  make mx6ull_name_mmc_defconfig
  #编译uboot
  make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

7.6. 烧录启动

未找到图片qd

启动后可以发现确实可以正常使用。

提供一份定制好的uboot源码供大家参考 ebf_linux_uboot.tar.gz