一、开发环境准备
1.1 文件准备
bash
# 1. 将内核镜像和设备树拷贝到 TFTP 服务目录
cp arch/arm/boot/zImage ~/tftpboot/
cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb ~/tftpboot/1.dtb
改成1.dtb的原因是我文件夹里面的是这个名字
# 2. 将根文件系统解压到 NFS 服务目录
cd /home/linux/nfs
(sudo) tar -xvf rootfs.tar.bz2
⚠️ 建议独立存放,避免混淆。不可将文件放于系统根目录,应使用专用目录并设置权限。
1.2 服务验证
验证 TFTP 服务:
bash
# 在主机终端登录 tftp,验证文件可正常下载
tftp <服务器IP>
get zImage # 下载文件
put xxx.dtb # 上传文件
验证 NFS 服务:
bash
# 在宿主机挂载验证
mount -t nfs <服务器IP>:/home/linux/nfs /mnt
# 验证完毕后必须卸载!否则原目录文件会被隐藏
umount /mnt
二、uboot 命令行
⚠️ 进入方式:开发板上电后,倒计时归零前按回车键,即可进入 uboot 命令行。
2.1 基础命令
| 命令 | 说明 |
|---|---|
help 或 ? |
查看所有命令列表 |
reset |
重启开发板 |
printenv |
查看所有环境变量 |
setenv ipaddr 192.168.1.122 |
设置环境变量(有值=设置) |
setenv ipaddr |
删除环境变量(无值=删除) |
saveenv |
保存环境变量到存储介质 |
ping <IP> |
网络连通性测试 |
⚠️ 所有环境变量必须执行
saveenv保存,否则重启后全部失效!
2.2 网络参数配置
bash
# 设置开发板 IP(uboot 阶段使用)
setenv ipaddr 192.168.1.122
# 设置 TFTP 服务器 IP(ubuntu 主机 IP)
setenv serverip 192.168.1.3
# 设置 MAC 地址(避免网络通信失败)
setenv ethaddr xx:xx:xx:xx:xx:xx
# 保存
saveenv
# 测试网络
ping 192.168.1.3
网络失败排查:检查 IP 是否与服务器同网段、子网掩码是否匹配。
2.3 内核与设备树下载(tftp)
bash
# 下载 zImage 到内存 0x80800000 地址处
tftp 0x80800000 zImage
# 下载设备树 dtb 到内存 0x83000000 地址处
tftp 0x83000000 1.dtb
下载过程中
#号表示数据包传输,每个#代表一个数据包,无错误提示即为成功。⚠️ 下载地址必须与 bootz 启动命令中的地址完全一致,否则内核无法正确加载。
2.4 启动内核
bash
# 启动内核(zImage地址 - ramdisk地址 dtb地址)
# 中间的 - 表示没有 ramdisk
bootz 0x80800000 - 0x83000000
2.5 设置启动参数 bootargs(重点)
bash
setenv bootargs root=/dev/nfs \
nfsroot=192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3 \
ip=192.168.1.123 \
console=ttymxc0,115200 \
init=/linuxrc
bootargs 参数详解:
| 参数 | 说明 | 示例值 |
|---|---|---|
root |
根文件系统类型和位置 | /dev/nfs(NFS类型) |
nfsroot |
NFS 文件系统的 IP + 路径 | 192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3 |
ip |
内核启动阶段使用的 IP 地址 | 192.168.1.123(与uboot中ipaddr不同!) |
console |
控制台串口设备及波特率 | ttymxc0,115200 |
init |
根文件系统挂载完成后启动的第一个进程(1号进程) | /linuxrc |
⚠️ 注意:
ip(内核IP)和 uboot 中的ipaddr(uboot IP)是两个独立参数,可以不同!
2.6 启动验证
bash
# 成功启动后终端会显示完整的 Linux 根目录结构
# 在开发板上创建文件
touch 123456
# 在宿主机 NFS 目录中验证文件是否同步生成
ls /home/linux/nfs/imx6/rootfs/
# 能看到 123456 文件,说明 NFS 文件系统同步正常 ✓
三、内核编译
3.1 准备工作
bash
# 拷贝内核源码到 ubuntu 并解压
tar -xvf linux-imx-xxx.tar.bz2 # 支持自动识别压缩格式
cd linux-imx-xxx/
推荐使用
Ctrl+Shift+T开多个终端,Alt+1/2/3/4切换,提升开发效率。
3.2 内核配置机制
内核通过 Kconfig + Makefile 两个文件协作决定编译哪些模块:
Kconfig --- 定义配置选项(菜单结构)
kconfig
# 示例 Kconfig 片段
config DEMO
bool "Demo driver"
default y
help
Enable demo driver.
Makefile --- 根据配置决定是否编译
makefile
# 示例 Makefile 片段
obj-$(CONFIG_MOD1) += mod1.o # CONFIG_MOD1=n 则不编译
obj-$(CONFIG_MOD2) += mod2.o # CONFIG_MOD2=y 则编译
.config 文件 --- 所有配置项的汇总,由工具自动生成
CONFIG_MOD1 = n
CONFIG_MOD2 = y
⚠️
.config文件由make menuconfig工具自动生成,禁止手动修改!
Kconfig 配置类型说明:
| 类型 | 含义 |
|---|---|
bool |
布尔型,只能 y(编译进内核)或 n(不编译) |
tristate |
三态,可以 y(内核)、m(模块)或 n(不编译) |
depends on |
弱依赖,依赖项不满足时此选项不显示 |
select |
强依赖,选中此项时自动选中依赖项 |
3.3 内核编译标准流程
⚠️ 所有操作均在内核源码的顶层目录下执行!
第一步:拷贝默认配置文件
bash
cp arch/arm/configs/imx6_alientek_emmc_defconfig .config
第二步:图形化配置(可选,确认配置)
bash
make menuconfig
# 配置完的结果保存在 .config 中
# 可通过 / 搜索配置项
# 退出时选择保存
第三步:编译内核镜像
bash
make zImage # 仅编译 zImage
make zImage -j20 # 多线程编译,n 代表线程数,推荐 CPU 核心数的2倍
第四步:编译设备树
bash
make dtbs # 编译所有设备树(生成 .dtb 文件)
make all # 全编译(包含 zImage + dtbs + modules)
输出文件位置:
arch/arm/boot/zImage ← 内核镜像
arch/arm/boot/dts/imx6ull-alientek-emmc.dtb ← 设备树文件
第五步:拷贝到 TFTP 目录,重启验证
bash
cp arch/arm/boot/zImage ~ /tftpboot/
cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb ~ /tftpboot/1.dtb
3.4 向内核新增文件(完整流程)
以向 drivers/char 目录下新增 demo.c 为例:
第一步:创建源文件
bash
# 在 drivers/char 目录下创建并编辑 demo.c
vim drivers/char/demo.c
第二步:修改同目录 Makefile,新增一行
makefile
# drivers/char/Makefile 中添加:
obj-$(CONFIG_DEMO) += demo.o
第三步:修改同目录 Kconfig,新增配置项
kconfig
# drivers/char/Kconfig 中添加:
config DEMO
bool "Demo driver"
default y
help
Enable demo driver.
第四步:运行 menuconfig 使能新选项
bash
make menuconfig
# 找到 DEMO 选项,选中(Y)
# 保存退出 → .config 中出现 CONFIG_DEMO=y
第五步:重新编译内核
bash
make zImage -j20
# 无需重新编译 dtb(设备树未改动)
第六步:验证
bash
# 拷贝到 TFTP 目录
cp arch/arm/boot/zImage ~/tftpboot/
# 重启开发板,内核启动日志中出现 demo 模块的打印信息即表示成功
# 如:demo: init
四、完整操作流程速查
4.1 首次启动开发板(NFS + TFTP 方式)
bash
# ===== ubuntu 主机端 =====
# 1. 准备文件
cp zImage ~/tftpboot/
cp imx6ull-alientek-emmc.dtb ~/tftpboot/
tar -xvf rootfs.tar.bz2 -C /home/linux/nfs/imx6/rootfs/
# ===== 开发板 uboot 端 =====
# 2. 设置网络(首次需要,之后 saveenv 保存了可跳过)
setenv ipaddr 192.168.1.122
setenv serverip 192.168.1.3
setenv ethaddr xx:xx:xx:xx:xx:xx
saveenv
# 3. 测试网络
ping 192.168.1.3
# 4. 下载内核和设备树
tftp 0x80800000 zImage
tftp 0x83000000 imx6ull-alientek-emmc.dtb
# 5. 设置启动参数
setenv bootargs root=/dev/nfs nfsroot=192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3 ip=192.168.1.123 console=ttymxc0,115200 init=/linuxrc
saveenv
# 6. 启动内核
bootz 0x80800000 - 0x83000000
4.2 修改内核并验证(日常开发)
bash
# 1. 修改代码 / 新增文件
# 2. 编译
make zImage -j20
# 3. 拷贝到 TFTP
cp arch/arm/boot/zImage ~/tftpboot/
# 4. 开发板 uboot 下重新下载并启动
tftp 0x80800000 zImage
bootz 0x80800000 - 0x83000000
五、关键概念速查
| 概念 | 说明 |
|---|---|
zImage |
压缩后的内核镜像,加载到 0x80800000 |
dtb |
设备树二进制文件,描述硬件信息,加载到 0x83000000 |
bootz |
uboot 启动 zImage 格式内核的命令 |
bootargs |
uboot 传给内核的启动参数字符串 |
nfsroot |
指定 NFS 根文件系统的服务器IP和路径 |
.config |
内核所有配置项的汇总文件,由 menuconfig 生成 |
Kconfig |
定义 make menuconfig 的可配置选项和菜单结构 |
make menuconfig |
图形化内核配置工具,结果保存到 .config |
defconfig |
厂商提供的默认配置文件,位于 arch/arm/configs/ |
obj-$(CONFIG_XXX) |
Makefile 中根据配置变量决定是否编译对应 .o 文件 |
-j20 |
make 多线程编译参数,20 为线程数 |