嵌入式Linux系统构建
参考资料本篇内容主要参考
[*]韦东山的《嵌入式Linux应用开发完全手册V5.2_IMX6ULL_Pro开发板.pdf》, 具体课程见 百问网嵌入式专家-韦东山嵌入式专注于嵌入式课程及硬件研发
[*]嵌入式系统知识概述
实践环境为百问网官方开发板 100ASK_IMX6ULL-Pro
目标系统组成
Linux系统启动流程
一个有效的根文件系统集成了第三方和内部的所有软件组件。涉及组件的下载、提取、配置、编译和安装,并可能修复问题和调整配置文件。
[*]一个基本的根文件系统至少需要
[*]传统的目录层次结构,包括/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系统
嵌入式Linux系统框架
嵌入式Linux系统构建
开发环境搭建
基础软件安装
百问网提供了 Ubuntu 配置命令脚本,支持一键下载安装
git clone https://e.coding.net/weidongshan/DevelopmentEnvConf.gitcd DevelopmentEnvConfsudo ./Configuring_ubuntu.sh配置交叉编译工具链
工具链:一组编程工具,用于开发软件,创建软件产品。包括编译器和链接器,C库,调试器,头文件,二进制实用程序等等
交叉编译工具链:一组工具,用来将源代码构建为可以运行在其他平台的二进制代码,将构建环境和目标环境分隔开(不同的CPU架构,ABI,OS,Clib)
SDK(software development kit):一个更广泛的集合,除了工具链外,还包括为 Target 目标架构构建的库、头文件,以及示例代码、文档、开发指南等资源。
交叉编译构建过程:
[*]Build(构建机器),使用 GCC 的源码,制作交叉编译工具链。
[*]Host(主机),使用交叉编译工具链,编译出程序。
[*]Target(目标机器),程序执行的地方。
本地工具链:build == host == target。
交叉编译工具链:build == host!= target
系统定义描述了一个系统:CPU 架构、芯片厂商、操作系统、ABI、C 库。
[*]<arch>-<vendor>-<os>-<libc/abi>(完整名称);
[*]<arch>-<os>-<libc/abi>。
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:
git clone https://e.coding.net/codebug8/repo.gitmkdir -p 100ask_imx6ull-sdk && cd 100ask_imx6ull-sdk../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../repo/repo sync -j4交叉编译工具链配置
交叉工具链的主要内容
配置过程主要是设置 PATH, ARCH 和 CROSS_COMPILE 三个环境变量:
export ARCH=armexport CROSS_COMPILE=arm-buildroot-linux-gnueabihf-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前必须先配置好工具链等开发环境):
cd /home/book/100ask_imx6ull-sdk/Uboot-2017.03make distcleanmake mx6ull_14x14_evk_defconfig make编译完成之后生成 u-boot-dtb.imx,可以烧在 TF 卡、EMMC 上
# 将u-boot-dtb.imx 文件烧写到 EMMC 上:echo 0 > /sys/block/mmcblk1boot0/force_ro dd if=u-boot-dtb.imx of=/dev/mmcblk1boot0 bs=512 seek=2 echo 1 > /sys/block/mmcblk1boot0/force_roLinux Kernel 和模块
编译驱动程序之前要先编译内核:
[*]驱动程序要用到内核文件
[*]编译驱动时用的内核、开发板上运行到内核,要保持一致
[*]同理,更换板子上的内核后,板子上的其他驱动也要更换
流程说明
[*]获取配套的交叉编译工具链
[*]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 的编译过程如下:
cd /home/book/100ask_imx6ull-sdk/Linux-4.9.88make mrpropermake 100ask_imx6ull_defconfigmake zImage -j8make dtbs编译完成后,在 arch/arm/boot 目录下生成 zImage 内核文件, 在 arch/arm/boot/dts 目录下生成设备树的二进制文件 100ask_imx6ull14x14.dtb
编译安装内核模块
[*]使用内核模块可以支持更多不同的设备外设。
[*]模块使无需重启即可轻松开发驱动程序:加载、测试、卸载、重建、加载...
[*]有助于将内核映像大小保持在最小(在 PC 的 GNU/Linux 发行版中必不可少)。
[*]对于减少启动时间也很有用:您无需花时间初始化稍后才需要的设备和内核功能。
注意:一旦加载,在系统中拥有完全控制权和权限。没有特别的保护。这就是为什么只有 root 用户才能加载和卸载模块。
编译:
cd ~/100ask_imx6ull-sdk/Linux-4.9.88/make modles安装内核模块到Ubuntu内的某一个目录备用:
cd ~/100ask_imx6ull-sdk/Linux-4.9.88/make ARCH=arm INSTALL_MOD_PATH=/home/book/nfs_rootfs modules_install
编译设备树
[*]目标单板所需的硬件设备信息。
[*]一般用于嵌入式设备。
设备树文件要与目标单板配套使用。一般和内核镜像存放同一位置。
内核源码目录下执行 make dtbs
安装内核和模块到开发板
mount -t nfs -o nolock,vers=3 192.168.5.11:/home/book/nfs_rootfs /mntcp /mnt/zImage /bootcp /mnt/100ask_imx6ull-14x14.dtb /bootcp /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 在根文件系统:
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 编译过程
cd ~/100ask_imx6ull-sdk/Buildroot_2020.02.x#选择配置界面make menuconfig# 单独编译内核make linux-rebuild# 进入内核配置选项make linux-menuconfig# 单独编译 u-bootmake uboot-rebuild# 单独编译某个软件包make <pkg>-rebuild# 进入 busybox 配置选项make busy-box-menuconfig# 生成系统 sdkmake sdk配置文件说明
编译系统
cd /home/book/100ask_imx6ull-sdk/Buildroot_2020.02.xmake cleanmake 100ask_imx6ull_pro_ddr512m_systemV_qt5_defconfigmake 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 烧写工具:
使用命令行
[*]执行脚本命令
[*]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
echo 0 > /sys/block/mmcblk1boot0/force_ro //取消此分区的只读保护 dd if=u-boot-dtb.imx of=/dev/mmcblk1boot0 bs=512 seek=2 //实际烧写命令 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 卡烧录工具
格式化:
烧写镜像:
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 目录后重启
页:
[1]