linux phy调试方法_php执行shell命令

linux phy调试方法_php执行shell命令enumphy_state{ PHY_DOWN=0, PHY_STARTING,//1 PHY_READY,//2 PHY_PENDING,//3 PHY_UP,//4 PHY_AN,//5 PHY_RUNNING,//6 PHY_NOLINK,//7 PHY_FORCING,//8 PHY_CHANGELINK,//9 PHY_HALTED,//10…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定


Jetbrains全家桶1年46,售后保障稳定

一、phy执行的枚举状态定义

enum phy_state {
	PHY_DOWN=0, //down 如关闭网卡,ifconfig eth0 down
	PHY_STARTING, //1 
	PHY_READY, //2 phy设备注册成功
	PHY_PENDING, //3 phy芯片挂起
	PHY_UP, //4 开启网卡,ifconfig eth0 up
	PHY_AN, //5 网卡自动协商
	PHY_RUNNING, //6 网卡上已插入网线、并建立物理连接,同时会从这个状态切换到PHY_CHANGELINK
	PHY_NOLINK, //7 断网,如拔掉网线
	PHY_FORCING, //8 自动协商标识未被使能,就强制执行自动协商(读取phy寄存器、并设置通讯速率、半双工或全双工模式、等)
	PHY_CHANGELINK, //9 当连接时,会换到PHY_RUNNING,当断网时,会切到PHY_NOLINK
	PHY_HALTED, //10 在执行网卡关闭时(ifconfig eth0 down)会执行到这个状态,即phy挂起
	PHY_RESUMING //11 在执行网卡开启时(ifconfig eth0 up)会执行到这个状态,即phy恢复
};

二、emac接口驱动下的phy设备注册

nuc970_ether_probe //探测函数驱动
	nuc970_mii_setup
		mdiobus_register
			mdiobus_scan
				get_phy_device
					get_phy_id
					phy_device_create
						dev->autoneg = AUTONEG_ENABLE; //设置phy 自动协商使能
						dev->state = PHY_DOWN; //设置phy的状态 ----1-----
						INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); //初始化一个中断顶版本的延时工作队列,用来处理phy状态机
				phy_device_register //phy设备注册
					device_add //这里是通过堆栈信息打印的,详见下面的 堆栈信息
						bus_probe_device
							device_attach
								bus_for_each_drv
									__device_attach
										driver_probe_device
											phy_probe //非常重要的一个探测接口
												phydev->supported = phydrv->features; //phydrv->features = PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause
												phydev->advertising = phydrv->features;
												phydev->state = PHY_READY; //设置phy的状态 ----2-----
		phy_connect(dev, dev_name(&phydev->dev), &adjust_link, PHY_INTERFACE_MODE_RMII);	
			phy_connect_direct
				phy_prepare_link
					phydev->adjust_link = handler; //handler = adjust_link
				phy_start_machine
					phydev->adjust_state = handler; //handler = NULL
					schedule_delayed_work(&phydev->state_queue, HZ); //启动上面注册的延时工作队列状态机 phy_state_machine

总结:上面已经将phy的状态设置成了 phydev->state = PHY_READY,同时完成了emac接口下的phy设备驱动注册,接下来将分析如何使用该phy设备驱动。

三、应用层执行ifconfig eth0 up时phy的设备状态

ifconfig eth0 up----->
nuc970_ether_open
	phy_start 
		//......
		switch (phydev->state) { //上面已经 phydev->state = PHY_READY
		case PHY_STARTING:
			phydev->state = PHY_PENDING;
			break;
		case PHY_READY:
			phydev->state = PHY_UP; //所以到这里, 设置phy的状态为 PHY_UP ----3-----
			break;
		case PHY_HALTED:
			phydev->state = PHY_RESUMING;
		default:
			break;
		}
		//......

总结:上面在执行 ifconfig eth0 up 后,已将phydev->state = PHY_UP

四、phy状态机phy_state_machine执行状态分析

phy_state_machine
	switch(phydev->state) { //关于该phydev->state的各执行状态详见本“第一”小节的介绍
	case PHY_DOWN: 
	case PHY_STARTING:
	case PHY_READY:
	case PHY_PENDING:
		break;
	case PHY_UP:
		needs_aneg = 1;

		phydev->link_timeout = PHY_AN_TIMEOUT;

		break;
	.....
	phy_start_aneg //启动自动协商
		phydev->drv->config_aneg(phydev); //这里将调用 genphy_config_aneg
			genphy_config_aneg
				genphy_config_advert //自动协商声明,关于其源码详见如下
	phydev->state = PHY_AN; //设置为自动协商,设置phy的状态为 PHY_AN ----4-----	
	//此时函数返回,又重新进入到上面的状态机 phy_state_machine,不过此时的状态已经变为 PHY_AN
	
	case PHY_AN: //自动协商 
		phy_read_status //读取phy的状态
			phydev->drv->read_status(phydev); //.read_status = genphy_read_status
				genphy_read_status
					genphy_update_link
						phy_read(phydev, MII_BMSR); //读取phy的状态寄存器
						if ((status & BMSR_LSTATUS) == 0)  //phy 的链路状态
							phydev->link = 0; //设置网卡的状态处于断开状态
						else
							phydev->link = 1; //设置网卡的状态处于连接状态
		if (!phydev->link) { //链路状态
			phydev->state = PHY_NOLINK; //协商失败,未建立连接,设置phy的状态为 PHY_NOLINK ----5-----
			netif_carrier_off(phydev->attached_dev);
			phydev->adjust_link(phydev->attached_dev);
			break;
		}	
		
		err = phy_aneg_done(phydev); //判断自动协商是否完成	
		/* If AN is done, we're running */
		if (err > 0) { //自动协商完成
			phydev->state = PHY_RUNNING; //协商成功,建立连接,设置phy的状态为 PHY_RUNNING ----6-----
			netif_carrier_on(phydev->attached_dev);
			phydev->adjust_link(phydev->attached_dev); //adjust_link = adjust_link 调用nuc970_ether0里面的接口函数

		} else if (0 == phydev->link_timeout--) { //自动协商未完成,将根据 link_timeout 次数继续尝试自动协商
			needs_aneg = 1;
			/* If we have the magic_aneg bit,
			 * we try again */
			if (phydev->drv->flags & PHY_HAS_MAGICANEG)
				break;
		}
		
	case PHY_RUNNING:
		/* Only register a CHANGE if we are
		 * polling */
		if (PHY_POLL == phydev->irq)
			phydev->state = PHY_CHANGELINK; //正常运行,设置phy的状态为 PHY_CHANGELINK ----7-----
		break;
		
	case PHY_CHANGELINK:
		err = phy_read_status(phydev); //再次获取 phy 链路状态

		if (err)
			break;

		if (phydev->link) {
			phydev->state = PHY_RUNNING; //协商成功,建立连接,设置phy的状态为 PHY_RUNNING ----8-----
			netif_carrier_on(phydev->attached_dev);
		} else {
			phydev->state = PHY_NOLINK; //协商失败,未建立连接,设置phy的状态为 PHY_NOLINK ----9-----
			netif_carrier_off(phydev->attached_dev);
		}

		phydev->adjust_link(phydev->attached_dev);  //adjust_link = adjust_link 调用nuc970_ether0里面的接口函数

		if (PHY_POLL != phydev->irq)
			err = phy_config_interrupt(phydev,
					PHY_INTERRUPT_ENABLED);
		break;	

emac接口驱动配置phy

int genphy_config_aneg(struct phy_device *phydev)
{
	int result;

	if (AUTONEG_ENABLE != phydev->autoneg) //在phy创建的时候,初始了ev->autoneg = AUTONEG_ENABLE; //设置phy 自动协商使能 
		return genphy_setup_forced(phydev);

	result = genphy_config_advert(phydev);

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

	if (result == 0) {
		/* Advertisement hasn't changed, but maybe aneg was never on to
		 * begin with?  Or maybe phy was isolated? */
		int ctl = phy_read(phydev, MII_BMCR); //获取模式控制寄存器,详见该链接对该寄存器的定义:https://wenku.baidu.com/view/b8704335ee06eff9aef807bd.html

		if (ctl < 0)
			return ctl;

		//不能自动协商 || 自动协商复位
		if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE)) //BMCR_ANENABLE: 自动协商使能 || 
			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;
}

获取自动协商配置

static int genphy_config_advert(struct phy_device *phydev)
{
	u32 advertise;
	int oldadv, adv;
	int err, changed = 0;

	/* Only allow advertising what
	 * this PHY supports */
	/*
		phy 设备在注册时初始化为如下:
			phydev->supported = phydrv->features; //phydrv->features = PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause
			phydev->advertising = phydrv->features;
	*/ 
	phydev->advertising &= phydev->supported;
	advertise = phydev->advertising;

	/* Setup standard advertisement */
	oldadv = adv = phy_read(phydev, MII_ADVERTISE); //自动协商声明

	if (adv < 0)
		return adv;

	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
		 ADVERTISE_PAUSE_ASYM);
	adv |= ethtool_adv_to_mii_adv_t(advertise);

	if (adv != oldadv) { //自动协商结果不一致就重新设置
		err = phy_write(phydev, MII_ADVERTISE, adv);

		if (err < 0)
			return err;
		changed = 1;
	}

	/* Configure gigabit if it's supported */
	if (phydev->supported & (SUPPORTED_1000baseT_Half |
				SUPPORTED_1000baseT_Full)) {
		oldadv = adv = phy_read(phydev, MII_CTRL1000);

		if (adv < 0)
			return adv;

		adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
		adv |= ethtool_adv_to_mii_ctrl1000_t(advertise);

		if (adv != oldadv) {
			err = phy_write(phydev, MII_CTRL1000, adv);

			if (err < 0)
				return err;
			changed = 1;
		}
	}

	return changed;
}

重启自动协商

int genphy_restart_aneg(struct phy_device *phydev)
{
	int ctl;

	ctl = phy_read(phydev, MII_BMCR);

	if (ctl < 0)
		return ctl;

	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);

	/* Don't isolate the PHY if we're negotiating */
	ctl &= ~(BMCR_ISOLATE);

	ctl = phy_write(phydev, MII_BMCR, ctl); //设置自动协商

	return ctl;
}

总结:上面源码只要是完成emac接口与phy之间的自动协商、链路状态检测等

五、拓展信息

1. phy_probe匹配时的探测信息

===========================堆栈信息===========================	
Backtrace: 
[<c0012df8>] (dump_backtrace+0x0/0x10c) from [<c0012f1c>] (show_stack+0x18/0x1c)
 r7:c39c8374 r6:c39c8208 r5:c0474914 r4:c39c8200
[<c0012f04>] (show_stack+0x0/0x1c) from [<c0324ef4>] (dump_stack+0x20/0x2c)
[<c0324ed4>] (dump_stack+0x0/0x2c) from [<c022ae08>] (phy_probe+0x58/0x88)
[<c022adb0>] (phy_probe+0x0/0x88) from [<c01f69e4>] (driver_probe_device+0x9c/0x238)
 r7:c047496c r6:00000000 r5:c39c8208 r4:c047496c
[<c01f6948>] (driver_probe_device+0x0/0x238) from [<c01f6c5c>] (__device_attach+0x44/0x48)
[<c01f6c18>] (__device_attach+0x0/0x48) from [<c01f4ff8>] (bus_for_each_drv+0x68/0x94)
 r5:c3843cd8 r4:00000000
[<c01f4f90>] (bus_for_each_drv+0x0/0x94) from [<c01f6d14>] (device_attach+0x88/0xa0)
 r7:00000001 r6:c39c823c r5:c0474820 r4:c39c8208
[<c01f6c8c>] (device_attach+0x0/0xa0) from [<c01f5cc0>] (bus_probe_device+0x8c/0xb4)
 r7:00000001 r6:c39c8208 r5:c0474820 r4:c04b84f8
[<c01f5c34>] (bus_probe_device+0x0/0xb4) from [<c01f45d0>] (device_add+0x310/0x648)
 r7:00000001 r6:00000000 r5:c39c8208 r4:c04b84f8
[<c01f42c0>] (device_add+0x0/0x648) from [<c022bac8>] (phy_device_register+0x44/0x70)
[<c022ba84>] (phy_device_register+0x0/0x70) from [<c022bdd0>] (mdiobus_scan+0x2c/0x4c)
 r7:00000001 r6:00000000 r5:00000001 r4:c39c8200
[<c022bda4>] (mdiobus_scan+0x0/0x4c) from [<c022bf88>] (mdiobus_register+0xec/0x184)
 r5:00000001 r4:c39c8000
[<c022be9c>] (mdiobus_register+0x0/0x184) from [<c022d874>] (nuc970_ether_probe+0x2d8/0x4b4)
[<c022d59c>] (nuc970_ether_probe+0x0/0x4b4) from [<c01f7d08>] (platform_drv_probe+0x20/0x24)
[<c01f7ce8>] (platform_drv_probe+0x0/0x24) from [<c01f69e4>] (driver_probe_device+0x9c/0x238)
[<c01f6948>] (driver_probe_device+0x0/0x238) from [<c01f6c14>] (__driver_attach+0x94/0x98)
[<c01f6b80>] (__driver_attach+0x0/0x98) from [<c01f50a0>] (bus_for_each_dev+0x7c/0xa0)
 r7:c01f6b80 r6:c0474a58 r5:c3843e78 r4:00000000
[<c01f5024>] (bus_for_each_dev+0x0/0xa0) from [<c01f6828>] (driver_attach+0x20/0x28)
 r7:c046fc68 r6:c0474a58 r5:c0474a58 r4:c39a69c0
[<c01f6808>] (driver_attach+0x0/0x28) from [<c01f5990>] (bus_add_driver+0xec/0x240)
[<c01f58a4>] (bus_add_driver+0x0/0x240) from [<c01f6ffc>] (driver_register+0x60/0x150)
 r7:c3842000 r6:00000000 r5:c0474a58 r4:c044396c
[<c01f6f9c>] (driver_register+0x0/0x150) from [<c01f7fe8>] (platform_driver_register+0x4c/0x60)
 r7:c3842000 r6:00000000 r5:c043f414 r4:c044396c
[<c01f7f9c>] (platform_driver_register+0x0/0x60) from [<c04395b0>] (nuc970_ether_init+0x14/0x1c)
[<c043959c>] (nuc970_ether_init+0x0/0x1c) from [<c00087c4>] (do_one_initcall+0x38/0x150)
[<c000878c>] (do_one_initcall+0x0/0x150) from [<c04235d4>] (kernel_init_freeable+0x14c/0x224)
[<c0423488>] (kernel_init_freeable+0x0/0x224) from [<c0324528>] (kernel_init+0x10/0x15c)
[<c0324518>] (kernel_init+0x0/0x15c) from [<c000f850>] (ret_from_fork+0x14/0x24)
 r5:c0324518 r4:00000000
libphy: nuc970_rmii0: probed

2. phy标准寄存器的定义

/* Generic MII registers. */
//控制寄存器
#define MII_BMCR		0x00	/* Basic mode control register */
//状态寄存器
#define MII_BMSR		0x01	/* Basic mode status register  */
//PHY 标志
#define MII_PHYSID1		0x02	/* PHYS ID 1                   */
#define MII_PHYSID2		0x03	/* PHYS ID 2                   */

//4~8寄存器是用于自动协商的
#define MII_ADVERTISE		0x04	/* Advertisement control reg   自动协商声明*/
#define MII_LPA			0x05	/* Link partner ability reg    */
#define MII_EXPANSION		0x06	/* Expansion register          */

//保留
#define MII_CTRL1000		0x09	/* 1000BASE-T control          */
#define MII_STAT1000		0x0a	/* 1000BASE-T status           */
#define	MII_MMD_CTRL		0x0d	/* MMD Access Control Register */
#define	MII_MMD_DATA		0x0e	/* MMD Access Data Register */
#define MII_ESTATUS		0x0f	/* Extended Status             */

//制造商指定寄存器
#define MII_DCOUNTER		0x12	/* Disconnect counter          */
#define MII_FCSCOUNTER		0x13	/* False carrier counter       */
#define MII_NWAYTEST		0x14	/* N-way auto-neg test reg     */
#define MII_RERRCOUNTER		0x15	/* Receive error counter       */
#define MII_SREVISION		0x16	/* Silicon revision            */
#define MII_RESV1		0x17	/* Reserved...                 */
#define MII_LBRERROR		0x18	/* Lpback, rx, bypass error    */
#define MII_PHYADDR		0x19	/* PHY address                 */
#define MII_RESV2		0x1a	/* Reserved...                 */
#define MII_TPISTATUS		0x1b	/* TPI status for 10mbps       */
#define MII_NCONFIG		0x1c	/* Network interface config    */

关于phy的寄存器定义详见:https://wenku.baidu.com/view/b8704335ee06eff9aef807bd.html 第5页

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:http://www.javaforall.cn/234824.html原文链接:http://www.javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 初识业务架构图_管理架构图

    初识业务架构图_管理架构图文章目录什么是业务架构图?业务架构图规范宏观微观设计步骤分层分模块分功能实例什么是业务架构图?是将用户需求进行宏观系统抽象进行描述和展示,是表达业务层级和关系的工具,目的是将简单的业务逻辑简单化,降低理解难度,这个图是给用户和各级领导看的。业务架构图规范宏观1.宏观:横向:并列结构,级别是相同的;纵向:要有分层的思想,整体上有层次感,上层是依赖于下层的,越底层的,越是基础服务,同时也更为重要;对称:要讲究对称美,尽可能地功能结构分配均匀;虚线框:多个模块,逻辑上可以归为一块时可以使用虚线

    2022年10月11日
  • 启动ucosii之四OSTaskCreate()[通俗易懂]

    启动ucosii之四OSTaskCreate()[通俗易懂]函数原型来自OS_TASK.C/***********************************************************************************************************                                           CREATEATASK**************

  • 工业超纯水机:EDI超纯水设备技术介绍

    EDI超纯水设备技术是国际上20世纪90年代开始逐渐发展起来的新型纯水、超纯水制备技术。该技术巧妙地将电渗析技术和离子交换技术相融合,通过阴、阳离子的选择性透过作用与离子交换树脂对离子的交换作用,在直流电场的作用下实现离子的定向迁移,从而完成水的深度除盐,同事水电离解产生的氢离子和氧根离子对离子交换树脂进行再生,因此不需酸碱化学再生而能连续制取超纯水。  EDI设备特点  EDI系统运

  • 空洞骑士debug使用教程_debug调试汇编程序

    空洞骑士debug使用教程_debug调试汇编程序

    2022年10月15日
  • 怎么使用linux命令重启服务器

    怎么使用linux命令重启服务器

  • VMware Ubuntu安装详细过程(详细图解)

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!一.下载Ubuntu镜像文件下载地址:http://mirrors.aliyun.com/ubuntu-releases/16.04/进入下载页面,如下图选择版本点击即可下载二.下载及安装VMware下载地址:https://pan.baidu.com/s/1aEEI-DRa4oKeViddxW2CPA…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号