真真没啥技术的我学Linux驱动 | U-boot移植
在这之前我们写了个玩具级别的bootloader实现了内核引导与启动,这说明BootLoader的底层逻辑并不神秘。
但玩具终究是玩具。它没有命令行的调试能力,不支持网络加载,兼容性也不好......现在让我们走进真正的bootloader的世界。
什么是U-boot?
bootloader千千万万,可不止就只有个U-boot,除此之外还有Barebox、Coreboot、LK等等。只不过U-boot支持架构多,社区活跃,用的最多,比较流行而已。作为bootloader,简单来说U-boot就是嵌入式系统的“BIOS + 引导器”。
同样也离不开三件核心工作:
- 初始化硬件 —— 初始化 时钟、串口、DDR 、存储设备,让板子“活过来”。
- 加载内核 —— 从 Flash、SD 卡或网络把 Linux 内核读进内存。
- 启动内核 —— 告诉内核内存大小、根文件系统位置等信息,跳转到内核入口,把控制权交给操作系统。
但这还不是它的全部。U-Boot 本质上是一个极其复杂的裸机程序。它引入了设备树(Device Tree)来实现硬件解耦,支持 Kconfig 菜单化配置,还提供了一套类似 shell 的交互命令(md、mw、tftp 等),让底层调试变得异常优雅。
本篇属于第二部分
第二部分 我只是个搬运工之 BootLoader
U-boot移植
既然移植,那么暂时不需要抽丝剥茧的去看uboot的细节,一切以能跑起来能用为目的。、
一般U-boot移植的源码来源,通常分为3种:
-
主线版本(Mainline): 纯净但高冷,需要自己添加芯片soc以及相关外设,需要对整个芯片架构了如指掌,难度很大。。
-
芯片原厂版本(NXP/ST 等): soc相关内容已被添加,并且支持官方评估板。只需要根据自己的需求,修改部分设备树和外设源码即可。
-
板卡厂商版本(正点原子/讯为等): 开箱即用,适合直接开发应用。
本篇要介绍正是常用的第二种,基于 NXP 官方源码进行移植,移植的核心逻辑是
- 确定自己板子与源码支持的硬件差异。
- 根据差异,修改设备树或外设代码,进行适配。
- 对应条件配置到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即为编译后的可执行文件。

生成出来的文件这些是我们需要知道的。
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整个的编译链路是跑通的,接下来就是一系列的移植工作。

为了防止移植过程中,没有记录或污染源码。先创建个属于自己的分支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 = <ðphy0>;
phy-supply = <®_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 = <ðphy1>;
phy-supply = <®_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外设驱动正常运行。


在这之前我们写了个玩具级别的bootloader实现了内核引导与启动,这说明BootLoader的底层逻辑并不神秘。
但玩具终究是玩具。它没有命令行的调试能力,不支持网络加载,兼容性也不好......现在让我们走进真正的bootloader的世界,从0开始一步步移植带设备树功能U-boot到正点原子开发板。
浙公网安备 33010602011771号