1. 程式人生 > 實用技巧 >米聯ZYNQ7Z020系列的乙太網網口晶片RTL8211FD自適應速度的問題

米聯ZYNQ7Z020系列的乙太網網口晶片RTL8211FD自適應速度的問題

1.問題描述

本人使用的vivado版本時2019.1,此版本中的lwip版本為lwip211V1.0,雖然程式碼中已經有關於Realtek晶片的識別定義,但是點選自動識別還是顯示phy setup error,借鑑了米聯官方的改庫教程之後終於成功解決自適應速度的問題。


2.未改庫之前的自適應程式執行結果:

3.改庫的步驟:

首先右鍵工程對應的BSP工程,點選board support package settings,然後勾選LWIP211_v_1_0,

然後選擇Overview->standalone->lwip211,將temac_adapter_options中phy_link_ speed改為Autodetect。


返回對應的BSP工程,找到libsrc下的lwip211_v1_0,在其中找到xmacpsif _physpeed.c檔案

將原有的get_Realtek_phy_speed函式全部註釋或者刪除,更換為米聯提供的程式碼:

然後儲存檔案,BSP會自動進行編譯。改庫即可成功。

改庫之後可以成功執行:

改庫的程式碼如下:

static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
{
u16_t temp;
u16_t control;
u16_t status;
u16_t status_speed;

u32_t timeout_counter = 0;

xil_printf("Start PHY autonegotiation \r\n");
XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);

XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 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;
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
control);
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
&control);
control |= (7 << 12); /* max number of gigabit attempts */
control |= (1 << 11); /* enable downshift */
XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
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);
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp);
timeout_counter++;
if (timeout_counter == 30)
{
xil_printf("Auto negotiation error \r\n");
return 0;
}
XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
}
xil_printf("autonegotiation complete \r\n");
XEmacPs_PhyRead(xemacpsp, phy_addr,0x1A, &status_speed);
if ( (status_speed & 0x30) == 0x20)/* 1000Mbps */
return 1000;
else if ( (status_speed & 0x30) == 0x10)/* 100Mbps */
return 100;
else if ( (status_speed & 0x30) == 0x00)/* 10Mbps */
return 10;

return XST_FAILURE;
}