Linux 之八 完整嵌入式 Linux 环境介绍及搭建过程详解
本文主要是介绍Linux 之八 完整嵌入式 Linux 环境介绍及搭建过程详解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧! 最近,有个需求需要验证一下嵌入式 LINUX 系统在 STM32上使用效果,正好手里有一块前几年的 STM32F769I-EVAL 的评估板,如下图所示的这个:
这块评估板的功能应该是非常全了,价格也是不便宜(应该算是挺贵)。ST 官网对于这块评估板的介绍参见 Evaluation board with STM32F769NI MCU。
熟悉 ST 的开发板的都知道,ST 的开发板主要有 ST 官方的 Nucleo 系列、Discovery Kits 系列、Evaluation 系列以及第三方开发板这些组成。其中,ST 自家开发板中 Evaluation 系列是功能最全的,也是价格最高的。第三方开发板差异就比加大了。
嵌入式 Linux 环境
在开始实际的移植编译工作之前,有必要先来说一下我们要搭建的完整的 Linux 运行环境是啥样的,以及包含那些部分。废话不多说,直接上图:
- U-Boot 本质就是就是一个复杂点的裸机程序(镜像是 u-boot.bin),与我们通常编写的 ARM 裸机程序没有本质区别。U-Boot 是无条件启动的,从零开始启动的。
- Linux Kernel 本身也是一个裸机程序(镜像是 zImage),和 U-Boot、裸机程序无本质区别。要说不同的地方,那就是内核运行起来后,在软件上分为内核层和应用层,分层后两层的权限不同,内存访问和设备操作的管理上更加精细(内核可以随便访问各种硬件,而应用程序只能被限制地访问硬件和内存地址)。
内核是不能开机自动完全从零开始启动的,内核启动需要别人帮忙。U-Boot 需帮助内核实现重定位,U-Boot 还要给内核提供启动参数。 - 我们的嵌入式 Linux 中的应用程序所需的编译工具链也需要我们自己编译,现有的就只有 ARM 提供的 Cortex-A 系列的(有些开发板厂商也提供自己编译好的 Linux 编译套件)。这里需要注意,嵌入式 linux 编译套件往往不是通用的!
- 根文件系统包括 Linux 启动时所必须的目录和关键性的文件,例如 Linux 启动时都需要有 init 目录下的相关文件。Linux 启动时,第一个必须挂载的是根文件系统;若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动。成功之后可以自动或手动挂载其他的文件系统。
- 这里的应用程序必须使用我们自己编译出的配套的编译套件来编译。根文件系统就是第一个需要使用我们自己的编译套件来编译的程序。
嵌入式环境与我们熟悉的 PC 环境还是有很大区别的。尤其是对于部分芯片,它没有 MMU,也就不能使用虚拟内存相关的所有技术。也就意味着,嵌入式中的地址都是实际的物理地址。
其次,嵌入式环境的另一个大特点就是资源非常紧张,这就导致了我们可能需要将最终的多部分的可执行程序放到不同的地方。举个例子,STM32 的 MCU 中,往往不能存放 Linux Kernel,我们需要将 Linux Kernel 放到一些外部存储器中。
对于 ARM 平台,ARM 给出了两个概念:加载域 和 执行域,加载域对应加载地址,执行域对应了一个执行地址。关于 ARM 的分散加载机制,可以参见博文 ARM 之十三 armlink(Keil) 分散加载机制详解 及 分散加载文件的编写 即可。
进一步具体到 STM32 芯片,我们的程序是放到内部的 FLASH 上的,FLASH 就是加载域,FLASH 上的具体地址就是加载域地址。同时,ST 芯片的设计可以从 FLASH 上执行代码(速度相对较慢),此时的加载域与执行域是同一个;还有一种更高效的方式是将代码放到 RAM 中执行(存放还是在 FLASH),此时 RAM 就是执行域,程序在 RAM 中的地址就是执行域地址。
嵌入式系统启动
前面介绍了嵌入式系统的组成部分,接下来看看整个系统如何工作起来。一般 SoC 内部会有个固化的引导程序,这个固化的 BootLoader 我在博文 STM32 之十四 System Memory、Bootloader 中有过详细的介绍。这段程序的会初始化部分外设以与外部通信,具体可以参考官方手册。
嵌入式系统构建工具
构建一整套嵌入式 Linux 系统是一件很庞大的事情,需要做很多工作。因此,诞生了一些嵌入式系统构建工具,以帮助开发者简化嵌入式系统的构建过程,减少工作量。常用的嵌入式系统构建工具有如下几个:
- Buildroot: Linux 平台上的一个用于构建嵌入式 Linux 系统的框架。整个 Buildroot 是由 Makefile 脚本和 Kconfig 配置文件构成的。使用它可以和编译 Linux 内核一样,通过使用 Kbuild/Kconfig 系统编译出一个完整的可以直接烧写到机器上运行的 Linux 系统软件(包含boot、kernel、rootfs 以及 rootfs 中的各种库和应用程序、交叉编译工具链)。
官方网站:https://buildroot.org/,提供了非常详细的文档。 - Yocto: Yocto Project 推出的一个开源的协作软件,提供模板、工具和方法帮你创建定制的 Linux 系统和嵌入式产品,而无需关心硬件体系。适合嵌入式Linux开发人员使用,极大地简化你的开发过程。Yocto 推荐使用 OpenEmbedded 构建系统。
Yocto Project 是 Linux 基金会的一个协作开源项目,其目标是生成工具和流程,以便为嵌入式和物联网软件创建独立于嵌入式硬件底层架构的 Linux 发行版。官方网站:https://www.yoctoproject.org/,提供了非常详细的文档。 - OpenEmbedded: 一个开源的嵌入式 Linux 系统构建环境,它允许开发人员为嵌入式系统创建一个完整的 Linux 发行版。由OpenEmbedded 社区开发,该社区于 2003 年正式成立。OpenEmbedded 的构建系统基于 BitBake 构建工具,其操作行为与 Gentoo Linux ebuilds 相似。
官方网站:http://www.openembedded.org/wiki/Main_Page,提供了非常详细的文档。 - PTXdist: Pengutronix 在 2001 年开发的一个构建系统,用于生成固件镜像。采用了 Linux 内核中的配置系统 Kconfig 来选择和配置每个包。
官方网站:https://www.ptxdist.org/,提供了非常详细的文档。
当然,我们也可以选择自己动手,根据上面嵌入式 Linux 环境,一点一点来构建其中的各个部分。后续,我就以手里的 STM32F769I-EVAL 的评估板为载体,尽量不使用已有的嵌入式构建工具,来一步一步搭建这个嵌入式 Linux 环境。
搭建过程
工欲善其事,必先利其器。第一步就是搭建 LINUX 系统开发环境,为此特地在笔记本上安装了 Ubuntu,具体使用的桌面开发环境是 Ubuntu 20.04.3 LTS。至于为啥选择 Linux 系统,而不是直接使用 Windows 系统想必大家都清楚为啥。
接下来准备好一个目录,后续所有的操作均在此目录中进行。我的操作是新建 /home/zcshou/STM32LINUX
这个目录,用于存放整个要为 STM32 嵌入式 Linux 环境编译的源代码,后续都在这个目录中进行。如下图所示:
最开始我想按照上面说的嵌入式环境的各个部分来分别写几篇博文来完整介绍整个搭建过程,然而写着写着内容越来越多,最终超过了 CSDN 编辑器的限制!最终决定把内容拆分成多篇文章。具体搭建过程就是如下几步:
- 编译 U-Boot。参见博文 U-Boot 之一 零基础编译 U-Boot 过程详解 及 编译后的使用说明
- 编译 Linux Kernel。参见博文 Linux 之九 零基础编译嵌入式 Linux Kernel 过程详解 及 编译后的使用说明
- 编译交叉编译工具链。参见博文 Linux 之十 编译自己的嵌入式 Linux 交叉编译工具链
- 编译 RootFS。参见博文 Linux 之十一 编译嵌入式 Linux 下的 RootFS
参考
- https://codeantenna.com/a/wf8KVWOhym
- https://www.its404.com/article/qq_44034198/110872972