RTL8211D(I)业级网口芯片bsp自适应修改

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文件

测试

 

RTL8211FD是一种网络物理层芯片,常用于与Zynq芯片(一种嵌入式处理器)集成的系统中。它可以实现物理层接口的自协商和数据传输功能。 要将RTL8211FD与Zynq集成,需要进行一些配置和初始化。引用中提到了一种方法,可以在BSP工程中找到相应的文件,并对其进行修改。具体来说,要实现PHY的自协商,可以使用下列代码进行配置: ```c xil_printf("Start PHY autonegotiation \r\n"); XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control); control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK; XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control); ``` 此代码片段通过向PHY寄存器写入相应的值,启动了PHY的自协商过程,并配置了RGMII时钟延迟。 另外,引用中的代码展示了如何获取RTL8211FD的实际速度。通过读取PHY寄存器中的状态信息,可以获取实际的连接速度。 综上所述,要在Zynq系统中使用RTL8211FD,可以通过相应的配置和初始化代码来实现自协商和获取实际速度的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [米联ZYNQ7Z020系列的以太网网口芯片RTL8211FD自适应速度的问题](https://blog.csdn.net/qq_41779850/article/details/109055128)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值