一、系统移植的组成部分
在学习嵌入式Linux之前,首先得搞清楚一个完整的系统是由哪些部分组成的。系统移植主要包含以下三个核心部分:
-
uboot
- 先于Linux操作系统之前运行的一段裸机程序,主要负责初始化软硬件,为Linux操作系统运行提供一个合适的环境。
-
kernel
- Linux操作系统内核(编译后通常为
zImage格式)。
- Linux操作系统内核(编译后通常为
-
rootfs
- 根文件系统:内核启动后第一个挂载的文件系统。
二、U-Boot 详解
1. 什么是 U-Boot?
U-Boot 是一段先于 Linux 操作系统之前运行的裸机程序。它的主要职责是初始化软硬件,为 Linux 操作系统的后续运行提供一个合适的运行环境。
2. U-Boot 的功能有哪些?
U-Boot 的初始化工作非常繁杂,主要分为以下几个层面:
-
初始化硬件
-
初始化 CPU 工作模式
-
初始化内存
-
初始化时钟
-
初始化异常向量表
-
关闭 MMU
-
关闭中断
-
关闭看门狗
-
关闭 Dcache
-
-
初始化板级硬件
-
初始化串口(方便后续程序员进行交互)
-
初始化网口
-
-
初始化软件
- 初始化网络
-
其他核心工作
-
将内核搬移到内存(DDR)
-
向内核传参
-
3. U-Boot 向内核传递的参数有哪些?
U-Boot 向内核传递参数,最典型的就是 bootargs 环境变量。来看一个典型的 NFS 挂载启动命令:
bash
setenv bootargs root=/dev/nfs nfsroot=192.168.1.200:/home/linux/nfs/rootfs ip=192.168.1.103 console=ttySAC0,115200 init=/linuxrc
这段长长的命令,每一部分都有特定的含义(对应图中的红字标注):
-
root=/dev/nfs:告诉内核根文件系统挂载的方式(NFS方式)。 -
nfsroot=192.168.1.200:/home/linux/nfs/rootfs:nfs方式挂载文件系统所在的IP及路径。 -
ip=192.168.1.103:告诉内核开发板IP。 -
console=ttySAC0,115200:控制台设备及波特率。 -
init=/linuxrc:init进程(内核启动后执行的第一个用户空间程序)。
4. U-Boot 如何向内核传参?
U-Boot 向内核传参涉及到汇编与C语言的交接。
-
源码位置:
arch/arm/lib/bootm.c和common/fdt_support.c -
寄存器设置: 在传参之前,需要先设置好几个寄存器的值:
-
r0 = 0(默认值) -
r1 = machine ID(机器ID) -
r2 = dtb在内存中的地址
-
-
传参机制: 设置好参数之后,U-Boot 向内核传递的参数(bootargs)会自动写入到设备树(Device Tree) 中的
chosen节点。内核启动后通过解析设备树节点,就能获得 U-Boot 传过来的参数。
5. U-Boot 为何要向内核传参?
-
虽然 U-Boot 向内核传参之前已经完成了软硬件的初始化,且已经适配了这块开发板。
-
但是,Linux 内核并不是对所有的开发板都完美适配。要让内核正常启动,必须通过 U-Boot 向内核传递参数:
-
R0 = 0,R1 = Machine ID(判断内核是否支持该开发板),R2 = dtb在内存中的地址。 -
传递
bootargs参数。
-
-
内核只有成功解析了这些参数,才能够正常启动。
6. 如何编译 U-Boot?
-
下载 U-Boot 源码并解压。
-
编译源码:
bash
make ARCH=ARM CROSS_COMPILE=arm-linux-gnueabihf-gcc
编译成功后,会得到 uboot.bin 二进制文件。
7. 如何移植 U-Boot?
编译 U-Boot 源码得到 uboot.bin 二进制文件后,通过 imxdownload 脚本文件将 uboot.bin 下载到 SD 卡中,并以 SD 卡方式启动开发板即可。
📌 补充: 本笔记学习的 U-Boot 版本为 2016.03(2016年3月份发布的版本)。
8. U-Boot 常用命令表
在 U-Boot 命令行模式下,掌握这些常用命令非常重要:
| U-Boot命令 | 功能说明 |
|---|---|
setenv |
设置 uboot 环境变量 |
saveenv |
保存 uboot 环境变量 |
printenv |
打印 uboot 环境变量 |
bootz |
启动 zImage 形式内核 |
boot |
执行 bootcmd 命令 |
tftp |
通过 tftp 将文件下载到内存 |
ping |
测试网络连通性 |
version |
查看 uboot 版本及 uboot 编译时间 |
help |
查看帮助命令 |
mmc info |
打印 emmc 信息 |
mmc erase |
擦除 emmc 分区 |
mmc read |
从 emmc 读取数据到内存 |
mmc write |
将内存数据写入到 emmc 分区 |
💡 学习小结:
U-Boot 就像是电脑的 BIOS,负责把底层的硬件叫醒,然后把接力棒(内核)搬到一个舒服的地方(内存),并且把路线图(设备树、启动参数)交代给内核。弄懂了传参的机制(R0, R1, R2 寄存器),对整个 ARM 架构的启动流程就有了更深刻的理解。继续加油!💪