ZYNQ使用88E1510 PHY芯片的驱动程序

SDK V2014.4
PHY 88E1510
PL端以太网,自协商
standalone应用程序

PL端设计,略。
根据PL端生成的hdf,新建项目,采用官方lwip echo server例程。发现运行结果为

-----lwIP TCP echo server ------
TCP packets sent to port 6001 will be echoed back
auto-negotiated link speed: 69073

很明显不对。

1、调试发现运行到 xaxiemacif_physpeed.c文件中的get_IEEE_phy_speed()函数时,phy_model = 464 = 0x1D0,不属于例程自带的以下两个型号:

if (phy_identifier == MARVEL_PHY_IDENTIFIER) {
    
    
	if (phy_model == MARVEL_PHY_88E1116R_MODEL) {
    
    
		return get_phy_speed_88E1116R(xaxiemacp, phy_addr);
	} else if (phy_model == MARVEL_PHY_88E1111_MODEL) {
    
    
		return get_phy_speed_88E1111(xaxiemacp, phy_addr);
	}
}

2、所以加入该型号的驱动函数:

#define MARVEL_PHY_88E1510_MODEL  				0x1D0

unsigned get_phy_speed_88E1510(XAxiEthernet *xaxiemacp, u32 phy_addr)
{
    
    
	u16 temp;
	u16 phy_identifier;
	u16 phy_model;
	u16 control;
	u16 status;
	u16 partner_capabilities;

	xil_printf("in get_phy_speed_88E1510.\r\n");//FOR DEBUG
	/* Get the PHY Identifier and Model number */
	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 2, &phy_identifier);
	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 3, &phy_model);
	phy_model = phy_model & PHY_MODEL_NUM_MASK;

	XAxiEthernet_PhyWrite(xaxiemacp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
	//control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
	control &= ~(0x10);
	XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_CONTROL_REG_MAC, control);

	XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);

	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
	control |= IEEE_ASYMMETRIC_PAUSE_MASK;
	control |= IEEE_PAUSE_MASK;
	control |= ADVERTISE_100;
	control |= ADVERTISE_10;
	XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);

	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &control);
	control |= ADVERTISE_1000;
	XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, control);

	XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, &control);
	control |= (7 << 12);	/* max number of gigabit attempts */
	control |= (1 << 11);	/* enable downshift */
	XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, control);
	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
	control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
	control |= IEEE_STAT_AUTONEGOTIATE_RESTART;

	XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);


	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
	control |= IEEE_CTRL_RESET_MASK;
	XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);

	while (1) {
    
    
		XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
		if (control & IEEE_CTRL_RESET_MASK)
			continue;
		else
			break;
	}
	xil_printf("Waiting for PHY to complete autonegotiation.\r\n");

	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
	while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) )
	{
    
    
		sleep(1);
		XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp);
		if (temp & IEEE_AUTONEG_ERROR_MASK)
		{
    
    
			xil_printf("Auto negotiation error \r\n");
		}
		XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
	}
	xil_printf("autonegotiation complete \r\n");

	XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);

	if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */
		return 1000;
	else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */
		return 100;
	else					/* 10Mbps */
		return 10;
}

3、然后将 get_IEEE_phy_speed()函数改为:

if (phy_identifier == MARVEL_PHY_IDENTIFIER) {
    
    
	if (phy_model == MARVEL_PHY_88E1116R_MODEL) {
    
    
		return get_phy_speed_88E1116R(xaxiemacp, phy_addr);
	} else if (phy_model == MARVEL_PHY_88E1111_MODEL) {
    
    
		return get_phy_speed_88E1111(xaxiemacp, phy_addr);
	}
	//新加
	else if (phy_model == MARVEL_PHY_88E1510_MODEL) {
    
    
		return get_phy_speed_88E1510(xaxiemacp, phy_addr);
	}
}

4、编译运行结果正确:

-----lwIP TCP echo server ------
TCP packets sent to port 7 will be echoed back
in get_phy_speed_88E1510.
Waiting for PHY to complete autonegotiation.
autonegotiation complete
auto-negotiated link speed: 1000
Board IP: 192.168.1.10
Netmask : 255.255.255.0
Gateway : 192.168.1.1
TCP echo server started @ port 7

5、官方例程是回显网口数据,即在网口输入什么就输出什么,如果想在串口也输出,可以改下recv_callback()函数:

if (tcp_sndbuf(tpcb) > p->len) {
    
    
	err = tcp_write(tpcb, p->payload, p->len, 1);
	xil_printf("%s\n\r",(char*)( p->payload)); //加上这句话即可在串口也回显网口数据
} else
	xil_printf("no space in tcp_sndbuf\n\r");

猜你喜欢

转载自blog.csdn.net/LIU944602965/article/details/107021482