本帖最后由 UT发布 于 2025-5-16 11:12 编辑
第一步:自定义LWIP库版本号修改 复制一份你安装的版本的软件最新的库 修改如下文件: 修改lwip211.mld文件中的版本标识(如将OPTION VERSION =1.5;改为2.0),尽量改大一些,避免Vitis环境缓存旧库 第二步:修改LWIP库文件新增以太网芯片的适配 需要修改xemacpsif_physpeed.c或者xaxiemacif_physpeed.c文件,分别对应了ARM自带的以太网接口使用MIO实现以太网功能LWIP部分修改和PL部分基于AXI总线gig_ethernet_pcs_pma 以太网IP 扩展以太网使用 LWIP需要修改的文件。 1:添加,YT8531的PHY标识符 xemacpsif_physpeed.c或者xaxiemacif_physpeed.c文件中增加如下定义 #define PHY_YT8531_IDENTIFIER 0x4f51 2:ARM自带的以太网接口xemacpsif_physpeed.c文件修改 第一个修改位置:
- void detect_phy(XEmacPs *xemacpsp)
- {
- u16_t phy_reg;
- u32_t phy_addr;
- u32_t emacnum;
-
- if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR)
- emacnum = 0;
- else
- emacnum = 1;
- for (phy_addr = 31; phy_addr > 0; phy_addr--) {
- XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
- &phy_reg);
-
- if ((phy_reg != 0xFFFF) &&
- ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
- /* Found a valid PHY address */
- LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
- phy_addr));
- if (emacnum == 0)
- phymapemac0[phy_addr] = TRUE;
- else
- phymapemac1[phy_addr] = TRUE;
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
- &phy_reg);
- if ((phy_reg != PHY_MARVELL_IDENTIFIER) &&
- (phy_reg != PHY_TI_IDENTIFIER) &&
- (phy_reg != PHY_REALTEK_IDENTIFIER) &&
- (phy_reg != PHY_YT8531_IDENTIFIER))
-
- {
- xil_printf("WARNING: Not a Marvell or TI or Realtek or YT8531 Ethernet PHY. Please verify the initialization sequence\r\n");
- }
- }
- }
- }
复制代码
第二个修改的位置: - static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
- {
- u16_t phy_identity;
- u32_t RetStatus;
-
- XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
- &phy_identity);
- if (phy_identity == PHY_TI_IDENTIFIER) {
- RetStatus = get_TI_phy_speed(xemacpsp, phy_addr);
- } else if (phy_identity == PHY_REALTEK_IDENTIFIER) {
- RetStatus = get_Realtek_phy_speed(xemacpsp, phy_addr);
- } else if (phy_identity == PHY_YT8531_IDENTIFIER) {
- RetStatus = get_YT8531_phy_speed(xemacpsp, phy_addr);
- } else {
- RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr);
- }
-
- return RetStatus;
- }
复制代码
第三个修改位置: 复制代码中已经有的get_Realtek_phy_speed函数,修改为,get_YT8531_phy_speed函数,并且对读取的速率寄存器部分修改,读取的值含义对照YT8531芯片手册进行速率部分转换为1000/100/10三种速度 - static u32_t get_YT8531_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 YT8531 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");
-
- //YT8531 REG
- XEmacPs_PhyRead(xemacpsp, phy_addr,0X11,&status_speed);
- status_speed = status_speed>>8;
-
- if (status_speed & 0x04) {
- temp_speed = status_speed & 0xc0;
-
- if (temp_speed == 0x80)
- return 1000;
- else if(temp_speed == 0x40)
- return 100;
- else
- return 10;
-
- }
- return XST_FAILURE;
- }
复制代码
3:PL扩展xaxiemacif_physpeed.c文件的修改 第一个修改位置: - detect_phy函数中增加对该PHY的识别
- static int detect_phy(XAxiEthernet *xaxiemacp)
- {
- u16 phy_reg;
- u16 phy_id;
- u32 phy_addr;
-
- for (phy_addr = 31; phy_addr > 0; phy_addr--)
- {
- if(PHY_ADDR_CNT_UP)
- phy_addr = 32 - phy_addr;
-
- XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_DETECT_REG,
- &phy_reg);
-
- if ((phy_reg != 0xFFFF) &&
- ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
- /* Found a valid PHY address */
- LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet detect_phy: PHY detected at address %d.\r\n", phy_addr));
- LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet detect_phy: PHY detected.\r\n"));
- XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_1_REG,
- &phy_reg);
- if ((phy_reg != PHY_MARVELL_IDENTIFIER) &&
- (phy_reg != TI_PHY_IDENTIFIER) &&
- (phy_reg != PHY_REALTEK_IDENTIFIER)&&
- (phy_reg != PHY_YT8531_IDENTIFIER)
- ){
- xil_printf("WARNING: Not a Marvell or TI Ethernet PHY. Please verify the initialization sequence\r\n");
- }
- phyaddrforemac = phy_addr;
- return phy_addr;
- }
-
- XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_1_REG,
- &phy_id);
-
- if (phy_id == PHY_XILINX_PCS_PMA_ID1) {
- XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_2_REG,
- &phy_id);
- if (phy_id == PHY_XILINX_PCS_PMA_ID2) {
- /* Found a valid PHY address */
- LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet detect_phy: PHY detected at address %d.\r\n",
- phy_addr));
- phyaddrforemac = phy_addr;
- return phy_addr;
- }
- }
- }
-
- LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet detect_phy: No PHY detected. Assuming a PHY at address 0\r\n"));
-
- /* default to zero */
- return 0;
- }
复制代码
第二个修改位置: get_IEEE_phy_speed函数中,增加对以太网芯片速率识别的调用 - unsigned get_IEEE_phy_speed(XAxiEthernet *xaxiemacp)
- {
- u16 phy_identifier;
- u16 phy_model;
- u8 phytype;
-
- #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_YT8531_IDENTIFIER)
- {
- return get_YT8531_phy_speed(xaxiemacp, phy_addr);
-
- }
- else if(phy_identifier == PHY_REALTEK_IDENTIFIER)
- {
- return get_Realtek_phy_speed(xaxiemacp, phy_addr);
- }
- else {
- LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet get_IEEE_phy_speed: Detected PHY with unknown identifier/model.\r\n"));
- }
- #endif
- #ifdef PCM_PMA_CORE_PRESENT
- return get_phy_negotiated_speed(xaxiemacp, phy_addr);
- #endif
- }
复制代码
第三个修改位置: 该代码需要复制xemacpsif_physpeed.c代码中已经有的get_Realtek_phy_speed函数,修改为,get_YT8531_phy_speed函数,并且基于AXI接口读取寄存器的函数进行修改,最后对读取的速率寄存器部分修改,读取的值含义对照YT8531芯片手册进行速率部分转换为1000/100/10三种速度 - static u32_t get_YT8531_phy_speed(XAxiEthernet *xaxiemacp, 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 YT8531 PHY autonegotiation \r\n");
-
- 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);
-
- 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;
- }
-
- XAxiEthernet_PhyRead(xaxiemacp, 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;
- }
- XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
- }
- xil_printf("autonegotiation complete \r\n");
-
- XAxiEthernet_PhyRead(xaxiemacp, phy_addr,0X11,&status_speed);
- status_speed = status_speed>>8;
-
- if (status_speed & 0x04) {
- temp_speed = status_speed & 0xc0;
-
- if (temp_speed == 0x80)
- return 1000;
- else if(temp_speed == 0x40)
- return 100;
- else
- return 10;
-
- }
-
- return XST_FAILURE;
- }
复制代码
|