新手自学嵌入式 | 学习日记:Linux驱动复习之系统移植(U-Boot篇)

一、系统移植的组成部分

在学习嵌入式Linux之前,首先得搞清楚一个完整的系统是由哪些部分组成的。系统移植主要包含以下三个核心部分:

  • uboot

    • 先于Linux操作系统之前运行的一段裸机程序,主要负责初始化软硬件,为Linux操作系统运行提供一个合适的环境。
  • kernel

    • Linux操作系统内核(编译后通常为 zImage 格式)。
  • 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?

  1. 下载 U-Boot 源码并解压。

  2. 编译源码:

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 架构的启动流程就有了更深刻的理解。继续加油!💪

相关推荐
lzx_0023 小时前
Linux 进程(三) 从进程状态到僵尸进程、孤儿进程
linux·服务器
FlightYe4 小时前
音视频修炼之容器与协议(四):RTSP详解
android·linux·ffmpeg·音视频·dash
刘马想放假5 小时前
CANviz 使用指南|Linux 安装、DBC 解码、实时曲线与 J1939 实战
linux·python·websocket
kloc6 小时前
聊天室项目入口网关子服务的实现
linux·c++
GeW6 小时前
深圳APEC峰会倒计时:数据库与Linux运维的"隐形考场"
linux
梦到啥说啥8 小时前
Linux网络编程:UDP网络协议
linux·网络协议·udp
无足鸟ICT9 小时前
【RHCA+】ipcrm命令(删除IPC资源)
linux
星恒随风10 小时前
MySQL 从零入门(四):表的增删改查与基础查询详解
linux·服务器·数据库·笔记·mysql
li星野10 小时前
相位补偿学习记录:把被颅骨“打乱“的声波重新对齐
学习
Z21-X11 小时前
云原生运维学习笔记:ECShop全链路容器化部署与Docker底层资源隔离深度剖析
运维·笔记·学习·云原生