找回密码
 立即注册
首页 业界区 安全 嵌入式Linux系统构建

嵌入式Linux系统构建

寂傧 2025-6-9 13:47:00
参考资料

本篇内容主要参考

  • 韦东山的《嵌入式Linux应用开发完全手册V5.2_IMX6ULL_Pro开发板.pdf》, 具体课程见 百问网嵌入式专家-韦东山嵌入式专注于嵌入式课程及硬件研发
  • 嵌入式系统知识概述
实践环境为百问网官方开发板 100ASK_IMX6ULL-Pro
目标系统组成

Linux系统启动流程
1.png

一个有效的根文件系统集成了第三方和内部的所有软件组件。涉及组件的下载、提取、配置、编译和安装,并可能修复问题和调整配置文件。

  • 一个基本的根文件系统至少需要

    • 传统的目录层次结构,包括/bin、/etc、/lib、/root、/usr/bin、/usr/lib、/usr/share、/usr/sbin、/var、/sbin。
    • 一套基本实用程序,至少提供 init 程序、shell 和其他传统的 UNIX 命令行工具。这通常由 BusyBox 提供。
    • 安装在/lib 中的 C 库和相关库(线程库、数学库等)。一些配置文件,如/etc/inittab,以及初始化脚本/etc/init.d。

  • 在大多数嵌入式 Linux 系统通用的基础之上,可以添加第三方或内部组件。
几种解决方案:

  • 手动操作
  • 系统构建工具
  • 发行版或现成的文件系统
组件构建工具


  • Makefile
  • autotools
  • CMake
系统构建工具

可以使用不同的工具来自动化构建目标系统的过程,包括内核,有时还包括工具链。

  • 以正确的顺序自动下载、配置、编译和安装所有组件,有时在应用补丁修复交叉编译问题之后。
  • 已经支持大量的包,应该符合您的主要要求,并且易于扩展。
  • 构建变得可重现,这允许轻松更改某些组件的配置、升级它们、修复错误等。
常见的系统构建工具

  • Buildroot,由社区开发,https://buildroot.org。

    • 项目主要特点

      • 制作启动映像
      • 从源代码构建所有组件
      • 注重简单

    • 支持:根文件系统映像、内核、引导加载程序、工具链的自由组合

  • OpenWRT,最初是无线路由器 Buildroot 的一个分支,现在是一个更通用的项目,https://openwrt.org。
  • OpenEmbedded,更灵活但也更复杂,http://www.openembedded.org 及其工业化版本 Yocto 项目。
发行版Linux系统

Linux系统

  • 一种自由和开放源码的类UNIX操作系统,内核创建于1991-10-5,加上用户空间和应用程序之后成为Linux系统。
  • 遵循 GNU通用公共许可证(GPL),任何个人和机构都可以自由使用,修改和再发布。

    • GNU 是一个自由的操作系统,其内容软件完全以GPL方式发布(编译套件 GCC,C库 glibc,核心工具组 coreutils,调试器 GDB等)

发行版Linux:Linux distribution(GNU/Linux 发行版,为一般用户预先集成好Linux操作系统和各种应用软件,以软件包管理系统进行应用管理)

  • 商业发行版本:Ubuntu(支持x86,arm等不同的处理器架构),Red Hat(主要支持x86),SUSE
  • 社区发行版本:Debain,Fedora, Arch
  • 国内衍生Linux发行版本:Deepin,优麒麟
嵌入式Linux系统

2.png

嵌入式Linux系统框架
3.png

嵌入式Linux系统构建
4.png

开发环境搭建

基础软件安装

百问网提供了 Ubuntu 配置命令脚本,支持一键下载安装
  1. git clone https://e.coding.net/weidongshan/DevelopmentEnvConf.git
  2. cd DevelopmentEnvConf
  3. sudo ./Configuring_ubuntu.sh
复制代码
配置交叉编译工具链

工具链:一组编程工具,用于开发软件,创建软件产品。包括编译器和链接器,C库,调试器,头文件,二进制实用程序等等
交叉编译工具链:一组工具,用来将源代码构建为可以运行在其他平台的二进制代码,将构建环境和目标环境分隔开(不同的CPU架构,ABI,OS,Clib)
SDK(software development kit):一个更广泛的集合,除了工具链外,还包括为 Target 目标架构构建的库、头文件,以及示例代码、文档、开发指南等资源。
交叉编译构建过程:

  • Build(构建机器),使用 GCC 的源码,制作交叉编译工具链。
  • Host(主机),使用交叉编译工具链,编译出程序。
  • Target(目标机器),程序执行的地方。
5.png

本地工具链:build == host == target。
交叉编译工具链:build == host!= target
系统定义描述了一个系统:CPU 架构、芯片厂商、操作系统、ABI、C 库。

  • ---(完整名称);
  • --。
arm-foo-none-eabi,针对 ARM 架构的裸机工具链,来自供应商 foo。
arm-unknown-linux-gnueabihf,针对 ARM 架构的 Linux 工具链,使用来自未知供应商的 EABlhf ABI 和 glibc C 库。
armeb-linux-uclibcgnueabi,针对 ARM big-endian 的 Linux 工具链架构,使用 EABl ABI 和 uClibc C 库。
下载100ask_imx6ull 开发板的 BSP:
  1. git clone https://e.coding.net/codebug8/repo.git
  2. mkdir -p 100ask_imx6ull-sdk && cd 100ask_imx6ull-sdk
  3. ../repo/repo init -u https://gitee.com/weidongshan/manifests.git -b linux-sdk -m imx6ull/100ask_imx6ull_linux4.9.88_release.xml --no-repo-verify
  4. ../repo/repo sync -j4
复制代码
交叉编译工具链配置

交叉工具链的主要内容
6.png

配置过程主要是设置 PATH, ARCH 和 CROSS_COMPILE 三个环境变量:
  1. export ARCH=arm
  2. export CROSS_COMPILE=arm-buildroot-linux-gnueabihf-
  3. export PATH=$PATH:/home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
复制代码

  • 永久生效:修改用户配置文件 vim ~/.bashrc
  • 临时生效:直接执行命令,只对当前终端有效
系统构建

Bootloader: Uboot

Bootloader 是在操作系统运行之前运行的一段代码,用于引导操作系统,并支持下载和调试。
U-Boot 是一个开源的主引导加载程序,并含有多种命令以便调试系统。它适用于多种计算机体系结构,包括 ARM,RISC-V 和 x86。
不同的开发板对应不同的配置文件,配置文件位于 u-boot 源码的“configs/”目录。
对于 IMX6ULL Pro 版,u-boot 的编译过程如下(编译 uboot前必须先配置好工具链等开发环境):
  1. cd /home/book/100ask_imx6ull-sdk/Uboot-2017.03
  2. make distclean
  3. make mx6ull_14x14_evk_defconfig
  4. make
复制代码
编译完成之后生成 u-boot-dtb.imx,可以烧在 TF 卡、EMMC 上
  1. # 将u-boot-dtb.imx 文件烧写到 EMMC 上:
  2. echo 0 > /sys/block/mmcblk1boot0/force_ro
  3. dd if=u-boot-dtb.imx of=/dev/mmcblk1boot0 bs=512 seek=2
  4. echo 1 > /sys/block/mmcblk1boot0/force_ro
复制代码
Linux Kernel 和模块

编译驱动程序之前要先编译内核:

  • 驱动程序要用到内核文件
  • 编译驱动时用的内核、开发板上运行到内核,要保持一致
  • 同理,更换板子上的内核后,板子上的其他驱动也要更换
流程说明
7.png


  • 获取配套的交叉编译工具链

    • SOC原厂提供:NXP ST Rockchip Amlogic Allwinnertech等。
    • 社区下载:Linrao Debian ARM Bootlin

  • 下载kernel源码

    • 获取Linux Kernel主线LTS源码

      • Git方式获取:https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
      • 压缩包版下载:https://mirrors.edge.kernel.org/pub/linux/kernel/

    • 获取芯片原厂Kernel源码

  • Host下配置开发环境

    • 安装必要依赖包
    • 解压配置合适的工具链

  • 指定编译板子配置文件
    make BOARDNAME_defconfig
  • 编译

    • 编译内核镜像 make -jN
    • 编译设备树 make dtbs
    • 编译安装模块驱动 make modules

编译内核

源码镜像

  • vmlinux,未压缩的原始内核映像,ELF 格式,用于调试目的,但无法启动。
  • arch//boot/*image,是最终可以启动的压缩后的内核镜像文件:

    • bzImage for x86,
    • zImage for ARM,
    • Image.gz for RISC-V,
    • vmlinux.bin.gz for ARC等。

  • arch//boot/Image,也可以引导的未压缩内核映像。
  • arch//boot/dts/*.dtb,编译的设备树文件(某些架构)。
  • 所有内核模块,分布在内核源代码树中,作为 .ko(内核目标)文件。
配置编译环境:指定架构和编译器,以及单板的配置文件
不同的开发板对应不同的配置文件,配置文件位于内核源码 arch/arm/configs/ 目录。
IMX6ULL_Pro开发板 kernel 的编译过程如下:
  1. cd /home/book/100ask_imx6ull-sdk/Linux-4.9.88
  2. make mrproper
  3. make 100ask_imx6ull_defconfig
  4. make zImage -j8
  5. make dtbs
复制代码
编译完成后,在 arch/arm/boot 目录下生成 zImage 内核文件, 在 arch/arm/boot/dts 目录下生成设备树的二进制文件 100ask_imx6ull14x14.dtb
编译安装内核模块


  • 使用内核模块可以支持更多不同的设备外设。
  • 模块使无需重启即可轻松开发驱动程序:加载、测试、卸载、重建、加载...
  • 有助于将内核映像大小保持在最小(在 PC 的 GNU/Linux 发行版中必不可少)。
  • 对于减少启动时间也很有用:您无需花时间初始化稍后才需要的设备和内核功能。
注意:一旦加载,在系统中拥有完全控制权和权限。没有特别的保护。这就是为什么只有 root 用户才能加载和卸载模块。
编译:
  1. cd ~/100ask_imx6ull-sdk/Linux-4.9.88/
  2. make modles
复制代码
安装内核模块到Ubuntu内的某一个目录备用:
  1. cd ~/100ask_imx6ull-sdk/Linux-4.9.88/
  2. make ARCH=arm INSTALL_MOD_PATH=/home/book/nfs_rootfs modules_install
复制代码
8.png

编译设备树


  • 目标单板所需的硬件设备信息。
  • 一般用于嵌入式设备。
设备树文件要与目标单板配套使用。一般和内核镜像存放同一位置。
内核源码目录下执行 make dtbs
安装内核和模块到开发板
  1. mount -t nfs -o nolock,vers=3 192.168.5.11:/home/book/nfs_rootfs /mnt
  2. cp /mnt/zImage /boot
  3. cp /mnt/100ask_imx6ull-14x14.dtb /boot
  4. cp /mnt/lib/modules /lib -rfd
复制代码
替换对应的目录中文件,重启开发板即可完成更新 zImage、dtb、模块
完整的系统

根文件系统与 busybox

Linux 系统需要一组基本的程序才能工作,包括一个 init 程序、一个 shell 以及用于文件操作和系统配置的各种基本实用程序。在普通的 GNU/Linux 系统中,这些程序由不同的项目提供。
Busybox 本身包含了很多 Linux 命令,但是要编译其他程序或者某些依赖库,需要手工下载、编译。 如果想做一个极简的文件系统,可以使用 Busybox 手工制作。
文件系统是一套实现了数据的存储、分级组织、访问和获取等操作的抽象数据类型(Abstract data type)

  • 数据存取

    • 使用硬盘和光盘这样的存储设备,并维护文件在设备中的物理位置
    • 通过网络协议(如 NFS、SMB 等)提供的或者暂存于内存上
    • 虚拟文件(如 proc 文件系统)

  • 用户访问管理

    • 不必关心数据实际保存在硬盘(或者光盘)的地址为多少的数据块上,只需要记住这个文件的所属目录和文件名
    • 不必关心硬盘上的那个块地址没有被使用,硬盘上的存储空间管理(分配和释放)功能由文件系统自动完成

根文件系统:被挂载在特定层次结构的 root 位置,由“/”标识

  • mount 和 umount 是程序,是文件系统中的文件。所以在安装至少一个文件系统之前无法使用
  • 不能用普通的挂载命令挂载,由内核直接挂载,根据“root=”内核选项进行设置。当没有可用的根文件系统时,内核会崩溃
  • 支持从不同位置挂载,包括存储设备(硬盘,SD卡等),NFS和内存。
busybox 在根文件系统:
9.png

Buildroot

Buildroot 是一组 Makefile 和补丁,可自动化地为嵌入式系统构建完整的、可启动的 Linux 环境(包括 bootloader、Linux 内核、包含各种 APP的文件系统)。

  • 可以自动构建所需的交叉编译工具链,创建根文件系统,编译 Linux 内核映像,并生成引导加载程序用于目标嵌入式系统。并支持所有步骤的任何独立组合。
  • 使用简单:类似内核的menuconfig
  • 支持大量的实用软件包,比如 QT等
构建说明

  • 所有的构建都会输出到顶层目录下的 output/目录内。O = output。另外也支持 out-of-tree 构建。
  • 配置文件作为.config 存储在顶级 Buildroot 源目录中。CONFIG_DIR = $(TOPDIR),TOPDIR = $(shell pwd)
IMX6ULL_Pro 编译过程
  1. cd ~/100ask_imx6ull-sdk/Buildroot_2020.02.x
  2. #选择配置界面
  3. make menuconfig
  4. # 单独编译内核
  5. make linux-rebuild
  6. # 进入内核配置选项
  7. make linux-menuconfig
  8. # 单独编译 u-boot
  9. make uboot-rebuild
  10. # 单独编译某个软件包
  11. make <pkg>-rebuild
  12. # 进入 busybox 配置选项
  13. make busy-box-menuconfig
  14. # 生成系统 sdk
  15. make sdk
复制代码
配置文件说明
10.png

编译系统
  1. cd /home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x
  2. make clean
  3. make 100ask_imx6ull_pro_ddr512m_systemV_qt5_defconfig
  4. make all -j4
复制代码
镜像文件说明
buildroot2020.02.x/output/images/

  • 100ask_imx6ull-14x14.dtb【设备树文件】
  • rootfs.ext2
  • rootfs.ext4
  • rootfs.tar
  • rootfs.tar.bz2【打包并压缩的根文件系统,用于NFSROOT启动】
  • 100ask-imx6ull-pro-512d-systemv-v1.img【完整的系统镜像,用于烧写EMMC和SD卡】
  • uboot-dtb.imx【Uboot镜像】
  • zImage【内核镜像】
系统烧录

USB 模式烧录

使用 USB 烧写工具:

11.png

12.png

使用命令行


  • 执行脚本命令

    • sudo ./bin/uuu scripts/basic/emmc/write_all.clst #烧写整个系统

  • 对于裸机程序,名字各有不同,没有提供固定的脚本

    • sudo ./bin/uuu -b emmc(or sd) firmware/u-boot-dtb_fastboot_100ask.imx files/led.imx #把 led.imx 烧到 EMMC

在开发板上直接烧写

烧写 u-boot

  • 将uboot镜像u-boot-dtb.imx拷贝到开发板根目录

    • 烧写 EMMC
      1. echo 0 > /sys/block/mmcblk1boot0/force_ro                                         //取消此分区的只读保护
      2. dd if=u-boot-dtb.imx of=/dev/mmcblk1boot0 bs=512 seek=2         //实际烧写命令
      3. echo 1 > /sys/block/mmcblk1boot0/force_ro                                         //打开此分区的只读保护
      复制代码
    • 烧写 SD/TF
      dd if=u-boot-dtb.imx of=/dev/mmcblk0 bs=512 seek=2

更新内核或设备树
开发板使用的内核名为 zImage,设备树名为 100ask_imx6ull-14x14.dtb。 保存在开发板的/boot 目录中,只要替换/boot 目录下的文件后重启即可完成更新
烧写 SD/TF 卡

Windows SD/TF 卡烧录工具

格式化:
13.png

烧写镜像:
14.png

Ubuntu下使用命令行烧录 SD/TF 卡

在 Ubuntu 下可以更精细地操作 SD/TF 卡:把 sdcoard.img 整个烧写到卡上,单独烧写 u-boot 到卡上,甚至挂接卡上的文件系统后单独更新里面的文件。

  • 识别 SD/TF 卡:使用 dmesg 命令获取设备挂载的设备节点
  • 更新整个系统镜像:使用 dd 命令烧写 sdcard.img 镜像文件到 /dev/sdb 设备

    • sudo dd if=sdcard.img of=/dev/sdb

  • 只更新卡上的 u-boot:使用 dd 命令烧写 uboot的imx 镜像文件到 /dev/sdb 设备

    • sudo dd if=u-boot-dtb.imx of=/dev/sdb bs=1k seek=1 conv=fsync

  • 更新 SD/TF 卡中的内核和设备树

    • 对于曾经烧写过的 SD/TF 卡,上面已经有分区。使用 vmware 连接 TF 卡设 备后,Ubuntu 系统系统会自动挂载 tf 卡内的分区文件系统

      • 执行df -h命令找到对应目录,将其中的内核镜像拷贝到开发板 /boot 目录后重启



来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册