PHY启动

rockchip rk3566 android11 网口log报错: DMA engine initialization failed 问题描述:上电初始化前将网口插入,然后上电初始化网口能够正常使用,且能够找到PHY,ifconfig 查看能够有eth0 产生,网口正常使用且能够热插拔,但上电初始化时,不插入网口,就会报DMA engine initialization failed 错误,DMA 初始化的时候出错了。 分析:一般产生这个问题可以认为是GMAC 的工作时钟出问题了。先测量时钟引脚是否有时钟,时钟频率以及幅度等指标是否正常,主要确认以下几个方面: 1.IOMUX 出错,检查时钟脚寄存器值是否正确。 2.时钟方向以及配置 阅读详情

问题: PHY 是怎么启动的

当执行ifconfig eth0 up 希望启动网络的时候,会执行 网卡设备的操作集 open()

struct net_device
	const struct net_device_ops *netdev_ops; = &stmmac_netdev_ops-------+
																		|
																		|
static const struct net_device_ops stmmac_netdev_ops = {----------------+
	.ndo_open = stmmac_open,
	...
};

stmmac_open()会去尝试到mdio总线上 匹配 phy device 与 phy driver 。 当匹配成功后 会调用 phy driver的 probe()函数,设置 phy 状态为准备状态PHY_READY,启动phy 状态机任务phy_state_machine 函数。然后做一系列操作后 最终 切换phy 状态为驱动 PHY_UP,这样 状态机任务就会继续执行下去。该函数一直在运行(每隔一秒检测一次网络状态),判断不同的网络状态作出不同的动作。其中CHANGELINK是会根据网络连、断来判断是RUNNING还是NOLINK。这样,就知道网络是连接上还是断开。

关于PHY 状态机的状态切换

enum phy_state {
	PHY_DOWN = 0,//PHY 没准备好
	PHY_STARTING,//PHY 芯片OK了
	PHY_READY,//准备好了,会在phy driver probe()中切换状态机状态到 PHY_UP
	PHY_PENDING,
	PHY_UP, //PHY 启动
	PHY_AN, //自动协商
	PHY_RUNNING, //正在运行
	PHY_NOLINK, //断网
	PHY_FORCING, 
	PHY_CHANGELINK, //状态变化
	PHY_HALTED,
	PHY_RESUMING
};

phy状态变化主要在 phy_state_machine 函数。该函数一直在运行(每隔一秒检测一次网络状态),该函数判断不同的网络状态作出不同的动作。其中CHANGELINK是会根据网络连、断来判断是RUNNING还是NOLINK。这样,就知道网络是连接上还是断开

rivers\net\ethernet\stmicro\stmmac\stmmac_main.c

static int stmmac_open(struct net_device *dev)
{
	
	...
	/*
	目前分析的工作:
		如 
		1 到 mdio 总线上查找目标 phy 设备
		2 匹配到对应 phy driver 后 调用 phy driver 的probe(),设置phy 状态为 "准备好了"
		3 启动phy 状态机任务
	*/
	ret = stmmac_init_phy(dev);
	if (ret) {
		netdev_err(priv->dev,
			   "%s: Cannot attach to PHY (error: %d)\n",
			   __func__, ret);
		return ret;
	}

	...
	
	//分配TX/RX资源
	ret = alloc_dma_desc_resources(priv);
	
	//初始化RX/TX的回环描述
	ret = init_dma_desc_rings(dev, GFP_KERNEL);

	//检查MAC 地址
	stmmac_check_ether_addr(priv);
	
	//设置mac为可用状态,配置mac核心寄存器,然后DMA数据准备接收和发送
	ret = stmmac_hw_setup(dev, true);
	...
	
	//启动PHY设备
	// PHY 状态切换: PHY_READY---->PHY_UP
	phy_start(dev->phydev);
	
	...
}




/**
 * stmmac_init_phy - PHY initialization  PHY初始化
 * @dev: net device structure

工作:	
	如 到mdio 总线上查找 目标phy device,当
 */
static int stmmac_init_phy(struct net_device *dev)
{
	//获取网卡设备的 私有数据
	struct stmmac_priv *priv = netdev_priv(dev);
	...

	/* 在 GMAC控制器初始化的时候,已经解析了 phy配置节点
		struct net_device{
			
		}+网卡私有数据 
		struct stmmac_priv 
			//gmac控制器所有配置信息
			struct plat_stmmacenet_data *plat;
				struct device_node *phy_node; //phy配置节点
	*/
	if (priv->plat->phy_node) {
		/*
		struct net_device *dev
		
		struct net_device{
			
		}+网卡私有数据 
		struct stmmac_priv 
			//gmac控制器所有配置信息
			struct plat_stmmacenet_data *plat;
				struct device_node *phy_node; //phy配置节点
				
		 void stmmac_adjust_link(struct net_device *dev)
		 
		 0
		 
		 struct net_device{
			
		}+网卡私有数据 
		struct stmmac_priv 
			//gmac控制器所有配置信息
			struct plat_stmmacenet_data *plat;
				int interface;
		
		
		
		
		*/
		phydev = of_phy_connect(dev, priv->plat->phy_node,&stmmac_adjust_link, 0, interface);
	}

	...
}



drivers\of\of_mdio.c
/** 连接到设备树中描述的phy
 * of_phy_connect - Connect to the phy described in the device tree

目前分析的工作:
如 
1 到 mdio 总线上查找目标 phy 设备
2 匹配到对应 phy driver 后 调用 phy driver 的probe(),设置phy 状态为 "准备好了"
3 启动phy 状态机任务

 */
/*
	struct net_device *dev

	struct net_device{
		
	}+网卡私有数据 
	struct stmmac_priv 
		//gmac控制器所有配置信息
		struct plat_stmmacenet_data *plat;
			struct device_node *phy_node; //phy配置节点
			
	 void stmmac_adjust_link(struct net_device *dev)
	 
	 0
	 
	 struct net_device{
		
	}+网卡私有数据 
	struct stmmac_priv 
		//gmac控制器所有配置信息
		struct plat_stmmacenet_data *plat;
			int interface;

*/
struct phy_device *of_phy_connect(struct net_device *dev,
				  struct device_node *phy_np,
				  void (*hndlr)(struct net_device *), u32 flags,
				  phy_interface_t iface)
{
	
	/* 到 mdio 总线上查找目标 phy 设备
	
	struct net_device{
		
	}+网卡私有数据 
	struct stmmac_priv 
		//gmac控制器所有配置信息
		struct plat_stmmacenet_data *plat;
			struct device_node *phy_node; //phy配置节点
	*/
	struct phy_device *phy = of_phy_find_device(phy_np);
	int ret;

	if (!phy)
		return NULL;

	phy->dev_flags = flags;

	/*
	struct net_device *dev
	
	目标 phy 设备  struct phy_device
	
	void stmmac_adjust_link(struct net_device *dev)
	
	struct net_device{
		
	}+网卡私有数据 
	struct stmmac_priv 
		//gmac控制器所有配置信息
		struct plat_stmmacenet_data *plat;
			int interface = PHY_INTERFACE_MODE_RMII;
			
	*/
	ret = phy_connect_direct(dev, phy, hndlr, iface);

	/* refcount is held by phy_connect_direct() on success */
	put_device(&phy->mdio.dev);

	return ret ? NULL : phy;
}
EXPORT_SYMBOL(of_phy_connect);


/**
 * of_phy_find_device - Give a PHY node, find the phy_device
 * @phy_np: Pointer to the phy's device tree node

	/*
	struct net_device{
		
	}+网卡私有数据 
	struct stmmac_priv 
		//gmac控制器所有配置信息
		struct plat_stmmacenet_data *plat;
			struct device_node *phy_node; //phy配置节点
 */
struct phy_device *of_phy_find_device(struct device_node *phy_np)
{
	struct device *d;
	struct mdio_device *mdiodev;

	if (!phy_np)
		return NULL;

	/*
		
	在 GMAC 控制器初始化注册的时候,检索并创建了mdio总线上的 phy 设备,并注册了phy设备到 mdio_bus 总线
	所以这里 可以获取到目标 phy_device 
	*/
	d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match);
	if (d) {
		/*
			struct phy_device
				struct mdio_device mdio
					struct device dev;
		*/
		mdiodev = to_mdio_device(d);
		if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY){
			//获取 struct phy_device 
			return to_phy_device(d);
		}
		put_device(d);
	}

	return NULL;
}
EXPORT_SYMBOL(of_phy_find_device);
 
/** 
 * phy_connect_direct - connect an ethernet device to a specific phy_device
 * @dev: the network device to connect
 * @phydev: the pointer to the phy device
 * @handler: callback function for state change notifications
 * @interface: PHY device's interface
 */
 
/*
	struct net_device *dev

	目标 phy 设备  struct phy_device

	void stmmac_adjust_link(struct net_device *dev)

	struct net_device{
		
	}+网卡私有数据 
	struct stmmac_priv 
		//gmac控制器所有配置信息
		struct plat_stmmacenet_data *plat;
			int interface = PHY_INTERFACE_MODE_RMII;
			

*/
int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,
		       void (*handler)(struct net_device *),
		       phy_interface_t interface)
{
	int rc;

	if (!dev)
		return -EINVAL;

	/*
	struct net_device *dev

	目标 phy 设备  struct phy_device
	
	...
	
	struct net_device{
		
	}+网卡私有数据 
	struct stmmac_priv 
		//gmac控制器所有配置信息
		struct plat_stmmacenet_data *plat;
			int interface = PHY_INTERFACE_MODE_RMII;
			
	工作 :
		比如 调用 phy driver 的probe() ,设置phy 状态为 "准备好了"
	*/
	rc = phy_attach_direct(dev, phydev, phydev->dev_flags, interface);
	if (rc)
		return rc;

	phy_prepare_link(phydev, handler);
	
	// 启动phy 状态机任务
	phy_start_machine(phydev);
	if (phydev->irq > 0)
		phy_start_interrupts(phydev);

	return 0;
}
EXPORT_SYMBOL(phy_connect_direct);


/** 将网络设备附加到给定的PHY设备指针
 * phy_attach_direct - attach a network device to a given PHY device pointer
 * @dev: network device to attach
 * @phydev: Pointer to phy_device to attach
 * @flags: PHY device's dev_flags
 * @interface: PHY device's interface
 *
	工作 :
		比如 调用 phy driver 的probe() ,设置phy 状态为 "准备好了"
 */
int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
		      u32 flags, phy_interface_t interface)
{
	/*
		struct phy_device 
			struct mdio_device mdio
				struct device dev;
	*/
	struct device *d = &phydev->mdio.dev;
	
	...
	/* 执行 phy driver 的probe()
		struct device 
			// which driver has allocated this device 
			struct device_driver *driver;	
				int (*probe) (struct device *dev);
					   
	工作:
		比如 设置 phy 状态为 "准备好了"
	*/
	err = d->driver->probe(d);

	...
	
	
}

drivers\net\phy\phy_device.c

/**
 * phy_probe - probe and init a PHY device
 * @dev: device to probe and init
 *
 * Description: Take care of setting up the phy_device structure,
 *   set the state to READY (the driver's init function should
 *   set it to STARTING if needed).
 */
static int phy_probe(struct device *dev)
{
	struct phy_device *phydev = to_phy_device(dev);
	
	
	...
	
	/* Set the state to READY by default */
	//设置 phy 状态为 "准备好了"
	phydev->state = PHY_READY;
	
	...
}




/**
 * phy_start_machine - start PHY state machine tracking
 * @phydev: the phy_device struct
 */
void phy_start_machine(struct phy_device *phydev)
{
	/* 启动phy 状态机任务
	在创建 phy 设备的时候 建立了状态机任务 
		INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
	*/
	queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, HZ);
}
EXPORT_SYMBOL_GPL(phy_start_machine);
linux网口配置成自动协商,在Xilinx的Linux启动过程中禁用PHY自动协商 我正在尝试在FPGA板上安装Linux。linux版本是Xilinx FPGA芯片的petalinux。当前的Xilinx SoC具有Cortex A9处理器和可编程硬件逻辑,即FPGA。我在终端上捕获了启动消息:.....................U-boot time.......................partition................................ 阅读详情

相关推荐

Layerscape平台U-Boot与UEFI启动全解析:从DDR PHY到系统部署

在嵌入式系统开发中,引导加载程序是连接硬件初始化与操作系统的关键桥梁,其核心原理在于建立稳定的运行环境并加载后续软件。U-Boot和UEFI作为两大主流引导方案,通过不同的技术路径实现这一目标,其价值在于提供了灵活、可靠的系统启动基础,直接影响产品的部署效率和现场稳定性。在基于NXP Layerscape多核处理器的应用中,启动流程尤为复杂,涉及DDR PHY训练固件、FIP镜像打包等底层技术。这些技术确保了内存子系统等关键硬件的正确初始化,为高性能计算、工业网关和边缘服务器等场景提供了坚实基础。本文聚焦于

412

Linux网络设备驱动-内核stmmac网卡驱动

前言 写文章的目的是想通过记录自己的学习过程,以便以后使用到相关的知识点可以回顾和参考。 一、硬件组成框架 上图 内部MAC + 外部PHY + RJ45 的组合就组成了一个完整的嵌入式网络接口硬件。MAC跟PHY的通讯通过MDIO总线 和 MII/RMII/GMII/RGMII等接口完成,其中驱动程序可以通过 MDIO 总线访问 PHY 芯片的任意一个寄存器,来完成对PHY的配置,而网络数据传输则通过 MII/RMII/GMII/RGMII等接口完成。 . 一、阅读源代码的过程 stmmac驱动源码主

qq_43286311的博客 4706

STM32H563以太网启动UDP丢包:从PHY时序到D-Cache的排查与解决

在嵌入式网络通信中,UDP凭借其轻量高效成为首选传输协议,但设备启动阶段的丢包问题常困扰开发者。其本质往往并非协议栈缺陷,而在于MAC与PHY芯片上电时序不同步:MAC初始化远快于PHY自协商,导致数据帧在链路未就绪时被丢弃。理解并管理这一过程,对于提升工业控制、物联网设备等场景的通信可靠性至关重要。本文以STM32H563平台为例,剖析了启动阶段UDP前几包丢失的根因,包括PHY自协商延时、TX描述符耗尽以及D-Cache一致性问题,并给出从等待链路就绪、检查netif状态到DMA缓存维护的完整解决方案。

weixin_29195615的博客 322

STMMAC驱动

在PHY设备的注册中(读PHY ID)、PHY的初始化、自协商、中断、状态、能力获取等流程中经常可以看到phy_read和phy_write两个函数(下一节要讲的PHY驱动),这两个函数的实现就依赖于控制器设备mii_bus的读写。可以清楚的看到bus->read和bus->write读写接口在这里得到调用。

四季帆的博客 5424

飞腾2000/4C启动调试:FIP镜像与GPIO-PHY协同机制解析

ARMv8平台固件启动本质上是TrustZone安全域下的多阶段权限交接过程。FIP镜像作为ARM Trusted Firmware定义的模块化固件容器,承载BL1/BL2/BL31/BL33等关键启动组件,其签名验证、加载顺序与硬件初始化强耦合;而GPIO与PHY并非孤立外设,而是通过PINCTRL复用、MDIO时序控制和设备树强绑定形成跨层协同链路。这种深度耦合决定了国产CPU平台调试必须穿透UEFI、固件、驱动与硬件四层边界。本文聚焦飞腾2000/4C平台,详解FIP-all.bin结构逆向、GPIO

weixin_33910191的博客 224

linux网络设备—PHY

一.结构体 1.PHY设备 struct phy_device { struct phy_driver *drv; //PHY设备驱动 struct mii_bus *bus; //对应的MII总线 struct device dev; //设备文件 u32 phy_id; //PHY ID enum phy_state state; //PHY状态 u32 dev_f

paomadi的专栏 1万+

网卡启动时出现:PHY 0:00 not found

寞水

寞水 3861

汽车以太网PHY芯片TJA1101B硬件设计与链路启动实战指南

汽车以太网是支撑高级驾驶辅助系统(ADAS)和智能座舱高速数据传输的关键技术,其核心在于物理层(PHY)芯片。它通过PAM-3编码和全双工回声消除等技术,在单对非屏蔽双绞线上实现100Mbps全双工通信,满足了车载环境对高带宽、低延迟和强抗干扰性的严苛要求。在工程实践中,硬件设计的稳定性至关重要,涉及电源完整性、信号完整性(SI)及电磁兼容性(EMC)等多方面考量。例如,为满足汽车级功能安全,PHY芯片需集成ISO 26262 ASIL-A等级的安全监控机制。本文以NXP TJA1101B为例,深入解析其硬

weixin_32239523的博客 310

解决PHY6212烧录程序后无法启动的问题

PHY6212烧录固件无法启动问题 之前用安信可的PB02测试板想烧录PHY6212的主机固件一直跑不起来,网上也查不到资料,最后排查得出是因为安信可的PB02出厂时没有烧录PID/LID/TID/MID/SID/MAC的序列号,需要手动写入之后才可以正常运行SDK中的example,界面如下: 点击界面中的CheckID按钮,如果不能读出正确的PID/LID/TID/MID/SID/MAC序列号则需要自己写入,写入方法是将对应的序列号填好之后点击WriteID按钮,等待返回OK即可,结果如下: 注意,

Guardian Ye的博客 1351

汽车以太网PHY主从模式为什么不能自动协商?聊聊车载启动时间的那些事儿

本文深入探讨了汽车以太网PHY主从模式为何必须采用静态配置而非自动协商,重点分析了车载系统对实时性的严苛要求。通过对比工业以太网,揭示了车载PHY在启动时间、时钟同步和功耗优化等方面的独特设计,并提供了芯片选型与系统集成的实用建议。

weixin_42525385的博客 166

RK3399平台开发系列讲解(内核子系统篇)2.30、phy_device与net_device的连接

调用phy_connect接口进行phy_device、net_device的绑定时,可根据"fixed-0:phy_addr",在mdio_bus上查找对应的phy_device,从而完成phy_device与net_device的绑定。

内核笔记 3011

u-boot USB启动深度解析:从PHY初始化到fatload全流程避坑指南

USB启动是嵌入式系统常见的固件加载方式,其本质是基于USB主机控制器(EHCI/OHCI)、USB协议栈、MSC存储类驱动与FAT文件系统协同工作的完整链路。理解USB设备枚举原理、控制器寄存器初始化时序、PHY上电与模拟参数配置,是解决‘0 USB Device(s) found’等典型问题的基础;而U盘格式兼容性(如MBR分区、FAT32规范、活动标志位)、SCSI指令适配(READ CAPACITY容错)、以及DMA缓存一致性等技术细节,则直接决定fatload能否稳定加载内核镜像。本文聚焦ARM平

weixin_33767813的博客 411

DMA engine initialization failed rk3568的原因及解决方案

刚开始调试 switch 芯片的时候由于rgmii 时钟是output , rk3568的 GMAC 需要 switch 芯片提供 125M的时钟,如果没有这个时钟就会初始化失败,进入文件系统后 ethx 不会出现(当然,如果屏蔽掉这里ethx 会出现,但是引发更多的问题,笔者在这块耍小聪明,导致耗费了近一个月时间,把网络这块整个查了一遍 -----)dma 软复位是在进入文件系统后,网络系统启动的时候,我想如果在这个之前只要提供合适的时钟那么就是可以的,那么------以上是官方的文档说明。

Nyiragongo的博客 4573

12、UFS初始化与训练:UFS启动流程(Power-up到Link Startup)、UniPro协议栈初始化、M-PHY链路训练

如果你的板子layout不好,链路训练可能会失败,或者训练成功后出现误码。:我在项目中遇到过UniPro初始化失败的情况,最后发现是Device返回的属性值超出了Host的预期范围。UniPro是UFS的“大脑”,负责管理链路的建立、配置和错误处理。按照流程一步步排查,用示波器看波形,用逻辑分析仪抓协议,总能找到原因。,速率只有几Mbps。不管你是哪个厂家的UFS芯片,先用最低速率把链路建起来,然后再协商高速。的,前一步没完成,后一步就不会开始。每一步都有严格的时序要求,错一步,整个链路就起不来。

woailuojp的博客 26

lwIP裸机启动流程详解:PHY初始化与netif注册

嵌入式网络协议栈中,轻量级TCP/IP实现(如lwIP)在无操作系统环境下的启动过程,本质上是硬件驱动、内存管理与协议栈内核的协同初始化。其核心原理在于严格遵循硬件依赖时序,完成PHY芯片配置、MAC外设使能、MDIO通信建立,并构建pbuf内存池与netif网络接口结构体。该技术方案显著降低资源占用,适用于STM32等MCU平台的工业控制、物联网终端等低功耗高可靠场景。本文聚焦lwIP裸机移植中的关键路径——以LAN8720A PHY和STM32 ETH外设为典型载体,深入解析从复位释放、自协商启动到ne

weixin_28235889的博客 37

PHY6222国产BLE 5.2 SoC深度拆解:从启动流程、低功耗状态机到射频吞吐实测

在物联网与智能穿戴设备开发中,低功耗无线SoC的选型与底层驱动设计是核心挑战。以ARM Cortex-M0架构为例,芯片通过多级存储映射(ROM/SRAM/Flash/eFuse)完成启动,并借助时钟门控、系统睡眠等状态机实现微安级功耗管理。这类技术直接决定了BLE Mesh节点、工业传感器等场景的续航与可靠性。PHY6222作为支持BLE 5.2与802.15.4的国产SoC,其QFN32封装、单引脚天线及1.6Mbps吞吐特性,为穿戴与信标应用提供了高集成度方案。本文基于v1.2 datasheet,拆

weixin_29172201的博客 153

开源项目 phy 使用教程

phy 项目的目录结构如下: ``` phy/ ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── docs/ ├── phy/ │ ├── __init__.py │ ├── cluster/ │ ├── gui/ │ ├── io/ │ ├── plot/ │...

gitblog_01001的博客 443

PHY---YT8521S参考设计

YT8521参考设计

硬件打工仔的专栏 4054
上一篇: PHY驱动注册部分
下一篇: USB基础
Ma浩然
博客等级 码龄9年 1万+粉丝 462原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ma浩然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值