Linux 内核移植的核心工作分两层:配置层(defconfig)和硬件描述层(DTS)。配置层决定内核编译哪些功能,DTS 层告诉内核板子上的硬件长什么样。本文记录将 Linux 5.15 移植到 iMX6ULL 自制开发板的完整过程,包括一个经典的以太网驱动踩坑。
环境说明
| 项目 | 版本/型号 |
|---|---|
| 开发板 | iMX6ULL(自制,项目代号 iMXplorer) |
| Linux 内核 | 5.15.71 |
| 参考板 | NXP 官方 imx6ull-14×14-evk |
| 启动方式 | TFTP 加载内核 + NFS 根文件系统 |
后续所有自定义文件均以
imx_plorer或imx6ull-plorer命名,便于和官方文件区分。
一、为什么不直接用官方配置?
NXP 提供的 imx_v6_v7_defconfig 是一个通用配置,能跑在所有 i.MX6 系列板子上,为此开启了大量我们不需要的驱动和功能,编译慢、镜像大。
更重要的是,imx6ull-14x14-evk.dts 描述的是 NXP 官方评估板的硬件,和我们自制板子的引脚接法不完全一样。直接用官方文件,轻则部分外设无法工作,重则内核 panic。
正确做法:复制官方文件作为起点,在自己的副本上修改。
二、创建项目专属配置文件
2.1 复制 defconfig
cp arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/imx_plorer_emmc_defconfig
然后用它生成 .config:
make imx_plorer_emmc_defconfig
后续如果需要调整内核功能,执行
make menuconfig,修改后用make savedefconfig保存到imx_plorer_emmc_defconfig,下次就不用重新配置。
2.2 复制 DTS 文件
cp arch/arm/boot/dts/imx6ull-14x14-evk.dts
arch/arm/boot/dts/imx6ull-plorer-emmc.dts
2.3 注册到内核编译系统
打开 arch/arm/boot/dts/Makefile,找到 dtb-$(CONFIG_SOC_IMX6ULL) 一节,在末尾追加我们的 DTB:
dtb-$(CONFIG_SOC_IMX6ULL) +=
imx6ull-14x14-evk.dtb
... (已有条目)
imx6ull-plorer-emmc.dtb # 新增这一行
这一步不能跳过,否则 make dtbs 不会编译我们的 DTS 文件。
三、编译验证
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4 dtbs
编译完成后,确认 DTB 文件已生成:
ls arch/arm/boot/dts/imx6ull-plorer-emmc.dtb

成功生成自己的 DTB 文件。
四、U-Boot 配置:加载自定义 DTB
内核编译好了,还需要告诉 U-Boot 加载我们的 DTB,而不是官方的那个。在 U-Boot 命令行执行:
# 指定 DTB 文件名
setenv fdt_file "imx6ull-plorer-emmc.dtb"
# 设置启动命令:TFTP 加载内核镜像 + DTB,然后启动
setenv bootcmd "tftp 80800000 zImage; tftp 83000000 imx6ull-plorer-emmc.dtb; bootz 80800000 - 83000000"
# 保存环境变量
saveenv
地址说明:
0x80800000:zImage 加载地址(DDR 起始地址偏移处)0x83000000:DTB 加载地址(需与内核配置的 DTB 地址一致)bootz命令格式:bootz <kernel_addr> <initrd_addr> <dtb_addr>,无 initrd 用-占位
重启,内核成功启动:

五、踩坑:以太网驱动不工作
内核启动后,dmesg 出现网络相关报错,两个以太网口均无法正常工作。

原因分析:
iMX6ULL 使用的 PHY 芯片(LAN8720)需要一个硬件复位信号才能正常初始化。官方 EVK 板通过特定 GPIO 控制这个复位,而我们的板子用的是 GPIO5_IO07(ETH1)和 GPIO5_IO08(ETH2)。
官方 DTS 里没有声明这个复位 GPIO,所以 PHY 初始化失败。
六、修复以太网驱动:修改 DTS
在 arch/arm/boot/dts/imx6ull-plorer-emmc.dts 中添加以下内容:
/ {
model = "Freescale i.MX6 ULL 14x14 EVK Board";
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
/* 禁用与以太网复位 GPIO 冲突的 SPI4 节点 */
spi4 {
status = "disabled";
};
};
/* ETH1:追加 PHY 复位 GPIO */
&fec1 {
phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
phy-reset-duration = <200>;
};
/* ETH2:追加 PHY 复位 GPIO */
&fec2 {
phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
phy-reset-duration = <200>;
};
/* IOMUXC:为复位 GPIO 配置引脚复用 */
&iomuxc {
pinctrl_enet1: enet1grp {
fsl,pins = <
MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10b0 /* ETH1 PHY RST */
>;
};
pinctrl_enet2: enet2grp {
fsl,pins = <
MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x10b0 /* ETH2 PHY RST */
>;
};
};
关键点说明:
phy-reset-duration = <200>:复位保持时间 200ms,确保 PHY 可靠复位GPIO_ACTIVE_LOW:复位信号低有效,拉低 → 复位,拉高 → 正常工作spi4禁用:该 SPI 节点默认复用了 SNVS_TAMPER7/8 引脚,必须禁用才能让 GPIO5 控制权归以太网驱动
重新编译 DTB,烧录,以太网恢复正常。
七、NFS 启动参数说明
如果使用 NFS 作为根文件系统,bootargs 的写法需要注意 NFS 版本和协议参数:
# 完整的 NFS 启动参数
setenv bootargs "console=ttymxc0,115200
root=/dev/nfs
nfsroot=192.168.2.160:/home/zrc/nfs/rootfs,proto=tcp,nfsvers=3
rw
ip=192.168.2.8:192.168.2.160:192.168.2.1:255.255.255.0::eth0:off"
参数解析:
| 参数 | 说明 |
|---|---|
root=/dev/nfs | 告诉内核根文件系统来自 NFS |
nfsroot=IP:PATH | NFS 服务器 IP 和导出路径 |
proto=tcp,nfsvers=3 | 使用 TCP 传输 + NFSv3 协议 |
ip=板子IP:服务器IP:网关:掩码::网卡:off | 静态 IP 配置,内核启动时自动配置网络 |
如果不需要 NFS 启动,改用 eMMC 分区:
setenv bootargs "console=ttymxc0,115200 root=/dev/mmcblk1p2 rw"
总结
整个移植过程的核心操作只有三步:
- 复制官方文件 → 创建项目专属的 defconfig 和 DTS,与官方文件隔离
- 注册 DTB → 在
arch/arm/boot/dts/Makefile里添加条目,否则不会编译 - 按实际硬件修改 DTS → 本文的以太网驱动问题,根因就是 DTS 里缺少 PHY 复位 GPIO 的声明
DTS 是内核移植中最容易踩坑的地方——内核代码本身没问题,但描述硬件的”说明书”写错了,外设就跑不起来。遇到驱动不工作,优先对照原理图检查 DTS 里的 GPIO 编号和极性。
延伸阅读
完成内核移植后,可以向上梳理启动链路,也可以进入具体外设驱动适配。
- 返回嵌入式 Linux 学习路线,确认本文在完整知识结构中的位置。
- 芯片上电到 Linux 启动全流程
- RTL8189FS WiFi 驱动移植与配置




