草庐IT

Linux驱动之系统移植----uboot移植(有设备树版本),完整移植.

未燃机智鱼 2025-05-11 原文

uboot版本:uboot2020.04
开发板:100ask_imx6ull_pro

拿到官方uboot后第一步先编译烧写测试, 查看哪些驱动可用, 哪些不可用.
根据开发板厂商提供的资料:
使用mx6ull_14x14_evk_defconfig配置进行修改
编译完成后将uboot设备树以及uboot.imx烧写到开发板中运行


CPU:   i.MX6ULL rev1.1 792 MHz (running at 396 MHz)
CPU:   Industrial temperature grade (-40C to 105C) at 40C
Reset cause: POR
Model: i.MX6 ULL 14x14 EVK Board
Board: MX6ULL 14x14 EVK
DRAM:  512 MiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
Loading Environment from MMC... *** Warning - bad CRC, using default environment

[*]-Video Link 0 (480 x 272)
        [0] lcdif@21c8000, video
In:    serial
Out:   serial
Err:   serial
switch to partitions #0, OK
mmc1(part 0) is current device
flash target is MMC:1
Net:
Error: ethernet@20b4000 address not set.

Error: ethernet@20b4000 address not set.

Error: ethernet@20b4000 address not set.
FEC: can't find phy-handle

Error: ethernet@20b4000 address not set.
Could not get PHY for FEC0: addr 2

Error: ethernet@20b4000 address not set.
FEC: can't find phy-handle

Error: ethernet@20b4000 address not set.
Could not get PHY for FEC0: addr 2
No ethernet found.

显然网络不通, phy无法找到, 其次LCD需要关闭(uboot启动阶段非必要驱动LCD)

一, 添加自定义板子

参考文章官方uboot添加自定义板子
备注:
uboot2020的图形界面配置文件在 arch/arm/mach-imx/mx6
全局搜索TARGET_MX6ULL_14X14_EVK找到的

二, 关闭LCD

在mx6ull_jzy_defconfig文件中

删除 CONFIG_DM_VIDEO=y

因为在mx6ull_jzy.c文件中有lcd的初始化函数: setup_lcd(void);有个编译选项为CONFIG_DM_VIDEO, 搜索这个就可以得到是在mx6ull_jzy_defconfig中定义了

三, 在设备树中修改网络驱动

官板与开发板的硬件原理图对比
由于开发板更换了官板的phy芯片所以需要修改PHY芯片配置
在mx6ull_jzy.c文件中找到网络驱动相关的函数:
static int setup_fec(void)


#ifdef CONFIG_FEC_MXC
static int setup_fec(void)
{
	struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
	int ret;

	/*
	 * Use 50M anatop loopback REF_CLK1 for ENET1,
	 * clear gpr1[13], set gpr1[17].
	 */
	clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC1_MASK,
			IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK);
	/*
	 * Use 50M anatop loopback REF_CLK2 for ENET2,
	 * clear gpr1[14], set gpr1[18].
	 */
	if (!check_module_fused(MX6_MODULE_ENET2)) {
		clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC2_MASK,
				IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK);
	}

	ret = enable_fec_anatop_clock(0, ENET_50MHZ);
	if (ret)
		return ret;

	if (!check_module_fused(MX6_MODULE_ENET2)) {
		ret = enable_fec_anatop_clock(1, ENET_50MHZ);
		if (ret)
			return ret;
	}

	enable_enet_clk(1);

	return 0;
}

int board_phy_config(struct phy_device *phydev)
{
	phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x8190);

	if (phydev->drv->config)
		phydev->drv->config(phydev);

	return 0;
}
#endif

被CONFIG_FEC_MXC宏定义包含, 在mx6ull_jzy_defconfig中搜索得到:
CONFIG_FEC_MXC=y
已经开启.

由于开发板使用了LAN8720的PHY芯片,
在mx6ull_jzy_defconfig把
CONFIG_PHY_MICREL=y
CONFIG_PHY_MICREL_KSZ8XXX=y
这两个删除, 替换成
CONFIG_PHY_SMSC=y

因为在drivers/net/phy/Makefile中定义了一系列编译选项

# SPDX-License-Identifier: GPL-2.0+
#
# (C) Copyright 2008
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.

obj-$(CONFIG_BITBANGMII) += miiphybb.o
obj-$(CONFIG_B53_SWITCH) += b53.o
obj-$(CONFIG_MV88E61XX_SWITCH) += mv88e61xx.o
obj-$(CONFIG_MV88E6352_SWITCH) += mv88e6352.o

obj-$(CONFIG_PHYLIB) += phy.o
obj-$(CONFIG_PHYLIB_10G) += generic_10g.o
obj-$(CONFIG_PHY_AQUANTIA) += aquantia.o
obj-$(CONFIG_PHY_ATHEROS) += atheros.o
obj-$(CONFIG_PHY_BROADCOM) += broadcom.o
obj-$(CONFIG_PHY_CORTINA) += cortina.o
obj-$(CONFIG_PHY_DAVICOM) += davicom.o
obj-$(CONFIG_PHY_ET1011C) += et1011c.o
obj-$(CONFIG_PHY_LXT) += lxt.o
obj-$(CONFIG_PHY_MARVELL) += marvell.o
obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o
obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o
obj-$(CONFIG_PHY_NATSEMI) += natsemi.o
obj-$(CONFIG_PHY_REALTEK) += realtek.o
obj-$(CONFIG_PHY_SMSC) += smsc.o
obj-$(CONFIG_PHY_TERANETICS) += teranetics.o
obj-$(CONFIG_PHY_TI) += dp83867.o
obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o
obj-$(CONFIG_PHY_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
obj-$(CONFIG_PHY_VITESSE) += vitesse.o
obj-$(CONFIG_PHY_MSCC) += mscc.o
obj-$(CONFIG_PHY_FIXED) += fixed.o
obj-$(CONFIG_PHY_NCSI) += ncsi.o

跳转到smsc.c中发现开发板所用的芯片的定义:

static struct phy_driver lan8710_driver = {
	.name = "SMSC LAN8710/LAN8720",
	.uid = 0x0007c0f0,
	.mask = 0xffff0,
	.features = PHY_BASIC_FEATURES,
	.config = &genphy_config_aneg,
	.startup = &genphy_startup,
	.shutdown = &genphy_shutdown,
};

修改设备树

第一步确定PHY芯片地址
mx6ull_jzy_defconfig中定义了
CONFIG_DEFAULT_DEVICE_TREE=“imx6ull-14x14-evk”
使用设备树imx6ull-14x14-evk
打开imx6ull-14x14-evk.dts

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

包含了三个dtsi, 全部打开, 并搜索phy关键字
在imx6ul-14x14-evk.dtsi中找到fec1和fec2的描述

&fec1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet1>;
	phy-mode = "rmii";
	phy-handle = <&ethphy0>;
	status = "okay";
};

&fec2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet2>;
	phy-mode = "rmii";
	phy-handle = <&ethphy1>;
	status = "okay";

	mdio {
		#address-cells = <1>;
		#size-cells = <0>;

		ethphy0: ethernet-phy@2 {
			reg = <2>;
			micrel,led-mode = <1>;
			clocks = <&clks IMX6UL_CLK_ENET_REF>;
			clock-names = "rmii-ref";
		};

		ethphy1: ethernet-phy@1 {
			reg = <1>;
			micrel,led-mode = <1>;
			clocks = <&clks IMX6UL_CLK_ENET2_REF>;
			clock-names = "rmii-ref";
		};
	};
};

然而其标签是&fec2说明这并不是最初的源头, 我们需要找到对饮的节点的驱动程序, 最好的办法就是fec2的compatible属性的定义
通过追溯所有imx6ull-14x14-evk.dts包含的设备树, 找到imx6ul.dtsi中描述了fec2


			fec2: ethernet@20b4000 {
				compatible = "fsl,imx6ul-fec", "fsl,imx6q-fec";
				reg = <0x020b4000 0x4000>;
				interrupt-names = "int0", "pps";
				interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_ENET>,
					 <&clks IMX6UL_CLK_ENET_AHB>,
					 <&clks IMX6UL_CLK_ENET_PTP>,
					 <&clks IMX6UL_CLK_ENET2_REF_125M>,
					 <&clks IMX6UL_CLK_ENET2_REF_125M>;
				clock-names = "ipg", "ahb", "ptp",
					      "enet_clk_ref", "enet_out";
				fsl,num-tx-queues=<1>;
				fsl,num-rx-queues=<1>;
				status = "disabled";
			};

通过搜索 fsl,imx6ul-fec 这个关键字可以找到驱动程序

找到了drivers/net/fec_mxc.c中

static const struct udevice_id fecmxc_ids[] = {
	{ .compatible = "fsl,imx28-fec" },
	{ .compatible = "fsl,imx6q-fec" },
	{ .compatible = "fsl,imx6sl-fec" },
	{ .compatible = "fsl,imx6sx-fec" },
	{ .compatible = "fsl,imx6ul-fec" },
	{ .compatible = "fsl,imx53-fec" },
	{ .compatible = "fsl,imx7d-fec" },
	{ .compatible = "fsl,mvf600-fec" },
	{ .compatible = "fsl,imx8qm-fec" },
	{ }
};

U_BOOT_DRIVER(fecmxc_gem) = {
	.name	= "fecmxc",
	.id	= UCLASS_ETH,
	.of_match = fecmxc_ids,
	.ofdata_to_platdata = fecmxc_ofdata_to_platdata,
	.probe	= fecmxc_probe,
	.remove	= fecmxc_remove,
	.ops	= &fecmxc_ops,
	.priv_auto_alloc_size = sizeof(struct fec_priv),
	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
};

在device_get_phy_addr函数中发现获取phy地址, 读取的是phy-handle属性中的reg的第0个描述

static int device_get_phy_addr(struct udevice *dev)
{
	struct ofnode_phandle_args phandle_args;
	int reg;

	if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
				       &phandle_args)) {
		debug("Failed to find phy-handle");
		return -ENODEV;
	}

	reg = ofnode_read_u32_default(phandle_args.node, "reg", 0);

	return reg;
}

fec2的reg第0个描述是0x1.无需修改

第二步对PHY芯片进行硬复位, 即对复位引脚进行操作
在drivers/net/fec_mxc.c中的fecmxc_probe函数中是有复位函数调用的:

static int fecmxc_probe(struct udevice *dev)
{
...
#if CONFIG_IS_ENABLED(DM_GPIO)
	fec_gpio_reset(priv);
#endif
...
}

CONFIG_IS_ENABLED(DM_GPIO)这个宏表示
CONFIG_DM_GPIO是否使能了

查看fec_gpio_reset(priv);函数

/* FEC GPIO reset */
static void fec_gpio_reset(struct fec_priv *priv)
{
	debug("fec_gpio_reset: fec_gpio_reset(dev)\n");
	if (dm_gpio_is_valid(&priv->phy_reset_gpio)) {
		dm_gpio_set_value(&priv->phy_reset_gpio, 1);
		mdelay(priv->reset_delay);
		dm_gpio_set_value(&priv->phy_reset_gpio, 0);
		if (priv->reset_post_delay)
			mdelay(priv->reset_post_delay);
	}
}

dm_gpio_is_valid(&priv->phy_reset_gpio)知道 如果phy_reset_gpio是有效的才会进入初始化.
搜索phy_reset_gpio找到:

	ret = gpio_request_by_name(dev, "phy-reset-gpios", 0,
				   &priv->phy_reset_gpio, GPIOD_IS_OUT);

原来是通过读取设备树中的phy-reset-gpios这个属性, 因此,需要加这个属性.
回到imx6ul-14x14-evk.dtsi文件,
在&fec2中添加属性phy-reset-gpios = <&gpio5 6 GPIO_ACTIVE_LOW>;
模仿spi4节点中的pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;来写的;
初始化的过程还有用到reset_delay这个变量, 搜索得到
priv->reset_delay = dev_read_u32_default(dev, “phy-reset-duration”, 1);
是这么来, 所以要添加phy-reset-duration属性, 值在LAN8720芯片手册中说明, 初始化引脚要保持25以上, 因此设置phy-reset-duration = <26>;

&fec2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet2>;
	phy-mode = "rmii";
	phy-handle = <&ethphy1>;
	phy-reset-gpios = <&gpio5 6 GPIO_ACTIVE_LOW>;
	phy-reset-duration = <26>;
	status = "okay";

	mdio {
		#address-cells = <1>;
		#size-cells = <0>;

		ethphy0: ethernet-phy@2 {
			reg = <2>;
			micrel,led-mode = <1>;
			clocks = <&clks IMX6UL_CLK_ENET_REF>;
			clock-names = "rmii-ref";
		};

		ethphy1: ethernet-phy@1 {
			reg = <1>;
			micrel,led-mode = <1>;
			clocks = <&clks IMX6UL_CLK_ENET2_REF>;
			clock-names = "rmii-ref";
		};
	};
};

在设备树中加上 gpio5-6的初始化.
找到合适的位置添加:
MX6ULL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x79
只要会被调用的地方都可以
pinctrl_enet2是要使用的,必然会被调用.

	pinctrl_enet2: enet2grp {
		fsl,pins = <
			MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x1b0b0
			MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0
			MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0
			MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0
			MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0
			MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0
			MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0
			MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0
			MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0
			MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b031
			MX6ULL_PAD_SNVS_TAMPER6__GPIO5_IO06 0x79
		>;
	};

第三步添加PHY芯片的软复位驱动代码
软复位就是将LAN8720芯片中的复位寄存器设置
打开drivers/net/phy/phy.c b/drivers/net/phy/phy.c
这个是phy芯片的通用驱动
参考文章对drivers/net/phy/phy.c 的修改

烧录测试网卡

=> setenv eth1addr 00:01:3f:2d:3e:4d
=> setenv ipaddr 192.168.31.178
=> setenv gatewayip 192.168.31.1
=> setenv netmask 255.255.255.0
=> setenv serverip 192.168.31.158
=> saveenv
=> ping 192.168.31.158
ethernet@20b4000 Waiting for PHY auto negotiation to complete.... done
Using ethernet@20b4000 device
host 192.168.31.158 is alive

有关Linux驱动之系统移植----uboot移植(有设备树版本),完整移植.的更多相关文章

  1. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  2. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  3. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

    如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

  4. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  5. ruby-on-rails - 如何在 Ruby on Rails 中实现由 JSF 2.0 (Primefaces) 驱动的 UI 魔法 - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道ruby​​onrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim

  6. ruby-on-rails - 如何在发布新的 Ruby 或 Rails 版本时收到通知? - 2

    有人知道在发布新版本的Ruby和Rails时收到电子邮件的方法吗?他们有邮件列表,RubyonRails有一个推特,但我不想听到那些随之而来的喧嚣,我只想知道什么时候发布新版本,尤其是那些有安全修复的版本。 最佳答案 从therailsblog获取提要.http://weblog.rubyonrails.org/feed/atom.xml 关于ruby-on-rails-如何在发布新的Ruby或Rails版本时收到通知?,我们在StackOverflow上找到一个类似的问题:

  7. 电脑0x0000001A蓝屏错误怎么U盘重装系统教学 - 2

      电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。  准备工作:  1、U盘一个(尽量使用8G以上的U盘)。  2、一台正常联网可使用的电脑。  3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。  4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。  U盘启动盘制作步骤:  注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注

  8. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  9. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  10. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

随机推荐