ZYNQ. LwIP.PHY.KSZ9031RNX

新一块板子

米尔科技的 z-turn  使用的PHY芯片是Micrel的 KSZ9031RNX 而不是zedboard上的Marvell的。

直接使用lwip的echo server demo时会报错 , 无法启动。

在网上找了很久终于找到几篇关于这个问题的文章。

修改PHY的驱动 xemacpsif_physpeed.c 文件

该芯片的PHY Identifier 是 0x0022

bsp设置中修改参数以提速

MEM_SIZE 524288
MEMP_N_PBUF 1024
MEMP_N_TCP_SEG 1024

PBUF_POOL_SIZE 8192

TCP_MSS 4096
TCP_SND_BUF 65535
TCP_WND 65535

N_RX_DESCRIPTORS = 512
N_TX_DESCRIPTORS = 512

TCP_IP_TX_CHECKSUM_OFFLOAD= true
TCP_IP_RX_CHECKSUM_OFFLOAD= true

//********* 2018/11/27********

添加的代码

Code:

#define PHY_MICREL_IDENTIFIER                0x0022    //added by Liny


//added by Liny
static u32_t get_Micrel_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr)
{
    u16_t temp;
    u16_t control;
    u16_t status;
    u16_t status_speed;
    u32_t timeout_counter = 0;
    u32_t temp_speed;
    //u32_t phyregtemp;

    xil_printf("Start Micrel PHY autonegotiation  
");
    //Auto-negotiation Advertisement REG
    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);  //reg 0x04
    control |= IEEE_ASYMMETRIC_PAUSE_MASK;   //0x0800
    control |= IEEE_PAUSE_MASK;
    control |= ADVERTISE_100;
    control |= ADVERTISE_10;
    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
    //1000Basic-T Control REG
    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_COPPER_SPECIFIC_CONTROL_REG, &control);  //reg 0x0f
//    control |= (7 << 12);
//    control |= (1 << 11);
//    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, control);


    //basic Control
    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);        //reg 0x00
    control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
    control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
    XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
    //basic 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;
    }

    //read extended staus
    XEmacPs_PhyRead(xemacpsp, phy_addr, 0x0f, &status);
    xil_printf("extened status:0x%x 
",status);
    //read baisc status reg
    XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);

    xil_printf("Waiting for PHY to complete autonegotiation.
");

    while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
        sleep(1);
        XEmacPs_PhyRead(xemacpsp, phy_addr,
        IEEE_COPPER_SPECIFIC_STATUS_REG_2,  &temp);
        timeout_counter++;

        if (timeout_counter == 30) {
            xil_printf("Auto negotiation error 
");
            return XST_FAILURE;
        }
        XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
    }
    xil_printf("autonegotiation complete 
");

    //#define IEEE_1000BASE_STATUS_REG 0x0a
    #define MICREL_PHY_CONTROL_REG 0x1f
    //XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_SPECIFIC_STATUS_REG, &status_speed);
    //XEmacPs_PhyRead(xemacpsp, phy_addr,IEEE_1000BASE_STATUS_REG, &status_speed);
    //if (status_speed & 0x0800) {

    //xil_printf("micrel phy ksz9031 speed 1000 
");
    //return 1000;
    //}

    //modify by Liny
    XEmacPs_PhyRead(xemacpsp, phy_addr,MICREL_PHY_CONTROL_REG,
    &status_speed); // 读取寄存器17,改为31  0x1f  VS_PHY_CONTROL_REG  IEEE_SPECIFIC_STATUS_REG
    if (!(status_speed & 0x01)) {  //link on 原来0x400,第10 位
        xil_printf("PHY Link stutus:not failing 
");
        temp_speed = status_speed & 0x70; // 读取最高两位速度  [6:4]status_speed & IEEE_SPEED_MASK

        if (temp_speed == 0x40)//IEEE_SPEED_1000
            return 1000;
        else if(temp_speed == 0x20)//IEEE_SPEED_100
            return 100;
        else
            return 10;
    }

    return XST_SUCCESS;
}
//added by Liny

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);
    }
    //added by Liny
    else if(phy_identity == PHY_MICREL_IDENTIFIER){
    RetStatus = get_Micrel_phy_speed(xemacpsp, phy_addr);
    }
    //added by Liny
    else {
        RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr);
    }

    return RetStatus;
}

via:

https://forums.xilinx.com/t5/Embedded-Development-Tools/2015-4-lwip-KSZ9031-link-issues/m-p/696975

https://blog.csdn.net/yezizhangxinya/article/details/55805512?locationNum=4&fps=1

https://blog.csdn.net/he_wen_jie/article/details/51880845

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842366/Standalone+LWIP+library

https://blog.csdn.net/ma_cheng_yuan/article/details/78527205?utm_source=copy

原文地址:https://www.cnblogs.com/protogenoi/p/9779405.html