RTL8211FS在xsdk下调试

RTL8211FS在zynq下调试@TOC

RTL8211介绍

RTL8211是一个系列的phy芯片,从uboot的驱动中看出,共有4个子系列(RTL8211B , RTL8211E, RTL8211F, RTL8211DN),每个系列的寄存器都有一定的差异,在初始化中不能用通用的驱动。

RTL8211FS在zynq裸机下调试遇到的问题

之前自己调试过RTL8211E,使用默认的xsdk程序即可正常工作,使用xsdk方式调试RTL8211FS,最开始是初始化错误,读取手册发现,现有的驱动主要是适配RTL8211E系列,RTL8211FS检测连接状态的特殊状态寄存器和RTL8211E并不相同,在get_Realtek_phy_speed()中尾部进行了修改

	XEmacPs_PhyRead(xemacpsp, phy_addr, 26, &status_speed);
	if (status_speed & IEEE_STAT_LINK_STATUS) {
		temp_speed = status_speed & 0x30;
		xil_printf("autonegotiation temp_speed=%x \r\n", temp_speed);
		if (temp_speed == 0x20)
			return 1000;
		else if(temp_speed == 0x10)
			return 100;
		else if(temp_speed == 0x0)
			return 10;
		else
			return 0;
	}

修改之后,初始化没有出现问题,插拔网线都能正常检测到,但是就是ping不通,找了一下没能找到原因,按以前的经验该调试延时寄存器,手册中没找到相关寄存器。

RTL8211FS在u-boot和Linux系统下测试

因为在裸机下调试没有成功,转向u-boot和linux,于是创建petaLinux工程,
然后导入硬件信息,对u-boot和linux驱动进行配置(默认是包含了realtek的phy驱动),编译完成后烧写到flash,发现uboot中网口正常工作,linux系统下网口也正常工作,此时又回到裸机下调试RTL8211FS.

RTL8211FS裸机驱动调试

经过u-boot和linux下的测试,phy芯片都能正常工作,于是就参考u-boot下rtl8211fs phy的驱动,将裸机下的操作流程按照u-boot下的步骤实现

static u32_t get_RTL8211F_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
{
	u16_t control;
	u16_t status,regval;
	u16_t status_speed;
	u32_t timeout_counter = 0;
	u32_t temp_speed;

	xil_printf("Start RTL8211F autonegotiation \r\n");

	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, IEEE_CTRL_RESET_MASK);
	XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1f, 0xd08);
	//XEmacPs_PhyRead(XEmacPs_PhyRead, phy_addr, 0x11, &control);
	control = 0x109; //u-boot 中:默认值或上0x100
	XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x11, control);
	XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1f, 0xd04);
	XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x10, 0x617f);
	XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1f, 0);

	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
	control |= IEEE_ASYMMETRIC_PAUSE_MASK;
	control |= IEEE_PAUSE_MASK;
	control |= ADVERTISE_100;
	control |= ADVERTISE_10;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);

	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
					&control);
	control |= ADVERTISE_1000;
	control =0x200;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
					control);

	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
	control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
	control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);

	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
	control |= IEEE_CTRL_RESET_MASK;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);

	while (1) {
		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
		if (control & IEEE_CTRL_RESET_MASK)
			continue;
		else
			break;
	}

	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);

	xil_printf("Waiting for PHY to complete autonegotiation.\r\n");

	while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
		sleep(1);
		timeout_counter++;

		if (timeout_counter == 30) {
			xil_printf("Auto negotiation error \r\n");
			return XST_FAILURE;
		}
		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
	}
	xil_printf("autonegotiation complete \r\n");

	XEmacPs_PhyRead(xemacpsp, phy_addr, 26, &status_speed);
	if (status_speed & IEEE_STAT_LINK_STATUS) {
		temp_speed = status_speed & 0x30;
		xil_printf("autonegotiation temp_speed=%x \r\n", temp_speed);
		if (temp_speed == 0x20)
			return 1000;
		else if(temp_speed == 0x10)
			return 100;
		else if(temp_speed == 0x0)
			return 10;
		else
			return 0;
	}

	return XST_FAILURE;
}

从上面的操作中可以看到一些寄存器在手册上根本没有,按照手册上的操作后,ping操作还是没能成功,后面搜索了一下rtl8211fs,通过前面大神趟过的坑,发现page 0xd08 reg 0x11需要写入一个0x109(uboot下默认写的是或上0x100),改了此寄存器就能正常ping通了。

在get_Realtek_phy_speed()函数中,最前面,加入如下一句话即可兼容原有驱动

	XEmacPs_PhyRead(xemacpsp, phy_addr, 3, &control);
	if(control ==0xc916){
		return get_RTL8211F_phy_speed(xemacpsp ,phy_addr );
	}

在此处发现有一位大佬是另外的一种修改方式,测试了效果非常好,以下是我稍加整理,能保持原有驱动兼容

static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
{
	u16_t control;
	u16_t status;
	u16_t status_speed;
	u32_t timeout_counter = 0;
	u32_t temp_speed;

	XEmacPs_PhyRead(xemacpsp, phy_addr, 3, &control);
	if(control ==0xc916){
	    XEmacPs_PhyRead(xemacpsp, phy_addr, 0x1F, &control);
	    XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, 0xD08);
	    XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x10, 0x5E);
	    XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x11, 0x100);
	    XEmacPs_PhyWrite(xemacpsp, phy_addr, 0x1F, 0xA42);
	    usleep(10);
	}

	xil_printf("Start PHY autonegotiation \r\n");

	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
	control |= IEEE_ASYMMETRIC_PAUSE_MASK;
	control |= IEEE_PAUSE_MASK;
	control |= ADVERTISE_100;
	control |= ADVERTISE_10;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);

	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
					&control);
	control |= ADVERTISE_1000;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
					control);

	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
	control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
	control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);

	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
	control |= IEEE_CTRL_RESET_MASK;
	XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);

	while (1) {
		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
		if (control & IEEE_CTRL_RESET_MASK)
			continue;
		else
			break;
	}

	XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);

	xil_printf("Waiting for PHY to complete autonegotiation.\r\n");

	while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
		sleep(1);
		timeout_counter++;

		if (timeout_counter == 30) {
			xil_printf("Auto negotiation error \r\n");
			return XST_FAILURE;
		}
		XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
	}
	xil_printf("autonegotiation complete \r\n");

	XEmacPs_PhyRead(xemacpsp, phy_addr, 3, &control);
	if(control ==0xc916){
		XEmacPs_PhyRead(xemacpsp, phy_addr, 26, &status_speed);
		if (status_speed & IEEE_STAT_LINK_STATUS) {
			temp_speed = status_speed & 0x30;
			xil_printf("autonegotiation temp_speed=%x \r\n", temp_speed);
			if (temp_speed == 0x20)
				return 1000;
			else if(temp_speed == 0x10)
				return 100;
			else if(temp_speed == 0x0)
				return 10;
			else
				return 0;
		}
	}


	XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG,
					&status_speed);
	if (status_speed & 0x400) {
		temp_speed = status_speed & IEEE_SPEED_MASK;

		if (temp_speed == IEEE_SPEED_1000)
			return 1000;
		else if(temp_speed == IEEE_SPEED_100)
			return 100;
		else
			return 10;
	}

	return XST_FAILURE;
}

以上两种修改方式差不多,在此感谢2位大佬的分享。

2位大佬的参考链接

u-boot下命令操作参考链接: link.
XSDK下参考链接: link.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值