# 1. 编译系统介绍
嵌入式Linux系统BSP(Board Support Package)的整个编译过程非常繁琐且漫长,而我们在BSP开发过程中却经常需要编译这些源码,如果每次都是逐条命令输入执行,这个过程非常麻烦且容易出错。为此,凌云实验室郭工为 IMX 系列开发板编写了一套编译脚本,这样方便各个开发板的一键编译。当前该编译系统支持的开发板有:
* 凌云实验室 IGKBoard-IMX6ULL 开发板
* 凌云实验室 IGKBoard-IMX8MP 开发板
* 凌云实验室 GauGuin-imx8mp 开发板
* 正点原子 IMX6ULL 开发板
## 1.1 编译系统下载
凌云实验室 IMX 系列开发板一键编译脚本托管在 [凌云实验室的 git 服务器上](http://main.iot-yun.club:8088/summary/build-imxboard.git), 我们可以从该站点上下载最新的编译系统。这里以 IGKBoard-IMX6ULL 开发板为例,使用 git 命令下载该项目源码并重命名为 igkboard-imx6ull(也可以命名为其它开发板的名字)。
```bash
guowenxue@9d57f9229b66:~$ git clone http://iotcraft.cn:8088/r/build-imxboard.git ~/igkboard-imx6ull
guowenxue@9d57f9229b66:~$ cd ~/igkboard-imx6ull/
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ ls
bootloader config.json debian drivers images kernel tools yocto
```
下面是编译系统各文件的简单介绍。
| 文件/文件夹 | 描述 |
| --------------- | ------------------------------------------ |
| **config.json** | 编译系统的JSON格式配置文件 |
| **tools** | 编译系统所依赖系统命令和交叉编译器安装脚本 |
| **bootloader** | Bootloader的编译脚本及补丁文件 |
| **kernel** | Linux内核的编译脚本及补丁文件 |
| **drivers** | 驱动学习示例源码及测试程序 |
| **images** | Linux系统烧录镜像一键制作脚本 |
| **debian** | Debian根文件系统一键制作的脚本 |
| **yocto** | Yocto系统源码编译脚本 |
## 1.2 编译系统配置
下面是顶层编译系统的配置文件,默认为 ***IGKBoard-IMX6ULL*** 开发板的配置。
```json
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ cat config.json
{
"bsp":
{
"board":"igkboard-imx6ull",
"version":"lf-6.1.36-2.1.0",
"giturl":"https://github.com/nxp-imx/",
"cortexAtool":"/opt/gcc-aarch32-10.3-2021.07/bin/arm-none-linux-gnueabihf-",
"cortexMtool":"/opt/gcc-cortexM-10.3-2021.07/bin/arm-none-eabi-"
},
"system":
{
"distro":"yocto",
"version":"mickledore",
"imgsize":"3072",
"bootsize":"100"
}
}
```
下面是该配置文件中各选项的配置说明:
* ***bsp.board*** 该选项指定要编译的目标开发板,具体支持哪些可以查看 `kernel/patches/` 文件夹下有哪些开发板文件夹.
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ ls kernel/patches/
alientek-imx6ull-v20 alientek-imx6ull-v24 gauguin-imx8mp gen_patch.sh igkboard-imx6ull igkboard-imx8mp
```
> 如上面支持的开发板 ***igkboard-imx6ull、 igkboard-imx8mp、alientek-imx6ull-v20*** 等
* ***bsp.version*** 该选项指定要编译的Linux BSP版本,具体支持哪些可以查看 `kernel/patches/` 相应开发板下支持哪些补丁.
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ ls kernel/patches/igkboard-imx6ull/
linux-imx-lf-6.1.36-2.1.0.patch
```
> 如上面支持的 BSP 版本为 ***lf-6.1.36-2.1.0***
* ***bsp.giturl*** 该选项指定Linux BSP源码的下载地址,默认从NXP 官方的 github 仓库下载;
* ***bsp.cortexAtool*** 该选项用来指定 Cortex-A核 + Linux系统的交叉编译器;
* ***bsp.cortexMtool*** 该选项用来指定 Cortex-M核 + FreeRTOS系统的交叉编译器;
* ***system.distro*** 该选项指定要发型的Linux系统类型,当前支持 ***Yocto*** 和 ***Debian*** 系统;
* ***system.version*** 该选项指定要发型的Linux系统类型相应版本;
* ***system.imgsize*** 该选项指定要生成的Linux系统镜像的大小,通常需要根据根文件系统的大小来调整;
* ***system.bootsize*** 该选项指定要生成的Linux系统镜像Boot分区(FAT文件系统)的大小;
# 2. Linux系统编译
一个完整的 Linux 系统镜像制作,需要经过以下几个步骤:
1. Bootloader 源码编译;
2. Linux内核 源码编译;
3. 根文件系统制作;
4. Linux系统烧录镜像制作;
接下来,我们以 ***IGKBoard-IMX6ULL*** 为例,使用该编译系统从源码来编译制作一个可以烧录到 eMMC 或 TF 卡启动的系统镜像。
## 2.1 编译系统配置
在开始编译之前,我们首先确定当前编译系统支持哪些BSP版本,这点可以通过查看相应开发板的补丁文件来获取。如下所示,当前 IGKBoard-IMX6ULL 只支持 lf-6.1.36-2.1.0 这个版本。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ ls kernel/patches/igkboard-imx6ull/
linux-imx-lf-6.1.36-2.1.0.patch
```
接下来我们需要修改顶层的配置文件 ***config.json*** 如下:
```json
{
"bsp":
{
"board":"igkboard-imx6ull",
"version":"lf-6.1.36-2.1.0",
"giturl":"https://github.com/nxp-imx/",
"cortexAtool":"/opt/gcc-aarch32-10.3-2021.07/bin/arm-none-linux-gnueabihf-",
},
"system":
{
"distro":"yocto",
"version":"mickledore",
"imgsize":"3072",
"bootsize":"100"
}
}
```
* 修改目标开发板 **board** 为 ***igkboard-imx6ull*** ;
* 修改交叉编译器 **cortexAtool** 为后面安装的交叉编译器;
* 如果想编译其它版本BSP,可以修改 **version** 为支持的目标 BSP 版本;
* 如果想编译 Yocto 系统,可以修改 **distro** 为 ***yocto***,其 **version** 也要改成当前支持的 ***kirkstone***、***mickledore***;
* 如果想编译 Debian 系统,可以修改 **distro** 为 ***debian***,其 **version** 也要改成当前支持的 ***bullseye***、***bookworm***;
在下面的所有源码编译过程中,需要从github的NXP官方站点上下载大量的源码,但由于众所周知的原因,国内经常不能正常访问 github 。如果您的Linux编译服务器不能正常访问 github,请先设置好代理服务然后再开始执行后续的 ***build.sh*** 脚本开始编译,否则编译时会下载源码失败。***如果是凌云实验室的学员,可以将 giturl 设置为实验室的文件服务器地址,这样避免从 github 下载源码。***
```json
"bsp":
{
- "giturl":"https://github.com/nxp-imx/",
+ "giturl":"http://studio.xxx.club:2211",
},
```
> ***WARNNING: 上面的 `"http://studio.xxx.club:2211"` 请改成实验室文件服务器的正确域名。***
下面是我配置的代理命令 **proxy** 用来代理访问 github,设置好后可以使用 **curl** 命令访问 google.com 来测试代理是否生效。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ proxy
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ curl google.com
301 Moved
301 Moved
The document has moved
here.
```
另外,也可以使用 **unproxy** 命令来取消命令行代理。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ unproxy
```
如果是基于 i.MX8 处理器的开发板,则可以参考修改交叉编译器如下。
```json
{
"bsp":
{
"board":"igkboard-imx8mp",
"version":"lf-6.1.36-2.1.0",
"giturl":"https://github.com/nxp-imx/",
"cortexAtool":"/opt/gcc-aarch64-10.3-2021.07/bin/aarch64-none-linux-gnu-",
"cortexMtool":"/opt/gcc-cortexM-10.3-2021.07/bin/arm-none-eabi-"
},
"system":
{
"distro":"yocto",
"version":"mickledore",
"imgsize":"3072",
"bootsize":"100"
}
}
```
## 2.2 编译系统安装
在嵌入式BSP系统开发过程中,依赖很多的Linux系统命令及交叉编译器。在该编译系统的 ***tools*** 文件夹下,有一个 ***setup_tools.sh*** 脚本可以用来一键安装它们。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ ls tools/
imgmnt setup_tools.sh
```
接下来以 root 权限执行 ***tools/setup_tools.sh*** 脚本,来安装BSP源码编译所依赖的系统工具和交叉编译器,如果之前已经安装过则会自动跳过。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ cd tools/
guowenxue@9d57f9229b66:~/igkboard-imx6ull/tools$ sudo ./setup_tools.sh
All system tools already installed, skip it
All development tools already installed, skip it
start download cross compiler from ARM Developer for Cortex-A core
... ...
start decompress cross compiler for Cortex-A core
... ...
cross compiler for Cortex-A installed to "/opt/gcc-aarch32-10.3-2021.07" successfully
```
至此,整个编译系统的配置和开发环境搭建已经完成。
## 2.3 Bootloader编译
在做好前面的配置后,编译 bootloader 的工作就非常简单了,我们只需要切换到 ***bootloader*** 文件夹下,执行 `build.sh` 脚本即可。它将会自动从配置的源码服务器上下载源码,并打上相应的补丁文件,开始漫长的编译工作。
``` bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ cd bootloader/
guowenxue@9d57f9229b66:~/igkboard-imx6ull/bootloader$ ls
build.sh patches
guowenxue@9d57f9229b66:~/igkboard-imx6ull/bootloader$ ./build.sh
start build bootloader for igkboard-imx6ull
start fetch uboot-imx source code
... ...
do patch for uboot-imx now...
... ...
start build uboot-imx
... ...
MKIMAGE u-boot-dtb.imx
OFCHK .config
+ cp u-boot-igkboard-imx6ull.imx /home/guowenxue/igkboard-imx6ull/bootloader/install
+ set +x
bootloader installed to '/home/guowenxue/igkboard-imx6ull/bootloader/install'
u-boot-igkboard-imx6ull.imx
```
编译完成后,生成的 bootloader 文件将会存放到自动创建的 ***install*** 文件夹下。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull/bootloader$ ls install/
u-boot-igkboard-imx6ull.imx
```
如果对 bootloader 源码有新的修改,我们可以使用 `./patches/gen_patch.sh` 脚本生成新的 patch 补丁文件。如果想保存该补丁文件,则可以替换 ***patches*** 文件夹下的相应文件。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull/bootloader$ ./patches/gen_patch.sh uboot-imx/
generate patch file
guowenxue@9d57f9229b66:~/igkboard-imx6ull/bootloader$ ls
build.sh install patches tarballs uboot-imx uboot-imx-lf-6.1.36-2.1.0.patch
guowenxue@9d57f9229b66:~/igkboard-imx6ull/bootloader$ mv uboot-imx-lf-6.1.36-2.1.0.patch patches/igkboard-imx6ull/
```
另外使用 `build.sh -c` 命令可以一键清除所有编译产生的文件和源码。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull/bootloader$ ./build.sh -c
start clean bootloader
guowenxue@9d57f9229b66:~/igkboard-imx6ull/bootloader$ ls
build.sh patches
```
## 2.4 Linux内核编译
同样地,编译 Linux内核源码的工作也非常简单,我们只需要切换到 ***kernel*** 文件夹下,执行 `build.sh` 脚本即可。它将会自动从配置的源码服务器上下载源码,并打上相应的补丁文件,开始漫长的编译工作。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ cd kernel/
guowenxue@9d57f9229b66:~/igkboard-imx6ull/kernel$ ls
build.sh patches
guowenxue@9d57f9229b66:~/igkboard-imx6ull/kernel$ ./build.sh
start build linux kernel for igkboard-imx6ull
start fetch linux kernel source code
... ...
do patch for linux-imx now...
... ...
start build linux-imx
... ...
linux kernel installed to '/home/guowenxue/igkboard-imx6ull/kernel/install'
igkboard-imx6ull.dtb lib overlays zImage
```
同样地,编译完成后生成的 linux内核文件将会存放到自动创建的 ***install*** 文件夹下。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull/kernel$ ls install/
igkboard-imx6ull.dtb lib overlays zImage
```
如果对 Linux内核源码有新的修改,我们可以使用 `./patches/gen_patch.sh` 脚本生成新的 patch 补丁文件。如果想保存该补丁文件,则可以替换 ***patches*** 文件夹下的相应文件。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull/kernel$ ./patches/gen_patch.sh linux-imx/
generate patch file
guowenxue@9d57f9229b66:~/igkboard-imx6ull/kernel$ ls
build.sh install linux-imx linux-imx-lf-6.1.36-2.1.0.patch patches tarballs
guowenxue@9d57f9229b66:~/igkboard-imx6ull/kernel$ mv linux-imx-lf-6.1.36-2.1.0.patch patches/igkboard-imx6ull/
```
另外使用 `build.sh -c` 命令可以一键清除所有编译产生的文件和源码。
```
guowenxue@9d57f9229b66:~/igkboard-imx6ull/kernel$ ./build.sh -c
start clean linux kernel
guowenxue@9d57f9229b66:~/igkboard-imx6ull/kernel$ ls
build.sh patches
```
## 2.5 系统镜像制作
系统镜像的制作依赖 Bootloader、Linux内核 和 根文件系统系统,前面的过程我们已经从源码编译了 Bootloader 和 Linux内核镜像文件,而根文件系统则需要从凌云实验室的文件服务器上下载。实验室的学员只需要在前面的配置中,将 **githurl** 配置成实验室的文件服务器即可。
因为 Linux 系统镜像需要使用 **sudo** 和 **loop** 设备,所以这个需要在自己的虚拟机或实验室的编译服务器具有相应权限的账号下工作。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ cd images/
guowenxue@9d57f9229b66:~/igkboard-imx6ull/images$ ls
build.sh
guowenxue@9d57f9229b66:~/igkboard-imx6ull/images$ sudo ./build.sh
Build system image yocto-mickledore-lf-6.1.36-2.1.0.img
INFO: download rootfs-yocto-mickledore.tar.zst form http://studio.xxx.com:2211
... ...
start generate empty system image
... ...
start partition system image
losetup system image on loop4
... ...
start format system image
... ...
start install u-boot image
... ...
start install linux kernel images
update drivers in root filesystem
start install root filesystem
Build system image yocto-mickledore-lf-6.1.36-2.1.0.img done
Start bzip2 compress yocto-mickledore-lf-6.1.36-2.1.0.img
... ...
Shell script exit now, do some clean work
kpartx -dv /dev/loop4
del devmap : loop4p1
del devmap : loop4p2
losetup -d /dev/loop4
```
编译完成后,系统镜像和烧录所需要的文件将会存放到自动创建的 ***install*** 文件夹下。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull/images$ ls install/
u-boot-igkboard-imx6ull.imx yocto-mickledore-lf-6.1.36-2.1.0.img.bz2
```
接下来将上面两个文件下载到自己的 Windows 系统下,参考前面的文档就可以烧录启动了。
# 3. Yocto 系统源码编译
Yocto 系统的编译比较复杂,对软件的要求比较高。其至少要求:
* 至少8核+以上处理器和16GB+内存;
* 至少250GB以上硬盘空间,推荐SSD固态硬盘;
* 要求编译服务器能够翻墙正常访问 github ;
如果您的编译服务器满足上述软硬件要求,则可以尝试 Yocto 的源码编译。在该编译系统中,这个过程也非常简单,只需要执行 ***yocto*** 文件夹下的 `build.sh` 脚本即可。一次完整的编译在凌云实验室编译服务器上大概需要7~8个小时,该服务器的配置为:
* CPU: 48核Xeon(R) CPU E5-2678 v3 @ 2.50GHz 处理器
* 内存:128GB
* 硬盘: 1TB SDD
下面是 Yocto 源码编译的过程。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull$ cd yocto/
guowenxue@9d57f9229b66:~/igkboard-imx6ull/yocto$ ls
build.sh meta-igkboard
guowenxue@9d57f9229b66:~/igkboard-imx6ull/yocto$ ./build.sh
start build Yocto mickledore for igkboard-imx6ull
start download fetch Yocto mickledore source code
... ...
Build directory is igkboard-imx6ull
/home/guowenxue/igkboard-imx6ull/yocto/mickledore-lf-6.1.36-2.1.0
Welcome LingYun IoT Gateway Kit Board Yocto BSP
The Yocto Project has extensive documentation about OE including a
reference manual which can be found at:
http://yoctoproject.org/documentation
You can now run 'bitbake '
Common targets are:
yocto-image-full
core-image-minimal
imx-image-full
... ...
Yocto(mickledore) installed to '/home/guowenxue/igkboard-imx6ull/yocto/install'
Start bzip2 compress yocto-mickledore-lf-6.1.36-2.1.0.wic
rootfs-yocto-mickledore.tar.zst u-boot-igkboard-imx6ull.imx yocto-mickledore-lf-6.1.36-2.1.0.wic.bz2
```
编译完成后,系统镜像和烧录所需要的文件将会存放到自动创建的 ***install*** 文件夹下。
```bash
guowenxue@9d57f9229b66:~/igkboard-imx6ull/yocto$ ls install/
rootfs-yocto-mickledore.tar.zst u-boot-igkboard-imx6ull.imx yocto-mickledore-lf-6.1.36-2.1.0.wic.bz2
```
接下来将上面两个文件下载到自己的 Windows 系统下,参考前面的文档就可以烧录启动了。