lwip支持Phy芯片RTL8211FD的方法

参考资料:


[1].米联ZYNQ7Z020系列的以太网网口芯片RTL8211FD自适应速度的解决方案(good)

[2].RTL8211(工/商)业级网口芯片bsp自适应修改vivado2019.2

[3].vitis-sdk-lwip RTL8211FD(I)业级网口芯片自适应修改最简办法


原因:XILINX官方默认的lwip bsp驱动暂时不支持RTL8211网口芯片。

问题现象如下:

用xilinx官方lwip操作网口Phy芯片RTL8211FD设置错误

解决办法:

手动修改lwip库文件以支持该芯片,不同版本工具之间的修改方式大同小异。

vivado2019.1(参考[1])

步骤1:在工程的BSP中选择lwpi211,如图1。

步骤2:lwip的选项phy_link_speed设为Autodetect,如图2.

步骤3:修改工程中xemacpsif _physpeed.c中的get_Realtek_phy_speed()函数,注释原来的代码,然后用米联客的替代。如图3及代码。

步骤4:重新编译工程即可。


图1. 在工程的BSP中选择lwpi211


图2. phy_link_speed设为Autodetect


图3.找到xemacpsif _physpeed.c

工业级RTL8211对应的代码(速度信息在寄存器0x1A中),参考[2]. 商业级RTL8211对应的代码也在参考[2]中。

//工业级RTL8211的代码(注释掉原来代码)

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); /* 工业级 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_FAILURE;

}

//商业级RTL8211的代码

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_FAILURE;

}

Vitis的修改方法

参考[2](lwip211_v1.1)和[3](lwip211_v2.0)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容