11. 野火定制镜像构建流程

11.1. 野火OpenWrt系统简介

野火在官方OpenWrt-19.07长期支持版本的源码基础上,添加对imx6ull处理器的支持,并基于EBF6ULL平台对相关的配置进行了修改,以支持野火定制镜像的构建。

由于官方OpenWrt源码配套的内核和设备树均为官方源码,对当前处理器支持不完善,也缺少了很多芯片厂商定制的功能。所以我们替换了内核和Uboot。

其中内核使用NXP提供的4.19.35版本的内核,Uboot使用了NXP提供的2020.10版本,并添加了野火EBF6ULL开发板。

由于OpenWrt系统主要是用于路由器等网络设备,我们对EBF6ULL开发板的支持也以网络相关的功能为主,我们只需要一块野火EBF6ULL Mini开发板即可完成功能验证。

11.2. 下载安装编译镜像系统(如果没有编译环境)

使用平台:Ubuntu 18.04 LTS 版本

可以使用我们提供的虚拟机镜像 https://doc.embedfire.com/products/link/zh/latest/linux/ebf_i.mx6ull.html#id4

也可以自己下载ubuntu 18.04 LTS官方镜像搭建 https://mirrors.aliyun.com/ubuntu-releases/bionic

虚拟机的搭建过程可以参考文档 在PC上安装Ubuntu系统

11.3. 安装编译工具和依赖

编译OpenWrt之前需要安装必要的环境工具。

1
2
3
sudo apt install -y subversion g++ zlib1g-dev build-essential git
sudo apt install -y libncurses5-dev gawk gettext unzip file libssl-dev
sudo apt install -y python rsync man-db wget zip time aria2

11.4. 获取源码

野火OpenWrt镜像构建源码主要分为三部分:

OpenWrt源码:http://gitlab.ebf.local/openwrt/gateway/gateway_openwrt_imx6ull.git

kernel源码:http://gitlab.ebf.local/openwrt/gateway/ebf_gateway_linux_kernel.git

Uboot源码:http://gitlab.ebf.local/openwrt/gateway/ebf_gateway_linux_uboot.git

我们需要新建一个单独的目录来存放源码,并分别拉取这三个Git仓库到本地。如果只是为了编译, 不想查看这个仓库完整的提交信息,可以在git clone后加 depth= 的参数以大幅减少从Git拉取的数据(等号后的数字表示最近多少次提交)。 如果要查看完整的提交信息,可以把depth参数去掉。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#在当前用户家目录创建工作目录
mkdir ~/ebf6ull-openwrt

#进入工作目录
cd ~/ebf6ull-openwrt

#拉取OpenWrt源码
git clone -b openwrt-19.07 --depth=1 git@gitlab.ebf.local:openwrt/gateway/gateway_openwrt_imx6ull.git

#拉取kernel源码
git clone -b ebf_4.19.35_imx6ul --depth=1 git@gitlab.ebf.local:openwrt/gateway/ebf_gateway_linux_kernel.git

#拉取uboot源码
git clone -b ebf_v2020_10_imx --depth=1 git@gitlab.ebf.local:openwrt/gateway/ebf_gateway_linux_uboot.git
拉取仓库

提示

图中的git地址为野火内部Git服务器地址,用户使用的为外部github或gitee地址,内外部仓库内容相同,以文档中地址为准。

11.5. 构建镜像

11.5.1. 构建Uboot

野火适配了EBF6ULL开发板的nand版本和emmc版本,这里以编译nand版本为例

若想编译emmc版本的Uboot需要将 mx6ull_fire_nand_defconfig 改为 mx6ull_fire_mmc_defconfig

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#进入Uboot所在的目录
cd ~/ebf6ull-openwrt/ebf_gateway_linux_uboot

#清除之前的编译环境
sudo make distclean

#选择配置文件
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi- mx6ull_fire_nand_defconfig

#编译Uboot
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi-
  • sudo make distclean 清除上次生成的编译环境,避免之前的环境干扰影响编译结果

  • sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi- mx6ull_fire_nand_defconfig 加载板级配置文件,具体的板级配置文件在Uboot根目录下的configs目录下

  • sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi- 设置编译架构为arm 编译工具链为arm-none-eabi- 然后开始编译

编译uboot 编译uboot

编译生成的u-boot-dtb.imx文件就是我们想要文件,手动将文件重命名为u-boot-nand-dtb.imx以防止和emmc版本的搞混。如果是emmc版本则重命名为u-boot-emmc-dtb.imx。

将u-boot-nand-dtb.imx保存在烧录工具的 mfgtools-release\Profiles\Linux\OS Firmware\release 文件夹内。如果是emmc版本路径也相同。

11.5.2. 构建kernel、设备树、OpenWrt根文件系统

我们借助OpenWrt SDK来编译我们的内核,在编译内核的同时也会编译设备树。

11.5.2.1. 使用准备工作

在编译OpenWrt源码前,我们还要进行一些准备工作,以满足编译的要求。我们可以借助 make_fire.sh 脚本来完成这项工作。

1
2
3
4
5
#进入Uboot所在的目录
cd ~/ebf6ull-openwrt/gateway_openwrt_imx6ull

#运行脚本
./make_fire.sh
编译openwrt

运行脚本以后,会提示输入数字选择要进行的项目,我们要进行编译前的准备工作,输入1然后按Enter键 。

然后选择要编译设备的配置文件,这里我们编译nand版本的固件,就输入5然后按Enter键。

接着脚本会自动完成软件包列表的升级、设置相应的OpenWrt配置文件、下载软件包源码,我们耐心等待这个过程完成。

如果我们还想自行添加一些软件包进去,我们可以在脚本运行完成以后,使用make menuconfig来修改配置文件。 如果想保存修改的配置文件,可运行 make_fire.sh 脚本,输入2选择保存配置文件,然后选择对应的设备。 配置文件被保存在 gateway_openwrt_imx6ull/config/ 目录中。

在正式编译之前,我们还需要将OpenWrt自带的内核替换为我们的内核。

先获取内核所在目录的绝对路径。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#进入内核所在目录
cd ~/ebf6ull-openwrt/ebf_gateway_linux_kernel

#使用pwd命令查看kernel所在的目录
pwd

#返回结果
/home/jiawen/ebf6ull-openwrt/ebf_gateway_linux_kernel

#返回OpenWrt目录
cd -
获取内核路径

使用make menuconfig命令进入OpenWrt配置界面,进入 Advanced configuration options , 然后在Use external kernel tree选项按Enter键,输入内核绝度路径,保存并退出。这样就完成了内核的替换。

替换内核路径 替换内核路径

警告

输入的路径根据自己的情况修改。

11.5.2.2. 编译OpenWrt

1
2
#开始编译
make V=s -jn

使用make命令进行源码的编译。参数V表示输出log的等级,V=s为输出所有的信息,等同于V=99,V=0为不输出,不使用V参数时默认为0。 -j表示同时进行指定数量的任务进行编译,也就是指定编译的线程数,n为线程数大小,不指定-jn参数时自动判断编译所需的线程数。

由于OpenWrt部分软件包不支持多线程编译,当我们指定n大于1时,会有极大的可能导致编译失败, 所以推荐大家使用 make V=s命令来减少不必要的麻烦。

由于我们在实际的开发过程中使用服务器进行编译,服务器具有核心多但单核频率低的特点, 如果仅使用单线程编译,效率甚至不如普通PC。所以,我们往往会先进行多线程编译, 直到工程编译失败,再使用单线程编译,具体过程如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#首先进行多线程编译
make V=s -j56

#遇到编译错误,尝试单线程编译
make V=s -j1

#如果单线程编译不通过,检查详细报错信息并解决错误

#单线程编译报错软件包通过之后,Ctrl+C打断编译,继续使用多线程编译
make V=s -j56

#重复上述过程,直到编译完成

注解

以上开发编译流程可以有效提高开发效率,减少编译源码占用的时间。

编译完成

经过一段时间的编译(具体时间与编译服务器性能相关),我们就得到了编译好的kernel、设备树、OpenWrt根文件系统。

编译产生的最终文件,分别存放在以下位置:

  • kernel:build_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/linux-imx6_cortexa7/zImage

  • 设备树:bin/targets/imx6/cortexa7/openwrt-imx6-cortexa7-imx6ull-nand-npi.dtb

  • OpenWrt-rootfs:bin/targets/imx6/cortexa7/openwrt-imx6-cortexa7-device-embedfire-nand-rootfs.tar.gz

我们将上述三个文件保存到烧录工具的 mfgtools-release\Profiles\Linux\OS Firmware\release 文件夹内,即可进行烧录。

烧录过程详见 烧写系统 章节。