构建一个适合stm32mp157系列开发板的嵌入式Linux系统

在线课堂:https://www.100ask.net/index(课程观看)
论  坛:http://bbs.100ask.net/(学术答疑)
开 发 板:https://100ask.taobao.com/ (淘宝)
     https://weidongshan.tmall.com/(天猫)
交流群一:QQ群:869222007(鸿蒙开发/Linux/嵌入式/驱动/资料下载)
交流群二:QQ群:536785813(单片机-嵌入式)
公 众 号:百问科技


版本日期作者说明
V12020韦东山技术文档

6.1 前言

Linux平台上有许多开源的嵌入式linux系统构建框架(框架的意思就是工具),这些框架极大的方便了开发者进行嵌入式系统的定制化构建,目前比较常见的有OpenWrt, Buildroot, Yocto,等等。其中Buildroot功能强大,使用简单,而且采用了类似于linux kernel的配置和编译框架,所以受到广大嵌入式开发人员的欢迎。

本章重点介绍使用Buildroot_2020.02LTS版构建文件系统和u-boot, kernel镜像的方法,并从这三个部分入手,描述如何使用Buildroot构建一个适合100ask_stm32mp157系列开发板的嵌入式Linux系统。

在构建文件系统时,还简要介绍了如何通过Buildroot将QT5图形系统集成到文件系统中, 方便用户后续开发QT5的应用程序。

无论你是使用VMware还是docker运行Ubuntu,都需要先在Ubuntu中安装很多软件,比如ssh服务、nfs服务。确保Ubuntu能ping通外网(比如:ping news.qq.com)后,按以下章节配置Ubuntu:

《第 2 篇 环境搭建、Linux 基本操作、工具使用》
《第四章 使用 NAT 配置 Ubuntu 网络》
《第五章 安装软件及开发示例》

全文下载:嵌入式Linux系统开发完全手册 第二版

注意:我们制作出厂系统时,既用到了 Yocto 也用到了 Buildroot。
初学者先不要自己制作文件系统,因为:

① Yocto 超级难用

单是下载程序容量就达到 10G,使用一般的个人电脑需要编译 20 小时以上。以后稍微修改一下程序,重新制作时至少需要半小时。

我们迫不得已才使用 Yocto:QT GUI 程序需要用到 GPU 的一些库,在 Buildroot 上我们还没搞定。

② 我们提供完整适配的 Buildroot

Buildroot 简单、强大,并且可以根据自己需求来选择是否安装你需要的包,文件系统镜像大小可以随意定制,建议大家使用 buildroot 来构建文件系统,后期我们也主要以 buildroot 系统作为主要支持。

先不要自己制作文件系统,我们正在录制第1个项目,在它之后将会录制“定制系统”,到时会详细讲解怎么构建根文件系统。

作为初学者,可以跳过本章,先按照以下章节学习,它介绍了怎么下载源码、建立source insight工程、编译内核、编译模块,并且有对应的视频:

《第 2 篇 环境搭建、Linux 基本操作、工具使用》
《第七章 编程前的准备工作》
《第九章 开发板的第 1 个驱动程序》
全文下载:嵌入式Linux系统开发完全手册 第二版

微信公众号:百问科技(关注回复“资料”免费领取海量学习资料)

6.2 获取源码

源码的获取方法有2种:本地拷贝、在线下载。这2种方法请选择1种,不要同时选择2种方法。强烈建议使用在线下载,这种方式得到的源码肯定是最新的。

6.2.1 本地拷贝

暂不提供本地拷贝,太费事,没有在线下载方便。

6.2.2 在线下载

100ask_stm32mp157_pro开发板的所有代码都是保存在git站点上通过repo命令进行统一管理,可以通过如下命令进行下载或同步。

6.2.2.1 配置 repo

下载repo工具前需要设置git的邮箱和用户名,git邮箱和用户名请根据个人情况进行配置。

book@100ask:~$ git config --global user.email "user@100ask.com"
book@100ask:~$ git config --global user.name "100ask"

注意: 请先配置git邮箱和用户名,否则会导致下载失败(如下为参考示例图)。
在这里插入图片描述

6.2.2.2 下载源码

通过repo管理多个git仓库中的源码,可以及时更新最新代码,以方便开发者学习使用。

对于不同版本的STM32MP157开发板,要执行不同的命令下载源码。

1)STM32MP157全功能版
执行以下4条命令,为方便大家复制,第3条是很长的命令,使用了\来换行,需要一并拷贝:

book@100ask:~$ git clone https://e.coding.net/codebug8/repo.git
book@100ask:~$ mkdir -p 100ask_stm32mp157_pro-sdk && cd 100ask_stm32mp157_pro-sdk
book@100ask:~/100ask_stm32mp157_pro-sdk$ ../repo/repo init -u \
https://gitee.com/weidongshan/manifests.git -b linux-sdk \ -m stm32mp1/100ask_stm32mp157_pro_release-v2.0.xml --no-repo-verify
book@100ask:~/100ask_stm32mp157_pro-sdk$ ../repo/repo sync -j4

在这里插入图片描述
首次下载如果提示 Testing colorized output (for ‘repo diff’, ‘repo status’): 此时输入 y 即可,继续执行 …/repo/repo sync -j4 命令即可开始同步源码(同步代码根据网络情况需要等待数分钟)。

注 意 : 我 们 会 每 隔 一 段 时 间 更 新 一 次 源 码 包 , 如 使 用 在 线 方 式 获 取 源 码 可 以 直 接 在~/100ask_stm32mp157_pro-sdk 目录下执行 …/repo/repo sync -c进行同步更新最新代码。

注意:下载成功后,可以看到名为Linux-5.4的目录,可以在Ubuntu压缩它,再传回Windows。

在Windows下解压后,用source insight建立工程,这样就可以很方便地阅读源码了。

注意:使用source insight阅读Linux源码的方法,请参考《7.4 使用Source Insight阅读Linux内核源码》。

Ubuntu下压缩命令为(最好是下载之后马上压缩,不要编译内核后再压缩,否则文件太大了):

book@100ask:~$ tar cjf Linux-5.4.tar.bz2 Linux-5.4

在这里插入图片描述
首次下载如果提示 Testing colorized output (for ‘repo diff’, ‘repo status’): 此时输入 y 即可,继续执行 …/repo/repo sync -j4 命令即可开始同步源码(同步代码根据网络情况需要等待数分钟)。

下图为参考示例。
在这里插入图片描述
同步完成后如下图所示
在这里插入图片描述
注意:repo在线下载的代码和网盘配套资料中的代码是一致的,我们会每隔一段时间更新一次源码包,如使用在线方式获取源码 可以直接~/100ask_stm32mp157_pro-sdk目录下执行 …/repo/repo sync -c进行同步更新最新代码!

6.3 配置交叉编译工具链

注意:使用我们提供的Ubuntu映象文件时,请按照我们的目录结构,手动设置交叉编译工具链以及编译的架构环境变量配置,(建议配置为永久生效),这里我们提供了两种交叉编译工具链,分别是buildroot构建生成的8.4以及yocto生成的9.3工具链,开发板系统默认安装的系统使用的是通过yocto编译构建,所以如果只想针对于文件系统应用做开发或者编译内核uboot等操作,建议只使用yocto的交叉编译工具链。
在这里插入图片描述

6.3.1 设置 yocto 交叉编译工具链(不推荐)

交叉编译工具链用来在Ubuntu主机上编译应用程序,而这些应用程序是在ARM等其他平台上运行。

设置交叉编译工具主要是设置PATH, ARCH和CROSS_COMPILE三个环境变量,下面介绍具体设置方法。

在本文档中,源码、交叉编译工具链都是存放于/home/book目录下;如果你的目录不一样,请自行修改本节所讲述的命令。

设置这3个环境变量有多种方法,任意选择其中一种方法即可。录制视频时我会使用多种开发板,所以在视频里我总是使用“临时生效”的方法。

6.3.1.1 临时生效

也可以手工执行“export”命令设置环境变量,该设置只对当前终端有效(另开一个终端需要再次设置)。

  1. 100ASK_STM32MP157_PRO全功能版
    示例如下,第1条命令很长,这里使用 \ 用来换行,复制的时候需要一并复制,注意 \ 前面没有空格:
book@100ask:~$ source /home/book/100ask_stm32mp157_pro-sdk/ToolChain/\
openstlinux_eglfs-linux-gnueabi/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
book@100ask:~$ export ARCH=arm
book@100ask:~$ export CROSS_COMPILE=arm-ostl-linux-gnueabi-

在这里插入图片描述

6.3.1.2 手动指定

先设置PATH环境变量,然后在make编译时指定ARCH架构 CROSS_COMPILE交叉编译工具链(执行make命令时指定的参数,只对当前命令有效;下次执行make时仍需要再次指定那些参数)。

  1. 100ASK_STM32MP157_PRO全功能版
    示例如下,第1条命令很长,这里使用 \ 用来换行,复制的时候需要一并复制,注意 \ 前面没有空格:
book@100ask:~$ source /home/book/100ask_stm32mp157_pro-sdk/ToolChain/\
openstlinux_eglfs-linux-gnueabi/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
book@100ask:~$ make ARCH=arm CROSS_COMPILE=arm-ostl-linux-gnueabi-

在这里插入图片描述

6.3.2 测试交叉编译工具链

6.3.2.1 测试环境变量:

book@100ask:~$ echo $ARCH
arm
book@100ask:~$ echo $CROSS_COMPILE
arm-ostl-linux-gnueabi-

6.3.2.2 测试交叉编译器:

执行以下命令,结果见后图:

book@100ask:~$ arm-ostl-linux-gnueabi-gcc –v

在这里插入图片描述

6.3.3 设置 buildroot 交叉编译工具链(默认使用)

交叉编译工具链用来在Ubuntu主机上编译应用程序,而这些应用程序是在ARM等其他平台上运行。

设置交叉编译工具主要是设置PATH, ARCH和CROSS_COMPILE三个环境变量,下面介绍具体设置方法。

在本文档中,源码、交叉编译工具链都是存放于/home/book目录下;如果你的目录不一样,请自行修改本节所讲述的命令。

设置这3个环境变量有多种方法,任意选择其中一种方法即可,建议使用“永久生效”的方法。录制视频时我会使用多种开发板,所以在视频里我总是使用“临时生效”的方法。

6.3.3.1 永久生效

如需永久修改,请修改用户配置文件。
注意:如果不会使用vim命令,可以使用图形化的编辑工具,执行:gedit ~/.bashrc

book@100ask:~$ vim ~/.bashrc

1)100ASK_STM32MP157_PRO全功能版
在行尾添加或修改,加上下面几行(第3行很长,这里使用小字体方便大家复制):

book@100ask:~$ export ARCH=arm
book@100ask:~$ export CROSS_COMPILE=arm-buildroot-linux-gnueabihf
book@100ask:~$ export PATH=$PATH:/home/book/100ask_stm32mp157_pro-sdk/ToolChain/\
arm-buildroot-linux-gnueabihf_sdk-buildroot/bin

设置完毕后,要执行 source ~/.bashrc 命令使其生效,这条命令是加载这些设置的环境变量。

6.3.3.2 临时生效

也可以手工执行“export”命令设置环境变量,该设置只对当前终端有效(另开一个终端需要再次设置)。

  1. 100ASK_STM32MP157_PRO全功能版
    执行以下3个命令,第3个命令很长,这里使用 \ 用来换行,复制的时候需要一并复制,注意 \ 前面没有空格:
book@100ask:~$ export ARCH=arm
book@100ask:~$ export CROSS_COMPILE=arm-buildroot-linux-gnueabihf
book@100ask:~$ export PATH=$PATH:/home/book/100ask_stm32mp157_pro-sdk/ToolChain/\
arm-buildroot-linux-gnueabihf_sdk-buildroot/bin

6.3.3.3 手动指定

先设置PATH环境变量,然后在make编译时指定ARCH架构 CROSS_COMPILE交叉编译工具链(执行make命令时指定的参数,只对当前命令有效;下次执行make时仍需要再次指定那些参数)。

1) 100ASK_STM32MP157_PRO全功能版
示例如下,第1条命令很长,这里使用 \ 用来换行,复制的时候需要一并复制,注意 \ 前面没有空格:

book@100ask:~$ export PATH=$PATH:/home/book/100ask_stm32mp157_pro-sdk/ToolChain/\
arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
book@100ask:~$ make ARCH=arm CROSS_COMPILE=arm-buildroot-linux-gnueabihf-

6.3.4 测试交叉编译工具链

6.3.4.1 测试环境变量:

book@100ask:~$ echo $ARCH
arm
book@100ask:~$ echo $CROSS_COMPILE
arm-buildroot-linux-gnueabihf-

6.3.4.2 测试交叉编译器:

执行以下命令,结果见后图:

book@100ask:~$ arm-buildroot-linux-gnueabihf-gcc –v

在这里插入图片描述

6.4 解压编译 Tfa

6.4.1 Tfa 介绍

Trusted Firmware-A(TF-A)是用于 Arm A-Profile 体系结构(Armv8-A 和 Armv7-A)的安全世界软件的参考实现,其中包括 Exception Level 3(EL3)安全监视器。它为在 AArch32 或 AArch64 执行状态下的安全世界启动和运行时固件产品化提供了一个合适的起点。

TF-A 实施 Arm 接口标准,包括:

  • 电源状态协调接口(PSCI)
  • 受信任的板引导要求客户端(TBBR-CLIENT)
  • SMC呼叫约定
  • 系统控制和管理界面(SCMI)
  • 软件委托异常接口(SDEI)

TF-a官方代码仓库地址: https://github.com/ARM-software/arm-trusted-firmware

TF-a官方参考文档资料: https://trustedfirmware-a.readthedocs.io/en/latest/

Arm官方参考资料:
https://developer.arm.com/tools-and-software/open-source-software/firmware/trusted-firmware

100ask_stm32mp157开发板TFA源码:https://gitee.com/weidongshan/stm32mp15xc-tf-a.git

6.4.2 Tfa 编译

于STM32MP157全功能版,Tfa的编译过程如下(编译Tfa前必须先配置好工具链等开发环境,这里我们使用的交叉编译工具链为Buildroot GCC 8.4版本)。设置交叉编译,并执行编译命令。

book@100ask:~$ export ARCH=arm
book@100ask:~$ export CROSS_COMPILE=arm-buildroot-linux-gnueabihf
book@100ask:~$ export PATH=$PATH:/home/book/100ask_stm32mp157_pro-sdk/ToolChain/\
arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
book@100ask:~/100ask_stm32mp157_pro-sdk/Tfa-v2.2$ make -f $PWD/./Makefile.sdk all

编译完成后生成的文件在…/build/trusted/ 目录下,如下图所示。
在这里插入图片描述
编译完成之后生成tf-a-stm32mp157c-100ask-512d-v1.stm32,可以用于TF卡启动和EMMC启动,可以将此文件拷贝至资料光盘 02_Images\Flashlayout 目录下,以备后续更新操作使用。

6.4.3 更新 Tfa

6.5.3.1.烧写工具更新 trust 版本 uboot 镜像

  • 使用STM32CubeProgrammer烧写工具更新

请参考章节《7.3.1 单独更新tfa方法》。

6.5.3.1.开发板系统上更新 trust 版本 uboot 镜像

  • Emmc 文件系统内更新 uboot 镜像。

通过nfs网络挂载或者ssh等方式吧把上述编译好的tf-a-stm32mp157c-100ask-512d-v1.stm32 镜像文件拷贝到开发板文件系统任意目录,之后执行如下命令来更新tf-a-stm32mp157c-100ask-512d-v1.stm32。

root@100ask:~$ echo 0 > /sys/class/block/mmcblk2boot0/force_ro
root@100ask:~$ echo 0 > /sys/class/block/mmcblk2boot1/force_ro
root@100ask:~$ dd if=tf-a-stm32mp157c-100ask-512d-v1.stm32 of=/dev/mmcblk2/boot0 conv=fsync > 
/dev/null 2>&1
root@100ask:~$ dd if=tf-a-stm32mp157c-100ask-512d-v1.stm32 of=/dev/mmcblk2/boot1 conv=fsync > 
/dev/null 2>&1
root@100ask:~$ echo 1 > /sys/class/block/mmcblk2boot0/force_ro
root@100ask:~$ echo 1 > /sys/class/block/mmcblk2boot1/force_ro

6.5 解压编译 bootloader

6.5.1 Bootloader 介绍

Bootloader是在操作系统运行之前运行的一段代码,用于引导操作系统。通常每个操作系统都有一组专属的引导加载程序。引导加载程序通常可以通过多种方式引导操作系统内核,还有各种命令用于调试或修改内核运行环境。

U-Boot是一个开源的主引导加载程序,用于引导设备的操作系统内核,并含有多种命令以便调试系统。它适用于多种计算机体系结构,包括68k,ARM,Blackfin,MicroBlaze,MIPS,Nios,SuperH,PPC,RISC- V和x86。

U-boot官网 https://www.denx.de/wiki/U-Boot

ST源码下载页面 https://github.com/STMicroelectronics/u-boot.git

100ask_stm32mp157开发板Git仓库地址 https://gitee.com/weidongshan/stm32mp15xc-uboot.git

uboot更多使用讲解请参考页面 http://wiki.100ask.org/Category:Uboot

注意:我们使用的版本针对板子进行过修改,u-boot官网下载的源码不能直接使用。

6.5.2 编译 u-boot 镜像

不同的开发板对应不同的配置文件,配置文件位于 u-boot源码的configs/ 目录。编译uboot前必须先配置好工具链等开发环境,这里我们使用的交叉编译工具链为Buildroot GCC 8.4版本。

设置交叉编译,并执行编译命令。

book@100ask:~$ export ARCH=arm
book@100ask:~$ export CROSS_COMPILE=arm-buildroot-linux-gnueabihf
book@100ask:~$ export PATH=$PATH:/home/book/100ask_stm32mp157_pro-sdk/ToolChain/\
arm-buildroot-linux-gnueabihf_sdk-buildroot/bin

6.5.2.1 编译 trust 版本 uboot:

对于STM32MP157全功能版,u-boot的编译配置过程如下:

book@100ask:~/100ask_stm32mp157_pro-sdk/Uboot-2020.02$ make stm32mp15_trusted_defconfig
book@100ask:~/100ask_stm32mp157_pro-sdk/Uboot-2020.02$ make DEVICE_TREE=stm32mp157c-100ask-
512d-v1 all -j4

如下为具体的执行步骤:
在这里插入图片描述
编译完成后生成的文件如下图所示。
在这里插入图片描述
编译完成之后生成u-boot.stm32,可以用于TF卡启动和EMMC启动, 可以将此文件拷贝至资料光盘02_Images\Flashlayout 目录下,以备后续更新操作使用。

6.5.3 更新 uboot 镜像

6.5.3.1.烧写工具更新 trust 版本 uboot 镜像

使用STM32CubeProgrammer烧写工具更新

请参考章节《7.3.2 单独更新Trust uboot方法》

6.5.3.1.开发板系统上更新 trust 版本 uboot 镜像

  • Emmc 文件系统内更新 uboot 镜像。

通过 nfs 网络挂载或者 ssh 等方式吧把上述编译好的 u-boot.stm32 镜像文件拷贝到开发板文件系统任意目录,之后执行如下命令来更新 uboot。

root@100ask:~$ dd if=u-boot.stm32 of=/dev/mmcblk2p1 conv=fsync > /dev/null 2>&1
root@100ask:~$ sync

6.6 编译 Linux Kernel

6.6.1 Linux 内核介绍

Linux内核(英语:Linux kernel)是一种开源的类Unix操作系统宏内核。整个Linux操作系统家族基于该内核部署在传统计算机平台(如个人计算机和服务器,以Linux发行版的形式)和各种嵌入式平台,如路由器、无线接入点、专用小交换机、机顶盒、FTA接收器、智能电视、数字视频录像机、网络附加存储(NAS)等。工作于平板电脑、智能手机及智能手表的Android操作系统,它的底层操作系统也是Linux。尽管在桌面计算机的占用率较低,但基于Linux的操作系统统治了几乎从移动设备到主机的其他全部领域。实际Linux的发行版Ubuntu,其易用性也逐渐接近Windows。

Linux kernel官网:https://www.kernel.org/
linux Kernel维基百科:https://www.wiki.kernel.org/
在线阅读linux kernel源码:https://elixir.bootlin.com/
ST官方源码地址:https://github.com/STMicroelectronics/linux.git
ST官方提供内核源码示例:https://github.com/STMicroelectronics/linux-examples
100ask_Stm32mp157开发板Git仓库地址: https://gitee.com/weidongshan/stm32mp15xc-kernel.git
更多关于Linux内核资料请参考页面:http://wiki.100ask.org/Category:Linux_Operating_System

上述Git仓库是专为100ask_imx6ull系列开发板制定的Linux内核,它有如下特性:

名称是否支持作用是否开源
USB HOST支持USB Host驱动,支持OHCI和EHCI两种传输模式Yes
USB OTG支持Usb otg驱动,支持device模式和host模式Yes
Network支持RJ-45以太网驱动Yes
MMC/SD支持MMC/SD卡驱动Yes
EMMC支持EMMC驱动Yes
I2C支持I2C驱动Yes
SPI支持SPI驱动Yes
LCD支持显示驱动Yes
RTC支持内置RTC时钟驱动Yes
ADC支持ADC驱动Yes
TouchScreen支持电容触摸Yes
UART支持串口驱动Yes
LED支持LED驱动,包括GPIO LED和PWMYes
Button支持GPIO Button 驱动Yes
Camera支持摄像头驱动Yes

6.6.2 编译内核镜像

不同的开发板对应不同的配置文件,配置文件位于内核源码arch/arm/configs/目录。

编译Linuxkernel前必须先配置好工具链等开发环境,这里我们使用的交叉编译工具链为Buildroot GCC 8.4版本。

设置交叉编译,并执行编译命令。

book@100ask:~$ export ARCH=arm
book@100ask:~$ export CROSS_COMPILE=arm-buildroot-linux-gnueabihf
book@100ask:~$ export PATH=$PATH:/home/book/100ask_stm32mp157_pro-sdk/ToolChain/\
arm-buildroot-linux-gnueabihf_sdk-buildroot/bin

STM32MP157全功能版
kernel的编译过程如下(编译内核前需要先配置好工具链等一些环境变量):

book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ make 100ask_stm32mp157_pro_defconfig
book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ make uImage LOADADDR=0xC2000040 
book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ make dtbs

编译步骤参考如下,编译完成 uImage 后才可编译设备树文件,如果你觉得编译速度很慢可以加 -j<数 字>来使用并行任务编译,如下图加 -j8 参数使用 8 个并行任务来编译内核,编译速度视性能而言,i7 9700F 主频 3Ghz 四核 8G 内存全速编译可能需要 5 分钟左右。

在这里插入图片描述
在这里插入图片描述
编译完成后生成的文件如下图所示
在这里插入图片描述
编译完成后,在arch/arm/boot目录下生成uImage内核文件, 在arch/arm/boot/dts目录下生成设备树
的二进制文件

stm32mp157c-100ask-512d-lcd-v1.dtb

把这2个文件复制到/home/book/nfs_rootfs目录下备用,如下图:

book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ cp arch/arm/boot/uImage ~/nfs_rootfs/
book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ cp arch/arm/boot/dts/\
stm32mp157c-100ask-512d-v1.dtb ~/nfs_rootfs/

在这里插入图片描述

6.6.3 编译内核模块

无论是哪个版本的STM32MP157开发板,编译内核模块的命令是一样的。

STM32MP157全功能版 进入内核源码目录后,就可以编译内核模块了:

book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ make ARCH=arm CROSS_COMPILE=arm-buildrootlinux-gnueabihf- modules -j8

内核模块编译命令执行截图示例
在这里插入图片描述

6.6.4 安装内核模块到 Ubuntu 某个目录下备用

可以先把内核模块安装到nfs根文件系统(/home/book/nfs_rootfs为安装目录)。

注意:下面会执行tree命令,如果提示没有该命令,需要执行“sudo apt install tree”命令安装tree工具(前提是Ubuntu能上网)。

STM32MP157全功能版
执行以下命令:

book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ make ARCH=arm INSTALL_MOD_PATH=/home/book\
/nfs_rootfs modules_install

如下图,把模块安装在nfs所在目录 /home/book/nfs_rootfs/ 目录下:
在这里插入图片描述
安装后的的/home/book/nfs_rootfs/目录结构如下图所示:
在这里插入图片描述
由于模块编译安装完成后会自动生成两个链接到内核源码目录的链接文件,需要手动删除这两个链接文件才可以继续执行拷贝内核模块到开发板步骤,否则会提示空间不足等问题,如下所示,执行rm build source 删除两个红框所示的链接文件。

book@virtual-machine:~/nfs_rootfs/lib/modules/5.4.31-g04363cb64$ rm build source

在这里插入图片描述
之后可以继续执行拷贝模块到开发板操作。

6.7 安装内核和模块到开发板上

注意:《第十章 烧写整个系统或更新部分系统》中列出了很多种更新开发板文件的方法,开发过程中最常用的是NFS,看本节即可。

假设:执行上述命令后,在Ubuntu的/home/book/nfs_rootfs目录下已经有了uImage、dtb文件,并且有lib/modules子目录(里面含有各种模块)。

下面,要把这些文件复制到开发板上。

如果你使用的是VMware NAT方式,或是使用docker,假设Windows IP为192.168.1.100,在开发板启动进入Linux后,输入root登录,然后执行以下命令(注意:必须指定port为2049、mountport为9999):

mount -t nfs -o nolock,vers=3,port=2049,mountport=9999 192.168.1.100:/home/book/nfs_rootfs /mnt
cp /mnt/zImage /boot
cp /mnt/*.dtb /boot
cp /mnt/lib/modules /lib -rfd

如果你使用的是VMware桥接方式,假设Ubuntu IP为192.168.1.100,在开发板上执行以下命令:

mount -t nfs -o nolock,vers=3 192.168.1.100:/home/book/nfs_rootfs /mnt
cp /mnt/zImage /boot
cp /mnt/*.dtb /boot
cp /mnt/lib/modules /lib -rfd

最后重启开发板,就会使用新的zImage、dtb、模块。

6.8 使用 Buildroot 构建根文件系统

6.8.1 Buildroot 简介

制作根文件系统有归多种方法:

① 使用Busybox手工制作

Busybox本身包含了很了Linux命令,但是要编译其他程序的话需要手工下载、编译,如果它需要某些依赖库,你还需要手工下载、编译这些依赖库。

如果想做一个极简的文件系统,可以使用Busybox手工制作。

② 使用Buildroot自动制作

它是一个自动化程序很高的系统,可以在里面配置、编译内核,配置编译u-boot、配置编译根文件系统。在编译某些APP时,它会自动去下载源码、下载它的依赖库,自动编译这些程序。

Buildroot的语法跟一般的Makefile语法类似,很容易掌握。

③ 使用Yocto

NXP、ST等公司的官方开发包是使用Yocto,但是Yocto语法复杂,并且Yocto动辄10GB,下载安装都很困难,普通笔记本编译可能需要2-3天甚至更久,非常不适合初学者(我们不推荐使用yocto构建文件系统)。

基于上述特点,我们选择Buildroot。

Buildroot是一组Makefile和补丁,可简化并自动化地为嵌入式系统构建完整的、可启动的Linux环境(包括bootloader、Linux内核、包含各种APP的文件系统)。Buildroot运行于Linux平台,可以使用交叉编译工具为多个目标板构建嵌入式Linux平台。Buildroot可以自动构建所需的交叉编译工具链,创建根文件系统,编译Linux内核映像,并生成引导加载程序用于目标嵌入式系统,或者它可以执行这些步骤的任何独立组合。例如,可以单独使用已安装的交叉编译工具链,而Buildroot仅创建根文件系统。

参考网址

6.8.2 系统特征讲解

我们都做了哪些改进?

我们基于buildroot官方 2020.02长期支持版本进行适配100ask-stm32mp1mp157-pro开发板,在此基础上针对ST yocto发行系统做了大量的裁剪,在保证最小系统的基础上增加对qt5.12 eglfs库的支持,同时也支持opencv3编程 mqtt库 swupdate ota升级等等比较常用的应用,我们也会提供如何在buildroot新增自己的软件包教程,同时源码保存在gitee上,链接地址为 https://gitee.com/weidongshan/ST-Buildroot.git 大家可以在上面提交issue 或者pull request。

init(为英语:initialization 的简写)是 Unix 和 类 Unix 系统中用来产生其它所有进程的程序。它以守护进程的方式存在,其进程号为 1。Linux 系统在引导时加载 Linux 内核后,便由 Linux 内核加载init 程序,由 init 程序完成余下的引导过程,比如加载运行级别,加载服务,引导 Shell/图形化界面等等。

什么是 systemv 守护进程?

System V(缩写为 SysV)在大多数 Linux 发行版中使用最广泛,在 systemv 中,有一个第一个程序在内核加载后运行。该程序称为 init。Init 做一些事情,其中之一就是加载一系列脚本来启动各种系统服务,例如网络,ssh 守护程序等。

System V 中的运行级别描述了某些状态。例如:

  • 运行级别 0:暂停
  • 运行级别 1:单用户模式
  • 运行级别 6:重新启动

systemv 的问题在于它需要仔细调整。假设您有一个要在启动时运行的网络文件系统(NFS)客户端。在网络正常工作之前运行 NFS 没有任何意义。因此,您必须确保它等待启动,直到网络已经正常工作为止。Systemv init 这样做的方法是为服务启动设置严格的顺序。每个服务都分配有一个优先级编号,init 会按优先级顺序启动服务。如果需要确保网络连接后启动服务,则必须手动为服务分配更高的优先级。这必须由某人(通常是软件包维护者)针对计算机上运行的每项服务来完成。

在这里插入图片描述
所有 System V 初始化脚本都存储在/etc/rc.d/init.d/或/etc/init.d 目录中。这些脚本用于控制系统的启动和关闭。通常,您会在这个目录找到启动 ssh 服务器或网络的脚本,使用/etc/init.d/S50sshd start 开启某个服务或者使用/etc/init.d/S50sshd stop 关闭某个服务。

什么是 systemd 守护进程?

systemd 这一名字源于 Unix 中的一个惯例:在 Unix 中常以“d”作为系统守护进程(英语:daemon,亦称后台进程)的后缀标识。除此以外,systemd 亦是借代英文术语 D 体系,而这一术语即是用于描述一个人具有快速地适应环境并解决困难的能力。

systemd 是 Linux 电脑操作系统之下的一套中央化系统及设置管理程序(init),包括有守护进程、程序库以及应用软件,由 Lennart Poettering 带头开发。其开发目标是提供更优秀的框架以表示系统服务间的依赖关系,并依此实现系统初始化时服务的并行启动,同时达到降低 Shell 的系统开销的效果,最终代替现在常用的 System V 与 BSD 风格 init 程序。目前绝大多数的 Linux 发行版都已采用 systemd 代替原来的System V。

在这里插入图片描述
将 service(服务)、target(运行模式,类似于运行级别)、mount、timer、snapshot、path、socket、swap 等称为 Unit。比如,一个 auditd 服务(就是 auditd.service)就是一个 Unit,一个 multi-user.target运行模式也是一个 Unit,其中不同的服务通过 systemctl 来进行统一管理,例如重启一个 sshd 服务,需要执行 systemctl restart sshd 命令,同样的如果添加一个启动程序需要自己定义一个 service 服务才可以。

你可以用我们提供的 buildroot 做些什么?

快速实现自己的想法,增加自己的应用,学习了解 busybox 以及各种包是如何编译生成,用于调试内核或者应用程序等等。

6.8.3 配置文件说明

下面介绍如何构建 100ASK_STM32MP157_PRO 全功能版的根文件系统

配置文件含义
100ask_stm32mp157_pro_ddr512m_systemV_core_defconfig使用systemV守护进程的系统(包含基本工具集包)
100ask_stm32mp157_pro_ddr512m_busybox_core_defconfig使用busybox守护进程的系统(包含基本工
100ask_stm32mp157_pro_ddr512m_systemD_core_defconfig使用systemD守护进程的系统(包含基本工
100ask_stm32mp157_pro_ddr512m_systemD_qt5_defconfig使用systemD守护进程的系统包含Qt GUI

6.8.4 编译系统

下面以100ask_stm32mp157_pro_ddr512m_systemD_qt5_defconfig配置文件为例,说明 Buildroot 的配置编译过程:

book@100ask:~/100ask_stm32mp157_pro-sdk/Buildroot_2020.02.x$ make \
100ask_stm32mp157_pro_ddr512m_systemD_qt5_defconfig
book@100ask:~/100ask_stm32mp157_pro-sdk/Buildroot_2020.02.x$ make all

在这里插入图片描述
注意:编译时需要联网,需要下载某些文件,由于机器性能不同,编译时间不同。性能差的电脑,有可能需要等待5 ~ 6个小时。

编译完成后终端提示如下图所示。

在这里插入图片描述

6.8.5 镜像文件

编译成功后文件输出路径为 output/images
在这里插入图片描述
可以参考《第七章 烧写整个系统或更新部分系统》把上面编译出来的100ask-stm32mp157-pro-512d-v1-tfa.img烧写到SD/TF卡,即可通过TF卡启动开发板进入系统。

6.8.6 扩展学习

深入了解学习更多关于buildroot知识请参考 http://wiki.100ask.org/Buildroot

buildroot下进入menuconfig包选择配置配置界面

book@100ask:~/100ask_stm32mp157_pro-sdk/Buildroot_2020.02.x$ make menuconfig

buildroot下单独编译内核

book@100ask:~/100ask_stm32mp157_pro-sdk/Buildroot_2020.02.x$ make linux-rebuild

buildroot下进入内核make menuconfig配置选项界面

book@100ask:~/100ask_stm32mp157_pro-sdk/Buildroot_2020.02.x$ make linux-menuconfig

buildroot下单独编译u-boot

book@100ask:~/100ask_stm32mp157_pro-sdk/Buildroot_2020.02.x$ make uboot-rebuild

buildroot下单独编译某个软件包

book@100ask:~/100ask_stm32mp157_pro-sdk/Buildroot_2020.02.x$ make <pkg>-rebuild

buildroot下进入busybox配置界面

book@100ask:~/100ask_stm32mp157_pro-sdk/Buildroot_2020.02.x$ make busybox-menuconfig

buildroot下生成系统sdk,最后生成的目录在output/images/目录下

book@100ask:~/100ask_stm32mp157_pro-sdk/Buildroot_2020.02.x$ make sdk

6.9 使用 Yocto 构建文件系统

6.9.1 简介

Yocto项目使用更强大和定制化的方法,来构建出适合嵌入式产品的Linux系统。Yocto不仅仅是一个制做文件系统工具,同时提供整套的基于Linux的开发和维护工作流程,使底层嵌入式开发者和上层应用开发者在统一的框架下开发,解决了传统开发方式下零散和无管理的开发形态。

yocto是一个开源的“umbrella”项目,意指它下面有很多个子项目,Yocto只是把所有的项目整合在一起,同时提供一个参考构建项目Poky,来指导开发人员如何应用这些项目,构建出嵌入式Linux系统。它包含Bitbake、 OpenEmbedded-Core, 板级支持包,各种软件包的配置文件。可以构建出不同类需求的系统,如带Qt5.14图形库的100ask-image-qt系统,全功能命令行系统100ask-image-core,基于ST官方weston系统及100ask-image-weston的系统。

100ASK_STM32MP157提供了符合Yocto的配置文件,帮助开发者构建出可烧写在100ASK_STM32MP157_PRO板上的Linux系统像。Yocto还提供了丰富的开发文档资源,让开发者学习并定制自己的系统。由于篇幅有限,不能完整介绍Yocto的使用,请用户自行上网搜索。

本节适合需要对文件系统进行深度定制的开发者,希望从Yocto构建出符合100ASK_STM32MP157系列开发板的文件系统,同时基于它的定制需求。初次体验使用或无特殊需要的开发者可以直接使用MYD-YA157C已经提供的文件系统。由于Yocto构建前需要下载文件系统中所有软件包到本地,为了快速构建,100ASK_STM32MP157已经把相关的软件打包好,可以直接解压使用,减少重复下载的时间。 注意:构建Yocto不需要加载工具链环境变量,请创建新shell或打开新的终端窗口。

注意:编译yocto系统以主频为2.5Ghz 4核处理器 DDR4 8GB内存 200GB磁盘空间大小的主机配置为例,编译100ask-image-core 可能最少需要5个小时,编译带QT或者weston界面的系统镜像可能需要10个小时以上,yocto最小支持配置建议在2GB内存2核2.5Ghz 100G空间磁盘上。

注意:执行一键配置环境脚本安装部分依赖包,否则会在编译时报错。

6.9.2 配置编译

book@100ask:~/100ask_stm32mp157_pro-sdk/Yocto_Dunfell$ DISTRO=openstlinux-eglfs MACHINE=100ask\source layers/meta-100ask-st/scripts/envsetup.sh

在这里插入图片描述
由于yocto所需软件包大部分都在国外网站上保存,国内下载很慢,所以需要单独拷贝资料光盘“07_Bsp_sdk (BSP包)/YoctoDunfell_Downloads.tar.gz” 到“/home/book/100ask_stm32mp157_pro-sdk/Yocto_Dunfell/build-openstlinuxeglfs-100ask ”目录下,之后执行 “tar -xvf YoctoDunfell_Downloads.tar.gz “等待解压缩完成,会出现一个dowloads文件夹,里面包含了所有yocto下载必需软件包。

继续执行编译命令:

book@100ask:~/100ask_stm32mp157_pro-sdk/Yocto_Dunfell/build-openstlinuxeglfs-100ask$ bitbake \100ask-image-core

在这里插入图片描述
编译完成后生成的目录镜像在”book@100ask:~/100ask_stm32mp157_pro-sdk/Yocto_Dunfell/build-openstlinuxeglfs-100ask/tmp-glibc/deploy/images/100ask “目录内。

6.9.3 扩展命令

6.9.3.1 单独编译某个包

比如单独编译内核,需要先清除之前的编译缓存再进行编译

book@100ask:~/100ask_stm32mp157_pro-sdk/Yocto_Dunfell/build-openstlinuxeglfs-100ask$ bitbake \virtual/kernel -c cleansstate
book@100ask:~/100ask_stm32mp157_pro-sdk/Yocto_Dunfell/build-openstlinuxeglfs-100ask$ bitbake \virtual/kernel

编译某个包需要执行如下命令,启动pkg为包名,一般以.bb为后缀,加上-v参数输出编译详细信息。

book@100ask:~/100ask_stm32mp157_pro-sdk/Yocto_Dunfell/build-openstlinuxeglfs-100ask$ bitbake \<pkg> -v

6.9.3.1 编译 sdk

编译完系统后可以执行如下命令生成 sdk 包,用以后续针对系统的应用开发。

book@100ask:~/100ask_stm32mp157_pro-sdk/Yocto_Dunfell/build-openstlinuxeglfs-100ask$ bitbake \meta-toolchain

编译完成生成的压缩包一般在” DISTRO/tmp-glibc/deploy/sdk “目录内

6.9.3.1 其它命令

使用多线程编译,需要修改DISTRO 里面的conf/local.conf配置项,新增如下两个参数

BB_NUMBER_THREADS ?= "8"
PARALLEL_MAKE ?= "-j 8"

6.9.4 深入学习 yocto

由于目前国内针对于yocto的教程比较稀缺,可以参考yocto官方提供的英文教程进行学习,其中资料网址是https://www.yoctoproject.org/docs/ 可以优先阅读学习,如下图红框所示的两份在线资料。
在这里插入图片描述
其中有几本基于yocto 项目开发的书籍,推荐阅读:
在这里插入图片描述
国内有个作者针对于上面左边的 Embedded Linux Projects Using Yocto Project Cookbook 翻译为中文版本,国内可以在各大图书网站直接购买阅读。
在这里插入图片描述

-end-