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

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

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

1.png

修改如下文件:

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

2.png

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

3.png


需要修改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文件修改

第一个修改位置:

  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. }

文章来源:米联客