真真没啥技术的我学Linux驱动 | U-boot移植

在这之前我们写了个玩具级别的bootloader实现了内核引导与启动,这说明BootLoader的底层逻辑并不神秘。

玩具终究是玩具。它没有命令行的调试能力,不支持网络加载,兼容性也不好......现在让我们走进真正的bootloader的世界。

什么是U-boot?

bootloader千千万万,可不止就只有个U-boot,除此之外还有BareboxCorebootLK等等。只不过U-boot支持架构多,社区活跃,用的最多,比较流行而已。作为bootloader,简单来说U-boot就是嵌入式系统的“BIOS + 引导器”。
同样也离不开三件核心工作:

  1. 初始化硬件 —— 初始化 时钟、串口、DDR 、存储设备,让板子“活过来”。
  2. 加载内核 —— 从 Flash、SD 卡或网络把 Linux 内核读进内存。
  3. 启动内核 —— 告诉内核内存大小、根文件系统位置等信息,跳转到内核入口,把控制权交给操作系统。

但这还不是它的全部。U-Boot 本质上是一个极其复杂的裸机程序。它引入了设备树(Device Tree)来实现硬件解耦,支持 Kconfig 菜单化配置,还提供了一套类似 shell 的交互命令(md、mw、tftp 等),让底层调试变得异常优雅。

本篇属于第二部分

第二部分 我只是个搬运工之 BootLoader

U-boot移植

既然移植,那么暂时不需要抽丝剥茧的去看uboot的细节,一切以能跑起来能用为目的。、

一般U-boot移植的源码来源,通常分为3种:

  • 主线版本(Mainline): 纯净但高冷,需要自己添加芯片soc以及相关外设,需要对整个芯片架构了如指掌,难度很大。。

  • 芯片原厂版本(NXP/ST 等): soc相关内容已被添加,并且支持官方评估板。只需要根据自己的需求,修改部分设备树和外设源码即可。

  • 板卡厂商版本(正点原子/讯为等): 开箱即用,适合直接开发应用。

本篇要介绍正是常用的第二种,基于 NXP 官方源码进行移植,移植的核心逻辑是

  1. 确定自己板子与源码支持的硬件差异。
  2. 根据差异,修改设备树或外设代码,进行适配。
  3. 对应条件配置到defconfig中,编译下载。

NXP的系列芯片源码,都可以github上找到,U-boot地址如下

git clone https://github.com/nxp-imx/uboot-imx.git

我用的版本是nxp-imx/uboot-imx:lf_v2025.04
除了可以通过上述git clone下载外也可以下载指定分支

# 下载指定分支
wget https://codeload.github.com/nxp-imx/uboot-imx/zip/refs/heads/lf_v2025.04
# 解压
unzip lf_v2025.04
cd uboot-imx-lf_v2025.04

先初次编译一下保证源码没问题,U-boot通过Kconfig来配置管理,使用Makefile来进行编译。在U-boot/configs/ 有配置好的配置文件

  • mx6ull_14x14_evk_nand_defconfig
  • mx6ull_14x14_evk_emmc_defconfig
    两种配置文件,分布对应不同的存储emmc和nand flash。可以使用如下命令进行开始界面的修改(以emmc版本为例)。
# 彻彻底清理目录。
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-   distclean
# 使用menuconfig生成U-Boot主目录下的.config配置文件。
# 编译时Makefile文件会将配置文件.config导入,从而启动或关闭对应配置项。
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-   mx6ull_14x14_evk_emmc_defconfig
# 使用命令make进行U-Boot的编译,如果编译成功,可以看到生成了u-boot一系列文件。
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-   -j8

编译完成后目录下的u-boot-dtb.imx即为编译后的可执行文件。

uboot首次编译成功
生成出来的文件这些是我们需要知道的。

u-boot.bin 是 U-Boot 的主要可执行文件。
u-boot.dtb 是描述硬件信息的设备树编译后的文件。
u-boot-dtb.bin 是包含了 U-Boot 和设备树的合并二进制文件。
u-boot-dtb.imx 是为 NXP i.MX 系列处理器生成的特定格式的启动镜像,包含了头部IVT DCD信息。

因为用的不是官方板子,
https://www.nxp.com.cn/design/design-center/development-boards-and-designs/i-mx-evaluation-and-development-boards/evaluation-kit-for-the-i-mx-6ull-and-6ulz-applications-processor:MCIMX6ULL-EVK
而是自己的板子,直接下载板子是无法正常工作的,可以看到除了串口打印正常,还有网络,lcd显示等都是有问题的。但说明U-boot整个的编译链路是跑通的,接下来就是一系列的移植工作。

uboot首次编译文件下载到开发板

为了防止移植过程中,没有记录或污染源码。先创建个属于自己的分支xoreaxeaxeax用来进行修改和管理。

git checkout -b xoreaxeaxeax

寻找参考板的逻辑:我们的 SoC 是 I.MX.6ULL,去 arch/arm/mach-imx/ 下看支持哪些型号,再去 board/freescale/ 下找对应的评估板。mx6ullevk 就是 I.MX.6UL 评估板,所以,选择这个作为移植的原始文件。

arch/arm/           # ARM 架构相关代码
  ├── cpu/          # 各 CPU 子目录(armv7、armv8...)
  ├── dts/          # 设备树文件存放处
  └── mach-imx/     # NXP i.MX 系列 SoC 支持代码
board/              # 具体开发板代码
  └── freescale/    # NXP 官方板
configs/            # 预设配置文件(defconfig)
include/configs/    # 板级头文件(旧式配置方式)
tools/logo          # logo图片显示

移植工作正式开始

添加mx6ull_alpha_emmc_defconfig配置文件

# 新建配置文件
cd configs
cp mx6ull_14x14_evk_emmc_defconfig  mx6ull_alpha_emmc_defconfig

mx6ull_alpha_emmc_defconfig配置文件描述

# 修改目标名称用于编译时候条件编译Kconfig
- CONFIG_TARGET_MX6ULL_14X14_EVK=y
+ CONFIG_TARGET_MX6ULL_ALPHA_EMMC=y

# 指定设备树文件名
- CONFIG_DEFAULT_DEVICE_TREE="imx6ull-14x14-evk-emmc" 
+ CONFIG_DEFAULT_DEVICE_TREE="imx6ull-alpha-emmc"

# 增加设备树配置信息,用于环境变量CFG_EXTRA_ENV_SETTINGSmx6ull_alpha_emmc.h里fdt赋值
+ CONFIG_DEFAULT_FDT_FILE="imx6ull-14x14-emmc-7-1024x600-c.dtb"

# 官方板子用的phy是KSZ8081,而正点原子是LAN8720,需要加载对应驱动。
- CONFIG_PHY_MICREL_KSZ8XXX=y
+ CONFIG_PHY_SMSC=y

这个CONFIG_DEFAULT_DEVICE_TREE就会被作为一个prefix,用来被Makefile引用构成一个完整的设备树文件名称,imx6ull-alpha-emmc要跟后面设备树名称统一起来。

	${CONFIG_DEFAULT_DEVICE_TREE}.dts

头文件include/configs/mx6ull_alpha_emmc.h

# board相关的头文件
cp include/configs/mx6ullevk.h  include/configs/mx6ull_alpha_emmc.h
-#ifndef __MX6ULLEVK_CONFIG_H
-#define __MX6ULLEVK_CONFIG_H
+#ifndef __MX6ULL_ALPHA_EMMC_CONFIG_H
+#define __MX6ULL_ALPHA_EMMC_CONFIG_H  

#define CFG_EXTRA_ENV_SETTINGS \
	CFG_MFG_ENV_SETTINGS \
	TEE_ENV \
	"script=boot.scr\0" \
	"image=zImage\0" \
	"console=ttymxc0\0" \
	"fdt_high=0xffffffff\0" \
	"initrd_high=0xffffffff\0" \
-	"fdt_file=undefined\0" \
+	"fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \
	"fdt_addr=0x83000000\0" \
	"tee_addr=0x84000000\0" \
	"tee_file=undefined\0" \
	"boot_fdt=try\0" \
	"ip_dyn=yes\0" \

boards相关文件

文件名 作用与含义
Kconfig 配置菜单文件。与当前开发板相关的Kconfig配置项。主要用于在make menuconfig等图形化配置界面中,控制是否显示或选择“mx6ull_evk”这个板型选项。
MAINTAINERS 维护者信息文件。记录了负责维护此开发板相关代码的维护者姓名和电子邮件地址。它通常还简要列出了与此板子相关的文件路径(如板级目录、头文件、配置文件)。
Makefile 编译脚本。告诉U-Boot的构建系统需要编译哪些文件来生成此开发板的二进制文件。核心内容是obj-y := mx6ullevk.o,这指示编译系统将mx6ullevk.c编译并链接进来。如果板子需要其他特定的驱动或初始化文件,也会在这里添加。
imximage.cfg 镜像配置文件。用于配置i.MX系列处理器特有启动参数的配置文件。在U-Boot编译的最终阶段,mkimage工具会读取此文件,并将其中的配置信息(如DDR初始化、时钟设置、镜像头信息等)添加到最终的u-boot.imx文件中。这是生成NXP芯片可启动镜像的关键文件。
imximage_lpddr2.cfg.cfg LPDDR2专用镜像配置文件。该文件是imximage.cfg的变体,专门用于配置LPDDR2类型的内存。当开发板使用LPDDR2内存时,会使用此文件替换通用配置文件,以提供不同的DDR初始化时序和参数
mx6ullevk.c 板级主文件。这是该目录下最核心的板级初始化文件。它包含了板子特定的硬件初始化代码,例如:
GPIO配置:初始化LCD背光、网络复位引脚等
plugin.S 插件文件。这是一个可选的、在U-Boot SPL(Secondary Program Loader)阶段之前或期间运行的小型代码片段(插件)。它主要用于实现更复杂的DDR初始化流程,但并非所有板子都必须使用。
mkdir board/freescale/mx6ull_alpha_emmc
cp board/freescale/mx6ullevk/*   board/freescale/mx6ull_alhpa_emmc/* 

mv mx6ullevk.c mx6ull_alpha_emmc.c

mx6ull_alpha_emmc.c修改。lcd没有单独复位引脚,代码需要屏蔽并且需要打印自己的板子信息。

static int setup_lcd(void)
{
	enable_lcdif_clock(LCDIF1_BASE_ADDR, 1);

	imx_iomux_v3_setup_multiple_pads(lcd_pads, ARRAY_SIZE(lcd_pads));
+#if 0  /* 添加条件编译去掉复位*/
    /* Reset the LCD */
	gpio_request(IMX_GPIO_NR(5, 9), "lcd reset");
	gpio_direction_output(IMX_GPIO_NR(5, 9) , 0);
	udelay(500);
	gpio_direction_output(IMX_GPIO_NR(5, 9) , 1);
+#endif 
	/* Set Brightness to high */
	gpio_request(IMX_GPIO_NR(1, 8), "backlight");
	gpio_direction_output(IMX_GPIO_NR(1, 8) , 1);

	return 0;
}

int checkboard(void)
{
	if (is_mx6ull_9x9_evk())
		puts("Board: MX6ULL 9x9 EVK\n");
	else if (is_cpu_type(MXC_CPU_MX6ULZ))
		puts("Board: MX6ULZ 14x14 EVK\n");
	else
        /* 修改容打印 */
-		puts("Board: MX6ULL 14x14 EVK\n");
+ 		puts("Board: MX6ULL Alpha Board \n");
	return 0;
}

imximage_lpddr2.cfg,修改路径。

#ifdef CONFIG_USE_IMXIMG_PLUGIN
/*PLUGIN    plugin-binary-file    IRAM_FREE_START_ADDR*/
- PLUGIN	board/freescale/mx6ullevk/plugin.bin 0x00907000
+ PLUGIN	board/freescale/mx6ull_alpha_emmc/plugin.bin 0x00907000
#else

#ifdef CONFIG_IMX_HAB
CSF CONFIG_CSF_SIZE
#endif

imximage.cfg,修改路径。

#ifdef CONFIG_USE_IMXIMG_PLUGIN
/*PLUGIN    plugin-binary-file    IRAM_FREE_START_ADDR*/
- PLUGIN	board/freescale/mx6ullevk/plugin.bin 0x00907000
+ PLUGIN	board/freescale/mx6ull_alpha_emmc/plugin.bin 0x00907000
#else

#ifdef CONFIG_IMX_HAB
CSF CONFIG_CSF_SIZE
#endif

Makefile,添加c文件。

# SPDX-License-Identifier: GPL-2.0+
# (C) Copyright 2016 Freescale Semiconductor, Inc.

- obj-y  := mx6ullevk.o
+ obj-y  := mx6ull_alpha_emmc.o

MAINTAINERS

- MX6ULLEVK BOARD
+ MX6ULL_ALPHA_EMMC  BOARD
M:	Peng Fan <peng.fan@nxp.com>
S:	Maintained
- F:board/freescale/mx6ull_alpha_emmc/
+ F:board/freescale/mx6ullevk/
- F:include/configs/mx6ullevk.h
+ F:include/configs/mx6ull_alpha_emmc.h
- F:configs/mx6ull_14x14_evk_defconfig
- F:configs/mx6ull_14x14_evk_plugin_defconfig
- F:configs/mx6ulz_14x14_evk_defconfig

Kconfig, U-Boot 的make会先判断TARGET_MX6ULL_ALPHA_EMMC是否成立(这一步其实在前面mx6ull_alpha_emmc_defconfig文件里面中已经被设置为y了)。它会利用使用下面定义进行拼接,以 SYS_BOARD 和 SYS_VENDOR 为例会拼接出板级目录的完整路径。

board/$(SYS_VENDOR)/$(SYS_BOARD)/...

这样配置后,后续的编译就能自动找到我们添加的文件。

- if TARGET_MX6ULL_14X14_EVK || TARGET_MX6ULL_9X9_EVK
+ if TARGET_MX6ULL_ALPHA_EMMC
config SYS_BOARD
-	default "mx6ullevk"
+	default "mx6ull_alpha_emmc"
config SYS_VENDOR
	default "freescale"

config SYS_CONFIG_NAME
-	default "mx6ullevk"
+	default "mx6ull_alpha_emmc"
config IMX_CONFIG
-	default "board/freescale/mx6ullevk/imximage.cfg"
+	default "board/freescale/mx6ull_alpha_emmc/imximage.cfg"

config TEXT_BASE
	default 0x87800000
endif

plugin.S文件不需要修改 (CONFIG_USE_IMXIMG_PLUGIN is not set)

将Board文件导入到U-Boot源码中,修改文件arch/arm/mach-imx/mx6/Kconfig,将新的Board配置信息导入,可以在界面make menuconfig时界面可以选择。

config TARGET_MX6ULL_14X14_EVK
	bool "Support mx6ull_14x14_evk"
	depends on MX6ULL
	select BOARD_LATE_INIT
	select DM
	select DM_THERMAL
	select IOMUX_LPSR
	select IMX_MODULE_FUSE
	select OF_SYSTEM_SETUP
	imply CMD_DM

+config TARGET_MX6ULL_ALPHA_EMMC
+	bool "Support mx6ull_alpha_emmc"
+	depends on MX6ULL
+	select BOARD_LATE_INIT
+	select DM
+	select DM_THERMAL
+	select IOMUX_LPSR
+	select IMX_MODULE_FUSE
+	select OF_SYSTEM_SETUP
+	imply CMD_DM

config TARGET_MX6ULZ_SMM_M2
	bool "Support imx6ulz_smm_m2"
	depends on MX6ULL
	select DM
	select DM_GPIO
	select DM_I2C
	select DM_SERIAL
	select DM_MTD
	select DM_THERMAL
	select SUPPORT_SPL
	imply OF_UPSTREAM

......

source "board/freescale/mx6ullevk/Kconfig"
+ #将增加的配置导入到menuconfig中
+source "board/freescale/mx6ull_alpha_emmc/Kconfig"
source "board/bosch/acc/Kconfig"

设备树

UBoot跟Linux一样,所有的设备树全部放到了我们的arch/arm/dts文件夹下,先观察设备树原始内容,发现imx6ull-14x14-evk-emmc.dts内容如下

/*
 * Copyright 2019 NXP
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 */

#include "imx6ull-14x14-evk.dts"

&usdhc2 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc2_8bit>;
	pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
	pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
	bus-width = <8>;
	non-removable;
	status = "okay";
};

imx6ull-14x14-evk.dts内容如下

// SPDX-License-Identifier: (GPL-2.0 OR MIT)
//
// Copyright (C) 2016 Freescale Semiconductor, Inc.

/dts-v1/;

#include "imx6ull.dtsi"
#include "imx6ul-14x14-evk.dtsi"
#include "imx6ul-14x14-evk-u-boot.dtsi"

/ {
	model = "i.MX6 ULL 14x14 EVK Board";
	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
};

&clks {
	assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>,
			  <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
	assigned-clock-rates = <320000000>, <786432000>;
};

&csi {
	status = "okay";
};

&ov5640 {
	status = "okay";
};

/delete-node/ &sim2;

imx6ull-14x14-evk-u-boot.dtsi

// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2022-2023 NXP
 */

&{/aliases} {
	spi0 = &qspi;
	spi1 = &ecspi1;
	spi2 = &ecspi2;
	spi3 = &ecspi3;
	spi4 = &ecspi4;
};

&pinctrl_uart1 {
	bootph-all;
};

&rngb {
	bootph-all;
};

imx6ul-14x14-evk-u-boot.dtsi

// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2018, 2023 NXP
 */

&{/aliases} {
	bootph-all;
	display0 = &lcdif;

	spi0 = &qspi;
	spi1 = &ecspi1;
	spi2 = &ecspi2;
	spi3 = &ecspi3;
	spi4 = &ecspi4;
};

&soc {
	bootph-all;
};

&aips2 {
	bootph-all;
};

&iomuxc {
	bootph-all;
};

设备树一层层递进,那直接展开从源头进行处理

imx6ull-14x14-evk-emmc.dts
	|-imx6ull-14x14-evk.dts
		|-#include "imx6ull.dtsi"
		|-#include "imx6ul-14x14-evk.dtsi"
		|-#include "imx6ul-14x14-evk-u-boot.dtsi"

cp imx6ul-14x14-evk-u-boot.dtsi        imx6ull-alpha-emmc-u-boot.dtsi
cp imx6ull-14x14-evk.dts  		   	 imx6ull-alpha-emmc.dts
cp imx6ul-14x14-evk.dtsi            imx6ull-alpha-emmc.dtsi

修改设备树,imx6ull-alpha-emmc.dts文件,根据复制的文件对应修改包含文件,因为imx6ull-14x14-evk-emmc.dts通过include导入#include "imx6ull-14x14-evk.dts"。因此,这里直接合并两个文件并修改include导入文件名和内容。

// SPDX-License-Identifier: (GPL-2.0 OR MIT)
//
// Copyright (C) 2016 Freescale Semiconductor, Inc.

/dts-v1/;

#include "imx6ull.dtsi"
- #include "imx6ul-14x14-evk.dtsi"
- #include "imx6ul-14x14-evk-u-boot.dtsi"
+ #include "imx6ull-alpha-emmc.dtsi"
+ #include "imx6ull-alpha-emmc-u-boot.dtsi"

/ {
-	model = "i.MX6 ULL 14x14 EVK Board";
-	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
+	model = "i.MX6 ULL Alpha Board";
+	compatible =  "fsl,imx6ull";
};

&clks {
	assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>,
			  <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
	assigned-clock-rates = <320000000>, <786432000>;
};

&csi {
	status = "okay";
};

&ov5640 {
	status = "okay";
};


+ &usdhc2 {
+ 	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+  	pinctrl-0 = <&pinctrl_usdhc2_8bit>;
+ 	pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
+ 	pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
+ 	bus-width = <8>;
+ 	non-removable;
+ 	status = "okay";
+ };

/delete-node/ &sim2;

imx6ull-alpha-emmc-u-boot.dtsi 合并imx6ul-14x14-evk-u-boot.dtsi和imx6ull-14x14-evk-u-boot.dtsi内容。另外,因为现在采用设备树进行驱动加载,串口的初始化会滞后一些,为了提前打印日志,这里添加串口uart1配置。

// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2018, 2023 NXP
 */

&{/aliases} {
	bootph-all;
	display0 = &lcdif;

	spi0 = &qspi;
	spi1 = &ecspi1;
	spi2 = &ecspi2;
	spi3 = &ecspi3;
	spi4 = &ecspi4;
};

&soc {
	bootph-all;
};

&aips2 {
	bootph-all;
};

&iomuxc {
	bootph-all;
};


+ &uart1 {
+	bootph-all;
+ };

+ &pinctrl_uart1 {
+	bootph-all;
+ };


imx6ull-alpha-emmc.dtsi重点修改

(1)、LCD我们屏参数跟官方不一样,要根据屏的参数进行对应修改。

	display0: display@0 {
		bits-per-pixel = <24>;
		bus-width = <24>;

		display-timings {
			native-mode = <&timing0>;

			timing0: timing0 {
-				clock-frequency = <9200000>;
-				hactive = <480>;
-				vactive = <272>;
-				hfront-porch = <8>;
-				hback-porch = <4>;
-				hsync-len = <41>;
-				vback-porch = <2>;
-				vfront-porch = <4>;
-				vsync-len = <10>;
+				clock-frequency = <51200000>;
+				hactive = <1024>;
+				vactive = <600>;
+				hfront-porch = <160>;
+				hback-porch = <140>;
+				hsync-len = <20>;
+				vback-porch = <20>;
+				vfront-porch = <12>;
+				vsync-len = <3>;

				hsync-active = <0>;
				vsync-active = <0>;
				de-active = <1>;
				pixelclk-active = <0>;
			};
		};
	};
};

(2)、存储部分SDCard不需要复位和选择引脚。

	pinctrl_usdhc1: usdhc1grp {
		fsl,pins = <
			MX6UL_PAD_SD1_CMD__USDHC1_CMD     	0x17059
			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x10071
			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 	0x17059
			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 	0x17059
			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 	0x17059
			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 	0x17059
			MX6UL_PAD_UART1_RTS_B__GPIO1_IO19       0x17059 /* SD1 CD */
-			MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT    0x17059 /* SD1 VSELECT */
+		//	MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT    0x17059 /* SD1 VSELECT */
-			MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 /* SD1 RESET */
+		//	MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 /* SD1 RESET */
		>;
	};

(3)、网络修改,添加pin-ctrl信息、复位引脚时间、mac地址,还有LAN8720对应驱动属性匹配字符、phy芯片地址。

&fec1 {
	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet1>;
+	pinctrl-0 = <&pinctrl_enet1
+				&pinctrl_enet1_reset>;
	phy-mode = "rmii";
	phy-handle = <&ethphy0>;
	phy-supply = <&reg_peri_3v3>;
+	phy-reset-gpios	= <&gpio5 7 GPIO_ACTIVE_LOW>;
+	phy-reset-duration = <200>;
+	phy-reset-post-delay = <200>;
+	local-mac-address = [00 04 9f 04 d2 35];
	status = "okay";
};

&fec2 {
	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet2>;
+   pinctrl-0 = <&pinctrl_enet2
+				&pinctrl_enet2_reset>;
	phy-mode = "rmii";
	phy-handle = <&ethphy1>;
	phy-supply = <&reg_peri_3v3>;
+	phy-reset-gpios	= <&gpio5 8 GPIO_ACTIVE_LOW>;
+	phy-reset-duration = <200>;
+	phy-reset-post-delay = <200>;
+	local-mac-address = [00 04 9f 04 d2 36];
	status = "okay";

	mdio {
		#address-cells = <1>;
		#size-cells = <0>;
			
-		ethphy0: ethernet-phy@2 {
+		ethphy0: ethernet-phy@0 {
-			compatible = "ethernet-phy-id0022.1560";
+			compatible = "ethernet-phy-id0007.c0f0", "ethernet-phy-ieee802.3-c22";
-			reg = <2>;
+			reg = <0>;
			micrel,led-mode = <1>;
			clocks = <&clks IMX6UL_CLK_ENET_REF>;
			clock-names = "rmii-ref";

		};

		ethphy1: ethernet-phy@1 {
-			compatible = "ethernet-phy-id0022.1560";
+			compatible = "ethernet-phy-id0007.c0f0", "ethernet-phy-ieee802.3-c22";
			reg = <1>;
			micrel,led-mode = <1>;
			clocks = <&clks IMX6UL_CLK_ENET2_REF>;
			clock-names = "rmii-ref";
		};
	};
};

网络复位引脚冲突屏蔽和初始化

	spi-4 {
		compatible = "spi-gpio";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_spi4>;
-		status = "okay";
+		status = "disabled";
		gpio-sck = <&gpio5 11 0>;
		gpio-mosi = <&gpio5 10 0>;
+	/*	cs-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>; */
		num-chipselects = <1>;
		#address-cells = <1>;
		#size-cells = <0>;

		gpio_spi: gpio@0 {
			compatible = "fairchild,74hc595";
			gpio-controller;
			#gpio-cells = <2>;
			reg = <0>;
			registers-number = <1>;
			registers-default = /bits/ 8 <0x57>;
			spi-max-frequency = <100000>;
+	/*		enable-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>; */
		};
	};
+ &iomuxc_snvs {
+	pinctrl-names = "default_snvs";
+	status = "okay";

+	pinctrl_enet1_reset: enet0grp {
+        fsl,pins = <
+            MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10B0
+        >;
+    };

+    pinctrl_enet2_reset: enet1grp {
+        fsl,pins = <
+            MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x10B0
+        >;
+    };
+ };

phy网络bug修改

/**
 * genphy_config_aneg - restart auto-negotiation or write BMCR
 * @phydev: target phy_device struct
 *
 * Description: If auto-negotiation is enabled, we configure the
 *   advertising, and then restart auto-negotiation.  If it is not
 *   enabled, then we write the BMCR.
 */
int genphy_config_aneg(struct phy_device *phydev)
{
	int result;

+    /* 复位phy,增加 */
+    phy_reset(phydev);

	if (phydev->autoneg != AUTONEG_ENABLE)
		return genphy_setup_forced(phydev);

	result = genphy_config_advert(phydev);

	if (result < 0) /* error */
		return result;

	if (result == 0) {
		/*
		 * Advertisment hasn't changed, but maybe aneg was never on to
		 * begin with?  Or maybe phy was isolated?
		 */
		int ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);

		if (ctl < 0)
			return ctl;

		if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
			result = 1; /* do restart aneg */
	}

	/*
	 * Only restart aneg if we are advertising something different
	 * than we were before.
	 */
	if (result > 0)
		result = genphy_restart_aneg(phydev);

	return result;
}

其他

增加图片logo显示,tools/logo下增加freescale.bmp,在lcd显示nxp的logo

重新编译后下载
移植完成后再次编译

添加uboot环境变量,并执行ping测试

# 1. 设置开发板自己的 IP 地址 (必须与电脑在同一网段)
setenv ipaddr 192.168.10.10
# 2. 设置电脑(服务器)的 IP 地址
setenv serverip 192.168.10.100
# 3. 设置子网掩码 (通常直连或局域网都是这个)
setenv netmask 255.255.255.0
# 4. 设置网关 (直连电脑时,通常设为电脑 IP 即可)
setenv gatewayip 192.168.10.100
# 5. 保存设置到存储设备 (下次开机不用再输)
saveenv
# 6. 执行 Ping 测试
ping 192.168.10.100

可以看到uboot外设驱动正常运行。
uboot下载后效果

posted @ 2026-04-02 12:41  真真没啥技术的我  阅读(6)  评论(0)    收藏  举报