干什么
尝试根据正点原子提供的教程将6.1版本的 Linux Kernal 移植到开发板上。
怎么干
NXP 官方开发板 Linux 内核编译
NXP 提供的 Linux 源码肯定是可以在自己的 I.MX6ULL EVK 开发板上运行下去的,所以我们肯定是以 I.MX6ULL EVK 开发板为参考,然后将 Linux 内核移植到 I.MX6U-ALPHA 开发板上的。
在顶层 Makefile 中合适的地方添加如下语句:
CROSS_COMPILE = /home/hcw/toolchain/gcc-arm-11.2-2022.02-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-
ARCH = arm
在终端中输入如下命令
make clean
make imx_v6_v7_defconfig
make -j16
Linux 内核编译完成以后会在 arch/arm/boot 目录下生成 zImage 镜像文件,如果使用设备树 的话还会在 arch/arm/boot/dts 目录下开发板对应的.dtb(设备树)文件,比如 imx6ull-14x14-evk.dtb 就是 NXP 官方的 I.MX6ULL EVK 开发板对应的设备树文件。
如何将编译好的 linux 的镜像传到开发板中呢,我们在虚拟机上搭建tftp服务器即可,具体操作百度教程。
搭建好服务器后,我们将编译好的镜像和设备树复制到服务器传输目录,输入如下命令
sudo cp arch/arm/boot/zImage /srv/tftp/ -f
sudo cp arch/arm/boot/dts/imx6ull-14x14-evk.dtb /srv/tftp/ -f
紧接着,串口连接开发板,输入以下命令
tftp 80800000 zImage
tftp 83000000 imx6ull-14x14-evk.dtb
bootz 80800000 - 83000000
出现如下界面就算进入成功了:

在 Linux 中添加自己的开发板
添加默认配置文件
将arch/arm/configs 目录下的 imx_v6_ v7_defconfig 重新复制一份,命名为 imx_hcw_e mmc_defconfig,命令如下
cd arch/arm/configs
cp imx_v6_v7_defconfig imx_hcw_emmc_defconfig
打开imx_hcw_emmc_defconfig 文件,找到“CONFIG_ARCH_MULTI_V6=y”这一行, 将其屏蔽掉。i.MX6ULL 是 ARMv7-A,只启用 v7 可以避免 v6 平台的旧兼容代码被选入,从而减少 Kconfig 冲突和模块 ABI 差异风险。以后 imx_alientek_emmc_defconfig 就是正点原子的 EMMC 版开发板默认配置文件了。运行make imx_hcw_emmc_defconfig。
添加开发板对应的设备树文件
EMMC 版开发板的设备树文件,进入目录 arch/arm/boot/dts 中,复制一 份 imx6ull-14x14-evk.dts,然后将其重命名为 imx6ull-alientek-emmc.dts,命令如下:
cd arch/arm/boot/dts
cp imx6ull-14x14-evk.dts imx6ull-hcw-emmc.dts
dts 是设备树源码文件,编译 Linux 的时候会将其编译为.dtb 文件。imx6ull-alientek-emmc.dts 创建好以后我们还需要修改文件 arch/arm/boot/dts/Makefile,找到“dtb-$(CONFIG_SOC_IM X6ULL)”配置项,在此配置项中加入“imx6ull-alientek-emmc.dtb” ,如下所示:
1 | dtb-$(CONFIG_SOC_IMX6UL) += \ |
编译尝试
可以创建如下编译脚本
1 | make distclean |
编译完成后,将镜像文件和设备树文件复制到 tftp 文件夹,在开发板上通过网络下载后启动。

CPU 主频
进入到目录/sys/bus/cpu/devices/cpu0/cpufreq 中,此目录下会有很多文件,如图 3 所示:

cpuinfo_cur_freg:当前cpu工作频率,从CPU寄存器读取到的工作频率。
cpuinfo_max_freq:处理器所能运行的最高工作频率(单位:KHz)。
cpuinfo_min_freg:处理器所能运行的最低工作频率(单位:KHz)。
cpuinfo_transition_latency:处理器切换频率所需要的时间(单位:ns)。
scaling_available_frequencies:处理器支持的主频率列表(单位:KHz)。
scaling_available_governors:当前内核中支持的所有goveror(调频)类型。
scaling_cur_freg:保存着cpufreq模块缓存的当前CPU频率,不会对CPU硬件寄存器进行检查。
scaling_driver:该文件保存当前CPU所使用的调频驱动。
scaling_governor:governor(调频)策略,Linux内核一共有5中调频策略:
1、Performance,最高性能,直接用最高频率,不考虑耗电。
2、Interactive,一开始直接用最高频率,然后根据CPU负载慢慢降低。
、Powersave,省电模式,通常以最低频率运行,系统性能会受影响,一般不会用这个!
4、Userspace,可以在用户空间手动调节频率。
5、Ondemand,定时检查负载,然后根据负载来调节频率。负载低的时候降低CPU频率,这样省电,负载高的时候提高CPU频率,增加性能。
scaling_max_freq:governor(调频)可以调节的最高频率。
cpuinfo_min_freg:governor(调频)可以调节的最低频率。
stats目录下给出了CPU各种运行频率的统计情况,比如CPU在各频率下的运行时间以及变频次数。

可以看出,当前CPU支持198MHz、396MHz、528Mhz和792MHz四种频率切换,其中调频策略为ondemand,也就是定期检查负载,然后根据负载情况调节CPU频率。因为当前我们开发板并没有做什么工作,因此CPU频率降低为198MHz以省电。如果开发板做一些高负载的工作,比如播放视频等操作那么CPU频率就会提升上去。查看stats目录下的time instate文件可以看到CPU在各频率下的工作时间,命令如下:
cat /sys/bus/cpu/devices/cpu0/cpufreq/stats/time_in_state

在 menuconfig 中可以对 CPU 运行策略进行调整,运行 make menuconfig 命令打开图形化配置,进入如下路径
CPU Power Management
-> CPU Frequency scaling
-> Default CPUFreq governor
然后就可以选择你想要用的电源策略了。
EMMC驱动修改
接下来我们修改 EMMC 驱动,正点原子 EMMC 版本核心板上的EMMC采用8位数据线:

Linux 内核驱动里面 EMMC 默认是 4 线模式的,4 线模式肯定没有 8 线模式的速度快,所 以本节我们将 EMMC 的驱动修改为 8 线模式。修改方法很简单,直接修改设备树即可,打开文件 imx6ull-hcw-emmc.dts,发现其引用了 imx6ul-14x14-evk.dtsi 和 imx6ull.dtsi 两个文件。根据之前移植 U-Boot的经验,我们复制一份 imx6ul-14x14-evk.dtsi 并将其重命名为 imx6ull-hcw-emmc.dtsi,将 imx6ull-hcw-emmc.dts 文件中的路径改掉。然后打开 imx6ull-hcw-emmc.dtsi,在引脚组中添加以下内容
1 | pinctrl_usdhc2_8bit: usdhc2grp8bit { |
将 usdhc2 的配置改为以下代码
1 | &usdhc2 { |
这里说明物理引脚的复用也切换到了8bit。最后是关闭 1.8V 驱动 emmc 的选项。
网卡驱动修改(这次已失败)
有了 UBoot 移植的经验,直接操作即可
①、在引脚组中添加以下代码
1 | pinctrl_enet1_reset: enet1resetgrp { |
②、修改 fec1 和 fec2 节点的 pinctrl-0 属性
先添加 ENET1 网络复位引脚所使用的 IO 为 GPIO5_IO07,低电平有效。复位低电平信号持续时间为 200ms;ENET2 网络复位引脚所使用的 IO 为 GPIO5_IO08,同样低电平有效,持续时间同样为 200ms。smsc,disable-energy-detect 是 SMSC/Microchip PHY 的一个可选特性配置,用于关闭能量检测功能,不参与驱动匹配。修改后的代码如下所示
1 | &fec1 { |
③、修改 fec_main.c 文件(这是临时验证手段,不推荐长期保留,正确方式应使用设备树 reset 时序。)
要在I.MX6ULL 上使用 SR8201F,需要修改一下 Linux 内核源码,打开 drivers/net/ethernet/freescale/fec_main.c,找到函数 fec_reset_phy,在 fec_reset_phy 函数的最后中加入如下代码:
msleep(200);
测试与修复
修改好设备树和 Linux 内核以后重新编译一下,得到新的 zImage 镜像文件和 imx6ull-alien tek-emmc.dtb 设备树文件。由图可知EMMC识别成功

但是输入 ifconfig -a 后,eth0显示网卡连接失败,我们来排查问题。
输入命令 dmesg | grep -E “fec|ethernet|phy|mdio” 查看日志
1 | root@ATK-IMX6U:~# dmesg | grep -E "fec|ethernet|phy|mdio" |
可以看出 phy-reset-gpios 这根 GPIO 已经被别人占用了,FEC 驱动想申请它时失败。-16 在 Linux 里基本就是 EBUSY(资源忙 / 已被占用)。于是 FEC 驱动 probe 失败 → eth0 后面要么不出现,要么出现又立刻废掉。找到使用了gpio5 7/8 引脚的代码并删除。
再次编译 烧录,继续查看日志
1 | root@ATK-IMX6U:~# dmesg | grep -E "fec|ethernet|phy|mdio" |
可以看出 gpio 占用的问题已经解决。第五行表明只有一个phy设备,地址为1,另一个未找到。第 8 行说明已经跑通了。接下来我们设置 ip 地址,将其和电脑处于同一网段下,成功ping通!

最终的网口配置代码如下
1 | &fec1 { |
结语
通过本次移植,我认识到了 Linux 内核的启动流程和设备初始化方式,同时学习了一些常用的日志查看命令与分析方法。