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");
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章