目录
[一、Linux 启动流程](#一、Linux 启动流程)
[1.1 内核与根文件系统均在 SD 卡中(本地启动)](#1.1 内核与根文件系统均在 SD 卡中(本地启动))
[1.2 内核与根文件系统均在 Ubuntu 主机(网络启动)](#1.2 内核与根文件系统均在 Ubuntu 主机(网络启动))
[二、Ubuntu 网络启动环境配置](#二、Ubuntu 网络启动环境配置)
[2.1 TFTP 服务配置](#2.1 TFTP 服务配置)
[2.2 NFS 服务配置](#2.2 NFS 服务配置)
[三、U-Boot 常用命令](#三、U-Boot 常用命令)
[3.1 基础命令:环境验证与配置](#3.1 基础命令:环境验证与配置)
[3.2 核心命令:TFTP 下载与内核启动](#3.2 核心命令:TFTP 下载与内核启动)
[四、bootargs 启动](#四、bootargs 启动)
[4.1 完整命令配置](#4.1 完整命令配置)
[4.2 启动完成](#4.2 启动完成)
[5.1 内核恐慌典型现象](#5.1 内核恐慌典型现象)
[5.2 排查步骤](#5.2 排查步骤)
一、Linux 启动流程
(1)系统上电触发 ROM 启动
- 系统上电后,先执行 IMX6 内部 ROM 中的启动程序(根据 boot mode 选择对应的外设);
(2)Bootloader 初始化与自搬移
- 拷贝 SD 卡中的 Bootloader 前半部分程序到 IMX6 内部的 RAM 中,Bootloader 必须在自己的前半部分初始化好内存,并将自己的后半部分搬移到内存执行;
之后分为本地启动和网络启动两种情况。
1.1 内核与根文件系统均在 SD 卡中(本地启动)
(3)加载内核到内存
- Bootloader 完成初始化后,从 SD 卡中读取内核镜像(zImage),将其搬移到内存的 0x80800000 地址处;
(4)启动内核并挂载根文件系统
- Bootloader 通过 bootz 命令启动内核(PC 指针指向 0x80800000),内核启动完成后,自动挂载 SD 卡中存储的根文件系统,最终进入 shell 终端。
1.2 内核与根文件系统均在 Ubuntu 主机(网络启动)
(3)TFTP 下载内核与设备树
- Bootloader 通过网络(依赖 SD 卡中配置的网络参数)连接 Ubuntu 主机的 TFTP 服务,将 Ubuntu 中的 zImage 下载到内存 0x80800000 地址,将设备树文件(imx6.dtb)下载到 0x83000000 地址;
(4)引导内核启动
- Bootloader 向内核传递 bootargs 启动参数(指定 NFS 根文件系统路径、IP 地址等),执行bootz 命令启动内核;
(5)NFS 挂载根文件系统
- 内核启动后,根据 bootargs 配置,通过网络挂载 Ubuntu 主机 NFS 服务中的根文件系统(rootfs),完成系统初始化并进入 shell。
二、Ubuntu 网络启动环境配置
当内核及根文件系统位于 Ubuntu 主机时,需在 Ubuntu 上配置 TFTP(传输内核镜像) 和 **NFS(共享根文件系统)**服务。
2.1 TFTP 服务配置
TFTP 协议用于快速传输小型文件(如内核镜像、设备树),开发板通过 UBoot 命令直接从 Ubuntu 下载,无需拷贝到 SD 卡:
(1)安装 TFTP 服务
bash
sudo apt-get install tftpd-hpa tftp-hpa
(2)配置 TFTP 服务目录
- 创建 TFTP 共享目录(建议与 NFS 目录同级,方便管理):
bash
mkdir -p /home/linux/nfs/tftpboot
sudo chmod 777 /home/linux/nfs/tftpboot # 赋予读写权限
- 修改 TFTP 配置文件(/etc/default/tftpd-hpa),添加以下内容:
bash
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/linux/nfs/tftpboot" # 刚才创建的共享目录
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure --create"
(3)拷贝核心文件到 TFTP 目录
- 将编译好的内核镜像(zImage)和 IMX6 设备树文件(imx6.dtb)拷贝到 TFTP 服务目录:
bash
cp zImage imx6.dtb /home/linux/nfs/tftpboot/
(4)重启 TFTP 服务生效
bash
sudo systemctl restart tftpd-hpa
2.2 NFS 服务配置
NFS 用于共享根文件系统,开发板内核启动后通过网络挂载,支持实时修改根文件系统中的驱动模块、配置文件:
(1)安装 NFS 服务
bash
sudo apt-get install nfs-kernel-server
(2)配置 NFS 共享目录
- 创建根文件系统存储目录(建议在 NFS 主目录下新建子目录,避免混乱):
bash
mkdir -p /home/linux/nfs/imx6/rootfs
(3)解压根文件系统镜像
- 将下载的根文件系统压缩包(rootfs.tar.bz2)拷贝到 NFS 共享目录并解压:
bash
# 进入根文件系统存储目录
cd /home/linux/nfs/imx6/rootfs
# 解压压缩包(保留原始权限和目录结构)
sudo tar -xvf rootfs.tar.bz2
解压完成后,目录下会生成 bin、etc、lib、root 等系统目录,后续驱动模块(.ko 文件)可直接放在该目录下供开发板加载。
三、U-Boot 常用命令
3.1 基础命令:环境验证与配置
- **help 或 ?:**查看 U-Boot 支持的所有命令。
- **reset:**重启开发板(等效于硬件复位)。
- **ping:**测试开发板与网络设备(如 PC、路由器)的连通性(例:ping 192.168.1.3)。
- **printenv:**打印所有环境变量(环境变量均为字符串类型,如 ipaddr=192.168.1.100)。
- **setenv:**设置环境变量(例:setenv ipaddr 192.168.1.100);若需删除变量,可执行 setenv name(将变量值置空)。
- **saveenv:**保存环境变量到存储设备(如 SD 卡、NAND Flash),确保重启后变量生效。
3.2 核心命令:TFTP 下载与内核启动
(1)配置 TFTP 相关环境变量
bash
# 设置开发板IP(与Ubuntu同网段)
setenv ipaddr 192.168.1.100
# 设置Ubuntu主机IP(TFTP/NFS服务器IP)
setenv serverip 192.168.1.3
# 保存配置
saveenv
(2)TFTP 下载内核与设备树
bash
# 下载内核zImage到内存0x80800000地址(IMX6固定地址)
tftp 0x80800000 zImage
# 下载设备树imx6.dtb到内存0x83000000地址
tftp 0x83000000 imx6.dtb
(3)启动内核
执行 bootz 命令,指定内核和设备树在内存中的地址:
bash
bootz 0x80800000 - 0x83000000
格式说明:bootz 内核地址 - 设备树地址,中间的 "-" 表示不指定 initrd 镜像。
四、bootargs 启动
4.1 完整命令配置
bootargs 是 U-Boot 传递给内核的核心参数,直接决定内核的控制台输出、根文件系统类型及挂载路径,以下是网络启动场景的经典配置(适配 IMX6 开发板):
bash
setenv bootargs console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3 ip=192.168.1.100 init=/linuxrc
参数详解:
- **console:**内核输出控制台(通过串口工具监视启动日志,ttyMXC0 为串口设备,115200 为波特率)。
- **root:**根文件系统类型(/dev/nfs 表示通过 NFS 网络挂载根文件系统)。
- **nfsroot:**NFS 服务器的 IP 及共享目录(格式为服务器 IP:共享目录路径,nfsvers=3 指定 NFS 版本)。
- **ip:**内核启动时使用的 IP 地址(需与 ipaddr 环境变量一致)。
- **init:**指定初始化进程(系统启动后运行的第一个进程,此处为 /linuxrc 脚本)。
4.2 启动完成
bootargs 启动完成后将出现以下界面,可在此输入命令行与 Ubuntu 连接:
bootargs启动完成
例如,在 Ubuntu 中新建 main.c 文件并编译后,可在 ARM 开发板上运行 a.out 程序:
ARM开发板和Ubuntu交叉开发环境
五、内核恐慌与启动失败
5.1 内核恐慌典型现象
若启动日志中出现类似信息:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0),核心原因是内核找不到或无法挂载根文件系统。
内核恐慌
5.2 排查步骤
(1)验证网络连通性
在 UBoot 命令行执行 ping 192.168.1.3(UbuntuIP),若提示 host is alive 说明网络正常;若提示 ping failed,需检查:
- 开发板与 Ubuntu 是否连接同一路由器 / 交换机;
- ipaddr 和 serverip 是否在同一网段;
- 开发板 MAC 地址(ethaddr)是否配置(部分开发板需手动设置:setenv ethaddr xx:xx:xx:xx:xx:xx)。
(2)检查 NFS 服务配置
- 验证 Ubuntu 的 NFS 共享目录权限:ls -ld /home/linux/nfs/imx6/rootfs,确保有 rwx 权限;
- 验证 NFS 配置是否生效:showmount -e 192.168.1.3,若输出包含共享目录,说明配置正常;
- 重启 NFS 服务:sudo systemctl restart nfs-kernel-server,解决服务未启动问题。
(3)检查 bootargs 参数
- 确保 nfsroot 路径与 Ubuntu 的 NFS 共享目录完全一致(注意大小写、目录层级);
- 确保 nfsvers=3 参数存在(部分内核不支持 NFSv4,指定 v3 兼容性更强);
- 重新执行 setenv bootargs [完整参数] 和 saveenv,避免参数输入错误。
六、总结
本节聚焦 Ubuntu 网络启动的全流程实操,核心收获如下:
- 掌握两种 SD 卡启动场景的差异,网络启动(TFTP+NFS)更适合驱动开发的实时调试需求;
- 完成 Ubuntu 的 TFTP/NFS 服务配置,实现内核 / 设备树快速下载和根文件系统共享;
- 熟练使用 UBoot 命令配置网络、下载镜像、启动内核,理解 bootargs 参数的核心作用;
- 学会排查内核恐慌等常见启动问题,确保启动链路畅通。