XILINX官方默認的lwip bsp驅動暫時不支持RTL8211網口芯片,在使用該網口的時候需要自己手動修改庫文件以支持該芯片,不同版本工具之間的修改方式大同小異,這邊僅以Vitis 2019.2爲例。
PS端網口以米聯客MZU07A board爲例:
Step1:首先,找到vitis ide安裝目錄下的LWIP庫的路徑,將其拷貝一份放到工程目錄下:
Step2:修改lwip211_v1_1\data\lwip211.mld文件(可用Notapad++等編輯器打開),將其中的版本編號
OPTION VERSION =1.1;
修改爲
OPTION VERSION = 1.2;;
Step3:打開lwip141_v2_0\src\contrib\ports\xilinx\netif\ xemacpsif_physpeed.c,進行如下修改
根據芯片手冊定義Realtek PHY芯片的ID
#define PHY_REALTEK_IDENTIFIER 0x001c |
Step4:在get_Marvell_phy_speed庫函數基礎上,對rtl8211的特殊狀態寄存器進行修改,然後保存
商業級RTL8211手冊PHYSR參數:
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;
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,0x11, &status_speed); /* Commercial RTL8211*/ if (status_speed & 0x400) { temp_speed = status_speed & 0xc000;
if (temp_speed == 0x8000) return 1000; else if(temp_speed == 0x4000) return 100; else return 10; }
return XST_SUCCESS; } |
工業級RTL8211手冊PHYSR參數:
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;
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,0X1A, &status_speed); /* Industrial RTL8211 */
if (status_speed & 0x04) { temp_speed = status_speed & 0x30;
if (temp_speed == 0x20) return 1000; else if(temp_speed == 0x10) return 100; else return 10; }
return XST_SUCCESS; } |
Step5:在vitis軟件中導入修改後的lwip庫的路徑(需根據實際情況更改此路徑,若不更改將產生錯誤)
Step6:導入庫文件後重啓SDK
Step7: 勾選lwip庫文件
Step8: 選擇lwip211_1.2版本
Step9: 選擇File->New->Application Project->lwip_echo_server
Step10:右擊lwip_testàDebug Asà Debug Configurations,然後單擊debug
Step11:單擊運行,查看輸出結果
PL端網口以米聯客MA703_100T爲例
Xilinx SDK 目錄下面 xaxiemacif_physpeed.c 文件裏面對 PHY 芯片有驅動,目前支持 MARVEL 和 TI 的部分 PHY 芯片,如果使用其他廠家的 PHY 芯片,需要更改驅動,否則協商不能通過。
打開fpga_prj\uisrc\07_sdk_src\lwip211_v1_1\src\contrib\ports\xilinx\netif\xaxiemacif_physpeed.c 源文件,增加宏定義
添加PHY ID的定義
以下驅動程序的修改僅支持工業級RTL8211的千兆協商
unsigned get_IEEE_phy_speed(XAxiEthernet *xaxiemacp) { u8 phytype; u16 phy_val; u16 phy_identifier; u16 phy_model; u16 control; u16 status; u16 partner_capabilities; u16 partner_capabilities_1000; u16 phylinkspeed; int TimeOut;
#ifdef XPAR_AXIETHERNET_0_BASEADDR u32 phy_addr = detect_phy(xaxiemacp);
/* Get the PHY Identifier and Model number */ XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_1_REG, &phy_identifier); XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_2_REG, &phy_model);
/* Depending upon what manufacturer PHY is connected, a different mask is * needed to determine the specific model number of the PHY. */ if (phy_identifier == MARVEL_PHY_IDENTIFIER) { phy_model = phy_model & MARVEL_PHY_MODEL_NUM_MASK;
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_identifier == TI_PHY_IDENTIFIER) { phy_model = phy_model & TI_PHY_DP83867_MODEL; phytype = XAxiEthernet_GetPhysicalInterface(xaxiemacp);
if (phy_model == TI_PHY_DP83867_MODEL && phytype == XAE_PHY_TYPE_SGMII) { return get_phy_speed_TI_DP83867_SGMII(xaxiemacp, phy_addr); }
if (phy_model == TI_PHY_DP83867_MODEL) { return get_phy_speed_TI_DP83867(xaxiemacp, phy_addr); } } else { if (phy_identifier==PHY_REALTEK_IDENTIFIER){ XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, 0x1A, 0x20); 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); } if (phy_identifier==PHY_REALTEK_IDENTIFIER){ XAxiEthernet_PhyRead(xaxiemacp, phy_addr, 0, &control); XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, 0,control | IEEE_CTRL_RESET_MASK); for(TimeOut=0;TimeOut<5000;TimeOut++); XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, 0x1A, 0x20); 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_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);
return 1000; } LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet get_IEEE_phy_speed: Detected PHY with unknown identifier/model.\r\n")); } |
設置BSP文件
測試