一、Linux启动流程详解
1.1 SD卡启动流程
1.1.1 四阶段启动过程
第一阶段:i.MX6内部ROM启动
第二阶段:SD卡中的Bootloader执行
第三阶段:内核加载与启动
第四阶段:根文件系统挂载
1.1.2 详细步骤
-
系统上电执行内部ROM程序
-
i.MX6内部有96KB ROM
-
ROM中的程序根据boot mode选择启动设备(SD卡、eMMC、USB等)
-
如果选择SD卡启动,从SD卡特定位置读取Bootloader
-
-
加载Bootloader第一部分
-
拷贝SD卡中的Bootloader前半部分到i.MX6内部RAM(128KB)
-
内部RAM大小有限,Bootloader必须分阶段执行
-
Bootloader第一部分(SPL)负责初始化DDR内存
-
-
Bootloader第二阶段执行
-
Bootloader在自身前半部分初始化好DDR内存
-
将自己后半部分从SD卡搬移到DDR内存执行
-
完成完整的硬件初始化
-
-
内核加载与启动
-
Bootloader从SD卡读取内核镜像(zImage)
-
将zImage加载到内存地址0x80800000处
-
PC指针指向0x80800000,启动内核执行
-
-
挂载根文件系统
-
内核启动完成后
-
根据启动参数挂载SD卡上的根文件系统
-
进入用户空间
-
1.2 网络启动流程(TFTP+NFS)
1.2.1 网络启动环境
硬件连接:
开发板(192.168.1.100) ↔ 交换机/路由器 ↔ Ubuntu服务器(192.168.1.3)
软件服务:
TFTP服务器:提供内核镜像下载
NFS服务器:提供根文件系统共享
1.2.2 详细步骤
-
Bootloader网络初始化
-
Bootloader初始化网卡驱动
-
设置IP地址:192.168.1.100
-
设置服务器IP:192.168.1.3
-
-
TFTP下载内核
-
Bootloader通过TFTP协议从Ubuntu下载zImage
-
命令:
tftp 0x80800000 zImage -
将zImage下载到内存0x80800000地址处
-
-
TFTP下载设备树
-
下载设备树二进制文件(.dtb)
-
命令:
tftp 0x83000000 imx6.dtb -
将设备树加载到内存0x83000000地址处
-
-
启动内核
-
命令:
bootz 0x80800000 - 0x83000000 -
从0x80800000启动内核,设备树在0x83000000
-
-
NFS挂载根文件系统
-
内核通过NFS协议挂载Ubuntu上的根文件系统
-
根据bootargs参数配置NFS挂载
-
1.3 混合启动方式
1.3.1 内核在SD卡,根文件系统在NFS
优点:
- 内核启动速度快(本地加载)
- 根文件系统方便更新(网络共享)
- 适合内核稳定、根文件系统频繁修改的场景
1.3.2 内核通过网络,根文件系统在SD卡
优点:
- 内核更新方便(网络下载)
- 根文件系统稳定(本地存储)
- 适合内核频繁调试的场景
二、Ubuntu开发环境准备
2.1 TFTP服务器配置
2.1.1 安装TFTP服务
# 安装TFTP服务器
sudo apt install tftpd-hpa
# 安装TFTP客户端(用于测试)
sudo apt install tftp-hpa
2.1.2 配置TFTP服务
# 编辑配置文件
sudo vim /etc/default/tftpd-hpa
# 配置文件内容示例
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure --create"
2.1.3 创建TFTP目录
# 创建TFTP服务目录
sudo mkdir /tftpboot
# 设置目录权限
sudo chmod 777 /tftpboot
sudo chown nobody:nogroup /tftpboot
2.1.4 重启服务
# 重启TFTP服务
sudo systemctl restart tftpd-hpa
# 查看服务状态
sudo systemctl status tftpd-hpa
# 设置开机自启
sudo systemctl enable tftpd-hpa
2.1.5 放置内核文件
# 将内核镜像复制到TFTP目录
cp zImage /tftpboot/
cp imx6.dtb /tftpboot/
# 确保文件可读
chmod 644 /tftpboot/zImage
chmod 644 /tftpboot/imx6.dtb
2.2 NFS服务器配置
2.2.1 安装NFS服务
# 安装NFS服务器
sudo apt install nfs-kernel-server
# 安装NFS客户端(可选)
sudo apt install nfs-common
2.2.2 配置NFS共享
# 编辑配置文件
sudo vim /etc/exports
# 添加共享配置
/home/linux/nfs *(rw,sync,no_root_squash,no_subtree_check)
# 或者更安全的配置
/home/linux/nfs 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)
参数说明:
-
rw:读写权限 -
sync:同步写入 -
no_root_squash:信任root用户 -
no_subtree_check:不检查子目录权限 -
192.168.1.0/24:只允许指定网段访问
2.2.3 创建共享目录
# 创建NFS共享目录
mkdir -p /home/linux/nfs
# 创建根文件系统子目录
mkdir -p /home/linux/nfs/imx6/rootfs
2.2.4 解压根文件系统
# 进入NFS目录
cd /home/linux/nfs/imx6
# 解压根文件系统
sudo tar -xvf rootfs.tar.bz2 -C rootfs/
# 设置权限(如果需要)
sudo chmod 755 rootfs
2.2.5 重启NFS服务
# 重新导出共享目录
sudo exportfs -arv
# 重启NFS服务
sudo systemctl restart nfs-kernel-server
# 查看服务状态
sudo systemctl status nfs-kernel-server
# 查看共享目录
sudo showmount -e localhost
2.3 网络配置检查
2.3.1 网络连通性测试
# 检查Ubuntu IP地址
ip addr show
# 检查网络连通性(开发板ping服务器)
# 在开发板上执行:ping 192.168.1.3
# 检查服务器是否能访问开发板
ping 192.168.1.100
2.3.2 防火墙配置
# 检查防火墙状态
sudo ufw status
# 如果防火墙开启,需要开放端口
sudo ufw allow 69/tcp # TFTP
sudo ufw allow 69/udp # TFTP
sudo ufw allow 111/tcp # NFS
sudo ufw allow 2049/tcp # NFS
sudo ufw allow 2049/udp # NFS
# 或者临时关闭防火墙(开发环境)
sudo ufw disable
三、U-Boot命令详解
3.1 基础命令操作
3.1.1 帮助与信息查询
# 查看所有可用命令
help
或
?
# 查看特定命令帮助
help command_name
例:help tftp
3.1.2 重启命令
# 重启系统
reset
# 重启到不同模式
reset recovery # 恢复模式
reset fastboot # 快速启动模式
3.2 环境变量管理
3.2.1 环境变量查看
# 查看所有环境变量
printenv
或
print
# 查看特定环境变量
printenv variable_name
例:
printenv ipaddr
printenv bootargs
3.2.2 环境变量设置
# 设置环境变量
setenv name value
# 示例:
setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.3
setenv bootdelay 3
# 设置多行变量(用于bootargs)
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'
3.2.3 环境变量删除
# 删除环境变量(将值设为空)
setenv name
# 示例:
setenv old_ip
setenv unused_var
3.2.4 环境变量保存
# 保存环境变量到存储设备
saveenv
# 保存位置一般为MMC/SD卡或Flash
# 查看保存的设备
printenv boot_device
3.3 网络相关环境变量
3.3.1 必需的网络变量
# 开发板IP地址
setenv ipaddr 192.168.1.100
# 服务器IP地址(TFTP/NFS服务器)
setenv serverip 192.168.1.3
# MAC地址(硬件唯一标识)
setenv ethaddr 00:04:9f:01:02:03
# 子网掩码
setenv netmask 255.255.255.0
# 网关地址
setenv gatewayip 192.168.1.1
3.3.2 可选网络变量
# 第二个网卡MAC地址
setenv eth1addr 00:04:9f:01:02:04
# 网络设备名
setenv nvlan 1
setenv vlan 1
setenv devtype ethernet
3.4 TFTP操作命令
3.4.1 TFTP下载命令格式
# 基本格式
tftp [loadAddress] [[hostIPaddr:]bootfilename]
# 下载内核到内存
tftp 0x80800000 zImage
# 下载设备树到内存
tftp 0x83000000 imx6.dtb
# 指定服务器IP下载
tftp 0x80800000 192.168.1.3:zImage
3.4.2 TFTP下载过程
-
设置服务器IP
setenv serverip 192.168.1.3 -
设置开发板IP
setenv ipaddr 192.168.1.100 -
测试网络连接
ping 192.168.1.3 -
下载内核
tftp 0x80800000 zImage -
下载设备树
tftp 0x83000000 imx6.dtb
3.5 内核启动命令
3.5.1 启动命令格式
# 基本格式
bootz [内核地址] [initrd地址] [设备树地址]
# 常用格式(无initrd)
bootz 0x80800000 - 0x83000000
# 含义:
# 0x80800000 - 内核zImage加载地址
# - - 无initrd(ramdisk)
# 0x83000000 - 设备树加载地址
3.5.2 启动参数设置
# 设置完整的启动参数
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 - 串口控制台,波特率115200
# root=/dev/nfs - 根文件系统类型为NFS
# nfsroot=192.168.1.3:/home/linux/nfs/imx6/rootfs - NFS服务器路径
# nfsvers=3 - NFS版本3
# ip=192.168.1.100 - 开发板IP地址
# init=/linuxrc - 第一个用户空间进程
3.5.3 自动启动设置
# 设置自动启动命令
setenv bootcmd 'tftp 0x80800000 zImage; tftp 0x83000000 imx6.dtb; bootz 0x80800000 - 0x83000000'
# 保存设置
saveenv
# 测试自动启动
run bootcmd
3.6 其他实用命令
3.6.1 内存操作
# 查看内存内容
md.b 0x80800000 10 # 以字节格式查看
md.w 0x80800000 10 # 以字格式查看
md.l 0x80800000 10 # 以长字格式查看
# 修改内存内容
mw.l 0x80800000 0x12345678 1
# 内存比较
cmp 0x80800000 0x80900000 100
3.6.2 存储设备操作
# 查看MMC设备
mmc list
# 选择MMC设备
mmc dev 0 # 选择设备0
mmc dev 0 1 # 选择设备0的分区1
# 读取MMC信息
mmc info
# 从MMC读取数据
mmc read 0x80800000 0x600 0x800
四、启动参数详解
4.1 bootargs参数解析
4.1.1 控制台配置
console=ttymxc0,115200
# ttymxc0 - i.MX6的串口设备名
# 115200 - 波特率
# 其他可选值:9600, 19200, 38400, 57600, 115200
4.1.2 根文件系统配置
root=/dev/nfs
# /dev/nfs - 表示使用NFS作为根文件系统
# 其他选项:/dev/mmcblk0p2(SD卡分区), /dev/mtdblock2(Flash)
4.1.3 NFS配置
nfsroot=192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3
# 192.168.1.3 - NFS服务器IP
# /home/linux/nfs/imx6/rootfs - 共享目录路径
# nfsvers=3 - NFS协议版本
4.1.4 网络配置
ip=192.168.1.100
# 开发板IP地址
# 完整格式:ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
4.1.5 Init进程配置
init=/linuxrc
# /linuxrc - 第一个用户空间进程
# 通常是/bin/init或/sbin/init的符号链接
4.2 其他常用参数
4.2.1 内存参数
mem=512M
# 指定内存大小
# 当系统内存检测不正确时使用
4.2.2 调试参数
debug
# 启用内核调试信息
loglevel=8
# 设置日志级别(0-8,8最详细)
earlyprintk
# 早期控制台输出,用于调试启动问题
4.2.3 文件系统参数
rw
# 以读写方式挂载根文件系统
noinitrd
# 不使用initrd(ramdisk)
五、故障排查指南
5.1 常见问题与解决方案
5.1.1 TFTP下载失败
问题:tftp命令执行后没有反应或超时
解决:
1. 检查网络连接:ping 192.168.1.3
2. 检查TFTP服务状态:sudo systemctl status tftpd-hpa
3. 检查文件权限:确保/tftpboot/zImage可读
4. 检查防火墙:sudo ufw status
5.1.2 NFS挂载失败
问题:内核启动后卡在NFS挂载
解决:
1. 检查NFS服务:sudo showmount -e localhost
2. 检查exports配置:sudo cat /etc/exports
3. 检查目录权限:确保共享目录存在且可访问
4. 检查网络配置:ip addr show
5.1.3 内核启动失败
问题:bootz命令后系统无响应
解决:
1. 检查内核地址:确保与加载地址一致
2. 检查设备树地址:确保正确加载
3. 检查串口输出:查看错误信息
4. 检查内存配置:确保足够内存
5.1.4 环境变量丢失
问题:重启后环境变量恢复默认
解决:
1. 确保执行saveenv保存
2. 检查存储设备:printenv boot_device
3. 检查存储空间:确保有足够空间