嵌入式Linux系统移植学习笔记
2025/12/11大约 8 分钟嵌入式
嵌入式Linux系统移植学习笔记
嵌入式Linux系统移植概述
嵌入式Linux系统构成
典型嵌入式Linux系统的组成部分
bootloder引导程序kernelLinux内核fs文件系统- 存放用户态的可执行程序和数据
rootfs系统级可执行程序datafs/userfs用户数据
什么是移植?
- 修改
bootloder源代码 - 修改
kernel源代码 - 修改文件系统中用户态
可执行程序源代码 - 目的:使其能够在目标硬件平台运行
Bootloder
Bootloder的作用
在PC电脑上,操作系统的引导工作通常由 BIOS引导程序 和
MBR分区表的第一个扇区或GPT分区表的EFI分区配合完成;
而嵌入式系统通常没有BIOS固件程序,因此整个系统的引导工作由bootloder来完成
- 负责初始化硬件设备
- 建立内存空间映射图
- 准备好合适的软硬件环境
- 以便最终调用操作系统内核程序
Bootloder的特点
- Bootloder不是操作系统内核代码
- Bootloder代码是针对特点CPU架构的汇编代码,不可移植。
- Bootloder代码依赖CPU架构 同时依赖嵌入式系统板级配置
Bootloder程序的基本流程
- 初始化硬件
- 将操作系统内核从Flash(存储器)拷贝到SDRAM(内存)中;
- 改写系统的内存映射
- 由Flash起始地址为0 改为SDRAM起始地址为0
- 设置堆栈指针 清零BSS段
- 执行C程序和调用子函数要用到。
- 提供Linux内核启动参数
- 启动Linux内核
- 改变PC寄存器的值,使得CPU开始执行真正的操作系统内核。
Kernel
Linux内核功能
- 内存管理:
- 裸板开发操作物理地址
- linux软件开发可以
malloc()获取虚拟地址
- 进程管理/进程通信
- 裸板开发通过RTOS实现多任务
- linux软件开发通过
fork()实现多任务
- 文件系统
- 裸板开发需要手动管理数据,精确到字节,需考虑存储地址、偏移、写入字节数
- linux软件开发通过文件系统管理数据,精确到文件
- 设备管理
- 网络协议
- linux是对网络协议支持最全的操作系统
- TCP/UDP/IP 协议都在linux源代码中有实现
内核的本质
- 从C语言角度看内核:c语言函数的集合。
- 从硬件角度看内核:硬件的管理者和维护者。
- 从应用程序角度看内核:服务提供者。
fs文件系统
嵌入式文件系统
- 是一种对存储设备上的数据进行组织管理的控制机制
- 是操作系统的一部分,负责管理和存储文件。
嵌入式Linux系统中典型的存储子系统层次化架构
- 用户层 (User Layer)
- 目录树:为用户和应用程序提供统一的文件访问视图。用户通过路径(如
/home/data/file.txt)来操作文件,完全无需关心文件实际存储在哪种介质上。
- 目录树:为用户和应用程序提供统一的文件访问视图。用户通过路径(如
- 内核层 (Kernel Layer)
- 虚拟文件系统 (VFS):这是整个架构的核心抽象层。它定义了一组标准的文件操作接口(如
open,read,write,close)。上层应用只需与VFS交互,而VFS负责将这些通用调用“翻译”并路由到下层的具体文件系统。 - 具体文件系统:VFS之下是各种针对不同存储介质优化的文件系统实现:
- JFFS2, YAFFS:专为Nand Flash设计的日志闪存文件系统,处理了闪存特有的擦除、读写均衡、坏块管理等问题。
- Cramfs, Romfs:只读的压缩文件系统,常用于存放固件、系统程序等不变的数据,节省空间。
- Ramdisk:将一部分内存(RAM)虚拟成块设备,作为临时性的高速文件系统,但掉电数据会丢失。
- 虚拟文件系统 (VFS):这是整个架构的核心抽象层。它定义了一组标准的文件操作接口(如
- 驱动层 (Driver Layer)
- MTD子系统:这是Linux内核为内存技术设备设计的统一驱动框架,专门用于管理各类闪存。
- MTD设备驱动:直接操作具体的Flash硬件(如某型号的Nor或Nand Flash芯片),负责最底层的读写、擦除命令。
- MTD字符/块设备:MTD向上提供的两种视图。
- MTD字符设备:提供对闪存的原始、字节级访问(如用于烧写引导程序)。
- MTD块设备:将闪存模拟成标准的块设备(类似硬盘),这样上层的文件系统(如JFFS2)就可以像操作普通磁盘一样在其上创建文件系统。
- MTD子系统:这是Linux内核为内存技术设备设计的统一驱动框架,专门用于管理各类闪存。
- 硬件层 (Hardware Layer)
- Nor Flash:支持芯片内执行,读写速度快,但价格高、容量小,常用于存储启动代码。
- Nand Flash:容量大、成本低,是主要的存储介质,但需要复杂的坏块管理和磨损均衡。
- RAM:易失性存储器,速度快,用于Ramdisk或作为系统缓存。


关键技术与数据流
- VFS的抽象作用:VFS是连接用户空间和多样存储后端的桥梁,它使得
ext4,FAT32,JFFS2等不同文件系统可以在Linux中共存,对用户透明。 - MTD的标准化意义:在MTD出现之前,每种Flash都需要为其文件系统编写专用驱动,耦合度高。MTD定义了标准的Flash操作接口,将闪存驱动和闪存文件系统解耦。文件系统基于MTD接口开发,驱动则实现MTD接口,二者可以独立开发和替换。
- 完整数据访问路径示例
当用户执行cat /mnt/nand/example.txt时:- 用户层通过路径发起请求。
- VFS解析路径,发现
/mnt/nand挂载的是YAFFS2文件系统。 - VFS调用YAFFS2文件系统的
read方法。 - YAFFS2文件系统将文件操作转换为对逻辑块地址的请求,并通过MTD块设备接口下发。
- MTD子系统将块设备请求转换为对具体Nand Flash芯片的读操作序列。
- MTD设备驱动操控硬件,从Nand Flash中读取数据,并按原路返回给用户。
总结
bootloder
- 硬件上电后固定跳转到该位置执行代码
- 初始化相应硬件设备
- 加载操作系统内核代码到内存
- 跳转到内核代码的起始位置开始执行
kernel
- 内核自解压ulmage
- 初始化硬件设备
- 初始化静态编译进内核的驱动模块
- 挂载根文件系统
- 执行第一个用户空间程序
第一个用户空间程序
- 配置用户环境
- 执行服务进程
u-boot 的配置、编译、烧写
u-boot是什么?
- U-Boot(Universal Boot Loader),即通用Bootloader
- 通用
- 支持多架构CPU: PowerPC、MIPC、X86、ARM等;
- 支持多系统OS: Linux、VxWorks、QNX、LynxOscar等操作系统
- 通用
- 德国DENX小组开发的用于多种嵌入式CPU的bootloader程序
- 遵循GPL条款的开放源代码项目
- Bootloader不属于操作系统内核,这一部分代码不具有可移植性;
- 在移植操作系统时,这部分代码必须加以改写;
- Bootloader不但依赖于CPU的体系结构,而且依赖于嵌入式系统板级设备的配置
u-boot特点
- 代码结构清晰、易于移植
- 支持多种处理器体系结构
- 支持众多开发板
- 支持网络协议、USB、SD等多种协议和设备
- 支持文件系统
u-boot代码的获取
- 官网获取 https://u-boot.org/
- github获取 https://github.com/u-boot/u-boot
- 开发板厂商提供
配置wsl: Ubuntu 22.04 记录
cat >> /etc/wsl.conf << EOF
# 互操作设置
[interop]
# 是否支持启动 Windows 进程
enabled=false
# 是否将 Windows 路径元素添加到 $PATH 环境变量
appendWindowsPath=false
EOF
# 在windows中执行:
# 关闭 WSL 发行版,以便重启 WSL 实例
wsl.exe --shutdown
wsl --list --all
wsl --manage Ubuntu-24.04 --move D:\WSL\Ubuntu安装gcc编译器
sudo update
# 安装 build-essential: gcc/g++/make/dpkg-dev/libc...
sudo apt install build-essential
# 编译u-boot要求gcc版本>10
# Ubuntu 20.04 默认 装的是GCC 9.4
# Ubuntu 22.04 默认 装的是GCC 11.3在Linux系统安装ARM交叉编译工具
# 从arm官网找到下载链接
# 注意不要下载嵌入式的编译工具gcc-arm-none-eabi
wget https://developer.arm.com/-/media/Files/downloads/gnu/14.3.rel1/binrel/arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz
# 解压
tar -xJvf arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz
# 安装
mkdir ~/.tools
mv ./arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-linux-gnu/ ~/.tools/
vi ~/.bashrc
export PATH=$PATH:/root/.tools/arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-linux-gnu/bin/
source ~/.bashrc构建 Arm 可信固件 (TF-A)
git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
cd trusted-firmware-a
# 编译 目标平台=sun50i_h616 (根据dts设备树描述,h618的cpu和h616共用一个)
make CROSS_COMPILE=aarch64-none-linux-gnu- PLAT=sun50i_h616 DEBUG=1
export BL31=$(pwd)/build/sun50i_h616/debug/bl31.bin构建u-boot
wget https://github.com/u-boot/u-boot/archive/refs/tags/v2026.01-rc4.tar.gz
tar -xzvf u-boot-2026.01-rc4.tar.gz
cd u-boot-2026.01-rc4
# 安装后续编译操作的依赖项 否则将依次报错缺失相关文件
sudo apt-get install bison flex swig python3-dev libssl-dev libgnutls28-dev
# 查看支持的开发板
ls configs/ | grep orangepi
# 生成配置文件 .config
make orangepi_zero2w_defconfig
# 生成 u-boot
make CROSS_COMPILE=aarch64-none-linux-gnu-