问答 店铺
热搜: ZYNQ FPGA discuz

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

微信扫一扫 分享朋友圈

已有 10 人浏览分享

开启左侧

针对VITIS无法支持的以太网芯片的LWIP库修改方法以(YT8531DH为例)

[复制链接]
10 0
本帖最后由 UT发布 于 2025-5-16 11:12 编辑

第一步:自定义LWIP库版本号修改

复制一份你安装的版本的软件最新的库

image.jpg

修改如下文件:

修改lwip211.mld文件中的版本标识(如将OPTION VERSION =1.5;改为2.0),尽量改大一些,避免Vitis环境缓存旧库

image.jpg

第二步:修改LWIP库文件新增以太网芯片的适配

image.jpg

需要修改xemacpsif_physpeed.c或者xaxiemacif_physpeed.c文件分别对应了ARM自带的以太网接口使用MIO实现以太网功能LWIP部分修改和PL部分基于AXI总线gig_ethernet_pcs_pma 以太网IP 扩展以太网使用 LWIP需要修改的文件。

1:添加,YT8531PHY标识符

xemacpsif_physpeed.c或者xaxiemacif_physpeed.c文件中增加如下定义

#define PHY_YT8531_IDENTIFIER               0x4f51

2:ARM自带的以太网接口xemacpsif_physpeed.c文件修改

第一个修改位置:

  1. void detect_phy(XEmacPs *xemacpsp)
  2. {
  3.     u16_t phy_reg;
  4.     u32_t phy_addr;
  5.     u32_t emacnum;
  6.     if (xemacpsp->Config.BaseAddress == XPAR_XEMACPS_0_BASEADDR)
  7.         emacnum = 0;
  8.     else
  9.         emacnum = 1;
  10.     for (phy_addr = 31; phy_addr > 0; phy_addr--) {
  11.         XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
  12.                             &phy_reg);
  13.         if ((phy_reg != 0xFFFF) &&
  14.             ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
  15.             /* Found a valid PHY address */
  16.             LWIP_DEBUGF(NETIF_DEBUG, ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
  17.                                                                     phy_addr));
  18.             if (emacnum == 0)
  19.                 phymapemac0[phy_addr] = TRUE;
  20.             else
  21.                 phymapemac1[phy_addr] = TRUE;
  22.             XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
  23.                             &phy_reg);
  24.             if ((phy_reg != PHY_MARVELL_IDENTIFIER) &&
  25.                 (phy_reg != PHY_TI_IDENTIFIER) &&
  26.                 (phy_reg != PHY_REALTEK_IDENTIFIER) &&
  27.                 (phy_reg != PHY_YT8531_IDENTIFIER))
  28.                
  29.                  {
  30.                 xil_printf("WARNING: Not a Marvell or TI or Realtek or YT8531 Ethernet PHY. Please verify the initialization sequence\r\n");
  31.             }
  32.         }
  33.     }
  34. }
复制代码

第二个修改的位置:

  1. static u32_t get_IEEE_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
  2. {
  3.     u16_t phy_identity;
  4.     u32_t RetStatus;
  5.     XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
  6.                     &phy_identity);
  7.     if (phy_identity == PHY_TI_IDENTIFIER) {
  8.         RetStatus = get_TI_phy_speed(xemacpsp, phy_addr);
  9.     } else if (phy_identity == PHY_REALTEK_IDENTIFIER) {
  10.         RetStatus = get_Realtek_phy_speed(xemacpsp, phy_addr);
  11.     } else if (phy_identity == PHY_YT8531_IDENTIFIER) {
  12.         RetStatus = get_YT8531_phy_speed(xemacpsp, phy_addr);
  13.     } else {
  14.         RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr);
  15.     }
  16.     return RetStatus;
  17. }
复制代码

第三个修改位置:

复制代码中已经有的get_Realtek_phy_speed函数,修改为,get_YT8531_phy_speed函数,并且对读取的速率寄存器部分修改,读取的值含义对照YT8531芯片手册进行速率部分转换为1000/100/10三种速度

  1. static u32_t get_YT8531_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
  2. {
  3.     u16_t control;
  4.     u16_t status;
  5.     u16_t status_speed;
  6.     u32_t timeout_counter = 0;
  7.     u32_t temp_speed;
  8. xil_printf("Start YT8531 PHY autonegotiation \r\n");
  9.     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
  10.     control |= IEEE_ASYMMETRIC_PAUSE_MASK;
  11.     control |= IEEE_PAUSE_MASK;
  12.     control |= ADVERTISE_100;
  13.     control |= ADVERTISE_10;
  14.     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
  15.     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  16.                     &control);
  17.     control |= ADVERTISE_1000;
  18.     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  19.                     control);
  20.     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  21.     control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
  22.     control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
  23.     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  24.     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  25.     control |= IEEE_CTRL_RESET_MASK;
  26.     XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  27.     while (1) {
  28.         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  29.         if (control & IEEE_CTRL_RESET_MASK)
  30.             continue;
  31.         else
  32.             break;
  33.     }
  34.     XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  35.     xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
  36.     while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
  37.         sleep(1);
  38.         timeout_counter++;
  39.         if (timeout_counter == 30) {
  40.             xil_printf("Auto negotiation error \r\n");
  41.             return XST_FAILURE;
  42.         }
  43.         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  44.     }
  45.     xil_printf("autonegotiation complete \r\n");
  46. //YT8531 REG
  47.     XEmacPs_PhyRead(xemacpsp, phy_addr,0X11,&status_speed);
  48.     status_speed = status_speed>>8;
  49.     if (status_speed & 0x04) {
  50.         temp_speed = status_speed & 0xc0;
  51.         if (temp_speed == 0x80)
  52.             return 1000;
  53.         else if(temp_speed == 0x40)
  54.             return 100;
  55.         else
  56.             return 10;
  57.     }
  58.     return XST_FAILURE;
  59. }
复制代码
3:PL扩展xaxiemacif_physpeed.c文件的修改
第一个修改位置:
  1. detect_phy函数中增加对该PHY的识别
  2. static int detect_phy(XAxiEthernet *xaxiemacp)
  3. {
  4.     u16 phy_reg;
  5.     u16 phy_id;
  6.     u32 phy_addr;
  7.     for (phy_addr = 31; phy_addr > 0; phy_addr--)
  8.     {
  9.         if(PHY_ADDR_CNT_UP)
  10.             phy_addr = 32 - phy_addr;
  11.         XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_DETECT_REG,
  12.                                 &phy_reg);
  13.         if ((phy_reg != 0xFFFF) &&
  14.             ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
  15.             /* Found a valid PHY address */
  16.             LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet detect_phy: PHY detected at address %d.\r\n", phy_addr));
  17.             LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet detect_phy: PHY detected.\r\n"));
  18.             XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_1_REG,
  19.                                         &phy_reg);
  20.             if ((phy_reg != PHY_MARVELL_IDENTIFIER) &&
  21.                     (phy_reg != TI_PHY_IDENTIFIER) &&
  22.                     (phy_reg != PHY_REALTEK_IDENTIFIER)&&
  23.                     (phy_reg != PHY_YT8531_IDENTIFIER)
  24.                     ){
  25.                 xil_printf("WARNING: Not a Marvell or TI Ethernet PHY. Please verify the initialization sequence\r\n");
  26.             }
  27.             phyaddrforemac = phy_addr;
  28.             return phy_addr;
  29.         }
  30.         XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_1_REG,
  31.                 &phy_id);
  32.         if (phy_id == PHY_XILINX_PCS_PMA_ID1) {
  33.             XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_2_REG,
  34.                     &phy_id);
  35.             if (phy_id == PHY_XILINX_PCS_PMA_ID2) {
  36.                 /* Found a valid PHY address */
  37.                 LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet detect_phy: PHY detected at address %d.\r\n",
  38.                             phy_addr));
  39.                 phyaddrforemac = phy_addr;
  40.                 return phy_addr;
  41.             }
  42.         }
  43.     }
  44.     LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet detect_phy: No PHY detected.  Assuming a PHY at address 0\r\n"));
  45.         /* default to zero */
  46.     return 0;
  47. }
复制代码

第二个修改位置:

get_IEEE_phy_speed函数中,增加对以太网芯片速率识别的调用

  1. unsigned get_IEEE_phy_speed(XAxiEthernet *xaxiemacp)
  2. {
  3.     u16 phy_identifier;
  4.     u16 phy_model;
  5.     u8 phytype;
  6. #ifdef XPAR_AXIETHERNET_0_BASEADDR
  7.     u32 phy_addr = detect_phy(xaxiemacp);
  8.     /* Get the PHY Identifier and Model number */
  9.     XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_1_REG, &phy_identifier);
  10.     XAxiEthernet_PhyRead(xaxiemacp, phy_addr, PHY_IDENTIFIER_2_REG, &phy_model);
  11. /* Depending upon what manufacturer PHY is connected, a different mask is
  12. * needed to determine the specific model number of the PHY. */
  13.     if (phy_identifier == MARVEL_PHY_IDENTIFIER) {
  14.         phy_model = phy_model & MARVEL_PHY_MODEL_NUM_MASK;
  15.         if (phy_model == MARVEL_PHY_88E1116R_MODEL) {
  16.             return get_phy_speed_88E1116R(xaxiemacp, phy_addr);
  17.         } else if (phy_model == MARVEL_PHY_88E1111_MODEL) {
  18.             return get_phy_speed_88E1111(xaxiemacp, phy_addr);
  19.         }
  20.     }
  21.     else if (phy_identifier == TI_PHY_IDENTIFIER) {
  22.         phy_model = phy_model & TI_PHY_DP83867_MODEL;
  23.         phytype = XAxiEthernet_GetPhysicalInterface(xaxiemacp);
  24.         if (phy_model == TI_PHY_DP83867_MODEL && phytype == XAE_PHY_TYPE_SGMII) {
  25.             return get_phy_speed_TI_DP83867_SGMII(xaxiemacp, phy_addr);
  26.         }
  27.         if (phy_model == TI_PHY_DP83867_MODEL) {
  28.             return get_phy_speed_TI_DP83867(xaxiemacp, phy_addr);
  29.         }
  30.     }
  31.     else if(phy_identifier == PHY_YT8531_IDENTIFIER)
  32.     {
  33.         return get_YT8531_phy_speed(xaxiemacp, phy_addr);
  34.     }
  35.     else if(phy_identifier == PHY_REALTEK_IDENTIFIER)
  36.     {
  37.         return get_Realtek_phy_speed(xaxiemacp, phy_addr);
  38.     }
  39.     else {
  40.         LWIP_DEBUGF(NETIF_DEBUG, ("XAxiEthernet get_IEEE_phy_speed: Detected PHY with unknown identifier/model.\r\n"));
  41.     }
  42. #endif
  43. #ifdef PCM_PMA_CORE_PRESENT
  44.     return get_phy_negotiated_speed(xaxiemacp, phy_addr);
  45. #endif
  46. }
复制代码

第三个修改位置:

该代码需要复制xemacpsif_physpeed.c代码中已经有的get_Realtek_phy_speed函数,修改为,get_YT8531_phy_speed函数,并且基于AXI接口读取寄存器的函数进行修改,最后对读取的速率寄存器部分修改,读取的值含义对照YT8531芯片手册进行速率部分转换为1000/100/10三种速度

  1. static u32_t get_YT8531_phy_speed(XAxiEthernet *xaxiemacp, u32_t phy_addr)
  2. {
  3.     u16_t control;
  4.     u16_t status;
  5.     u16_t status_speed;
  6.     u32_t timeout_counter = 0;
  7.     u32_t temp_speed;
  8.     xil_printf("Start YT8531 PHY autonegotiation \r\n");
  9.     XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
  10.     control |= IEEE_ASYMMETRIC_PAUSE_MASK;
  11.     control |= IEEE_PAUSE_MASK;
  12.     control |= ADVERTISE_100;
  13.     control |= ADVERTISE_10;
  14.     XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
  15.     XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  16.                     &control);
  17.     control |= ADVERTISE_1000;
  18.     XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
  19.                     control);
  20.     XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  21.     control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
  22.     control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
  23.     XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  24.     XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  25.     control |= IEEE_CTRL_RESET_MASK;
  26.     XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
  27.     while (1) {
  28.         XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
  29.         if (control & IEEE_CTRL_RESET_MASK)
  30.             continue;
  31.         else
  32.             break;
  33.     }
  34.     XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  35.     xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
  36.     while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
  37.         sleep(1);
  38.         timeout_counter++;
  39.         if (timeout_counter == 30) {
  40.             xil_printf("Auto negotiation error \r\n");
  41.             return XST_FAILURE;
  42.         }
  43.         XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  44.     }
  45.     xil_printf("autonegotiation complete \r\n");
  46.     XAxiEthernet_PhyRead(xaxiemacp, phy_addr,0X11,&status_speed);
  47.     status_speed = status_speed>>8;
  48.     if (status_speed & 0x04) {
  49.         temp_speed = status_speed & 0xc0;
  50.         if (temp_speed == 0x80)
  51.             return 1000;
  52.         else if(temp_speed == 0x40)
  53.             return 100;
  54.         else
  55.             return 10;
  56.     }
  57.     return XST_FAILURE;
  58. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

0

粉丝

304

主题
精彩推荐
热门资讯
网友晒图
图文推荐

  • 微信公众平台

  • 扫描访问手机版