0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于DWC_ether_qos的以太网驱动开发-MDIO驱动编写与测试

嵌入式USB开发 来源:嵌入式USB开发 作者:嵌入式USB开发 2023-08-30 09:37 次阅读

本文转自公众号欢迎关注

一.前言

以太网驱动的编写与调试往往从MDIO接口开始,MDIO是MAC访问PHY的接口。实现通过MDIO对PHY进行操作才能配置PHY,所以实现MDIO读写是第一步。DWC_ether_qos提供了SMA模块,操作两个寄存器即可实现PHY寄存器的读写,比较简单方便,且支持C45和C22两种模式,另外有比较灵活的配置参数后面会详讲。

二.SMA模块介绍

DWC_ether_qos中SMA(Station Management Agent)是一种双线站管理接口(MIM:Station Management interface),即MDIO管理接口,通过SMA模块即MDIO接口可以访问PHY的寄存器。

其具备以下特征:

l时钟

IEEE 802.3中规定,MDC的最大操作频率(gmi_MDC_o)是2.5MHz。在DWC_ether_qos中,gmii_mdc_o时钟是从csr_i分频得到的,通过MAC_MDIO_Address寄存器中的CR字段配置,

要注意该分频值一般要使得MDC满足不大于2.5MHz的要求。如果系统支持更高的频率该分频也可以分频到大于2.5MHz的频率。

l模式选择:MAC_MDIO_Address 的C45E 配置使用C45还是C22格式。

l前导抑制:MAC_MDIO_Address的PSE控制是否发送只有一个bit的前导的帧。

l时钟保持与连续传输:MAC_MDIO_Address 的NTC可以配置MDIO帧发送完后时钟保持07个CLK。在此基础上还可以配置MAC_MDIO_Address 的BTB使能连续传输,此时不等07个时钟保持结束,Busy信号就会发送完帧后立即清除,软件可以开始下一次传输,否则需要等到配置的0~7个保持时钟之后Busy才会清除。BTB必须在NTC大于0时才能使能。

三. MDIO帧结构

MDIO帧的一些特征:

MDC一般是1MHz~2.5MHz。

MDIO引脚需要一个1.5k欧姆的上拉电阻,以在空闲和周转期间保持MDIO高电平。

MDC下降沿修改数据,上升沿锁存数据,这样使得数据的建立和保持时间都是半个周期。

高位先发送,高字节先发送。

参考

IEEE 802.3,Section 22.2.4.5

**3.1 **Clause 45

SMA支持在该模式下操作时的读后递增地址。

MAC_MDIO_Address 的C45E 配置为1使用C45.

字段描述
IDLEgmii_mdc_o无时钟,MDIO处于高阻态。通过外部MDIO上拉到高电平
PREAMBLE32 个连续的1,前导抑制模式则只有一个bit。
START包开始2’b00
OPCODE操作码■ 2’b00 读写地址寄存器■ 2’b01 读写数据, 读写完地址不递增■ 2’b10 读写数据,读写完地址自动递增■ 2’b11 读写数据,仅写完地址自动递增
PHY ADDR5-bit 的PHY地址,可以编码最多32 个PHY。
DEV ADDR5-bit 设备地址可以编码32个设备。
TATurnaround寄存器地址和帧的数据字段之间的2位时间间隔,以避免在读取事务期间发生争用。■ 2’bZ0: 读时 第一个bit MAC和PHY都处于高组态,第二个bit是PHY拉低。■ 2’b10: 写时 10都是MAC驱动。Z 表示三态
DATA/ADDRESS16-bit 值: 对于地址周期(OPCODE = 2'b00), 表示下一个周期需要访问的寄存器地址. 对于数据写周期,表示需要写入寄存器的数据内容. 对于read,post-read递增帧,表示从PHY读出的寄存器内容.

完成一次C45寄存器读写需要两步,第一步发送地址包,第二步再读写

图片

**3.2 ****Clause **22

MAC_MDIO_Address 的C45E 配置为0使用C22.

帧结构如下

字段描述
IDLEgmii_mdc_o无时钟,MDIO处于高阻态。通过外部MDIO上拉到高电平。
PREAMBLE32 个连续的1,前导抑制模式则只有一个bit。
START包开始2’b01
OPCODE■ 2’b01 写■ 2’b10 读
PHY ADDR5-bit 的PHY地址,可以编码最多32 个PHY。
REG ADDR5-bit 寄存器地址可以编码32个寄存器。寻址对应指定MMD的某一个寄存器。
TATurnaround寄存器地址和帧的数据字段之间的2位时间间隔,以避免在读取事务期间发生争用。■ 2’bZ0: 读时 第一个bit MAC和PHY都处于高组态,第二个bit是PHY拉低。■ 2’b10: 写时 10都是MAC驱动。Z 表示三态
DATA16-bit 值:■ 写时DWC_ether_qos 驱动MDIO■ 读时PHY 驱动MDIO

完成C22读写只需要一步

图片

读写波形如下

图片

3.3使用C22模式访问C45寄存器

使用C22访问C45寄存器

参考https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf

用13号寄存器作为命令寄存器,14号寄存器作为寄存器/数据寄存器

图片

图片

步骤如下,分为4步完成:

1.C22模式写寄存器13,高两位FN为00,低5位DEV设备地址。

2.C22模式将16位寄存器地址写入14号寄存器。

3.C22模式写寄存器13,高两位FN为01或者10或者11,低5位DEV设备地址。

4.读:转至步骤5。写:转至步骤6

5.C22模式读14号寄存器的16位内容。

6.C22模式将16位寄存器内容写入14号寄存器。

四.相关寄存器

MDIO操作仅需要两个寄存器

MAC_MDIO_Address和MAC_MDIO_Data

4.1 MAC_MDIO_Address

Offset: 0x200

PSE[27]: bit27,置位则只发送1bit的前导,否则发送32位的前导

BTB **[26]: **bit26,NTC 不为0时生效,NTC为0时不能设置为1.

设置为1时,NTC不为0时,MDIO发送完帧不等NTC个时钟就立即清除GB位,可以立即重新下一次读写。

设置为0,则等待NTC保持时钟之后GB才清除。

**PA[25:21] **5位的PHY地址

RDA[22:16] 对于C22模式的寄存器地址,C45的设备地址MMD。

NTC[14:12] MDIO帧的发送完后,MDC再保持该配置个时钟。

CR[11:8]:MDC时钟选择 一般配置为1~2.5MHz

0000: CSR clock = 60-100 MHz; MDC clock = CSR clock/42
0001: CSR clock = 100-150 MHz; MDC clock = CSR clock/62
0010: CSR clock = 20-35 MHz; MDC clock = CSR clock/16
0011: CSR clock = 35-60 MHz; MDC clock = CSR clock/26
0100: CSR clock = 150-250 MHz; MDC clock = CSR clock/102
0101: CSR clock = 250-300 MHz; MDC clock = CSR clock/124
0110, 0111: Reserved

1000: CSR clock/4
1001: CSR clock/6
1010: CSR clock/8
1011: CSR clock/10
1100: CSR clock/12
1101: CSR clock/14
1110: CSR clock/16
1111: CSR clock/18

SKAP[4]:只有C45E使能时才有,置位时不发送地址包

GOC_1_0[3:2]:

00: Reserved
01: Write
10: Post Read Increment Address for Clause 45 PHY
11: Read

C45E[1]: 使能C45模式

GB[0]: 软件写1触发读写操作,读写完硬件清零。

4.2 MAC_MDIO_Data

Offset: 0x204

图片

RA[31:16]:C45E模式时指定16位寄存器地址。

GD[15:0]:读出或者写入寄存器的16位值。

五.MDIO读写驱动

5.1 寄存器操作接口

实现基本的寄存器级别的操作接口,

后面再对关键参数MDC时钟,NTC,PSE等测试,抓取波形进行验证。

/*
 * GB_MASK bit0 置位,触发MDIO操作, 操作完GB_MASK位硬件清零
 */
GMAC_INLINE int gmac_cfg_mdio_address(uint8_t id, uint8_t pse, uint8_t btb, uint8_t phyadd, 
                                    uint8_t reg_dev, uint8_t ntc, uint32_t csrclk,
                                    uint8_t skap, uint8_t cmd, uint8_t c45)
{
    (void)id;
    uint32_t tmp = 0;
    uint8_t csr = GMAC_CLK_60_100MHZ;
    if(csrclk >= 250000000ul)
    {
        csr = GMAC_CLK_250_300MHZ;
    }
    else if(csrclk >= 150000000ul)
    {
        csr = GMAC_CLK_150_250MHZ;
    }
    else if(csrclk >= 100000000ul)
    {
        csr = GMAC_CLK_100_150MHZ;
    }
    else if(csrclk >= 60000000ul)
    {
        csr = GMAC_CLK_60_100MHZ;
    }
    else if(csrclk >= 35000000ul)
    {
        csr = GMAC_CLK_35_60MHZ;
    }
    else
    {
        csr = GMAC_CLK_20_35MHZ;
    }
    tmp = ((uint32_t)csr < < CR_OFFSET) 
            | ((uint32_t)cmd < < GOC_0_OFFSET) 
            | (uint32_t)GB_MASK 
            | (((uint32_t)reg_dev < < RDA_OFFSET) & RDA_MASK) 
            | (((uint32_t)phyadd < < PA_OFFSET) & PA_MASK)
            | (((uint32_t)pse < < PSE_OFFSET) & PSE_MASK)
            | (((uint32_t)btb < < BTB_OFFSET) & BTB_MASK)
            | (((uint32_t)ntc < < NTC_OFFSET) & NTC_MASK)
            | (((uint32_t)skap < < SKAP_OFFSET) & SKAP_MASK)
            | (((uint32_t)c45 < < C45E_OFFSET) & C45E_MASK);
    GMAC_WRITE_REG(CFG_MAC_MDIO_ADDRESS_ADDR, tmp);
    return 0;
}


GMAC_INLINE int gmac_get_mdio_data(uint8_t id, uint16_t* data, uint16_t* regaddr)
{
    (void)id;
    uint32_t tmp = 0;
    tmp = GMAC_READ_REG(CFG_MAC_MDIO_DATA_ADDR);
    if(data != (void*)0)
    {
        *data = (tmp & GD_MASK) > > GD_OFFSET;
    }
    if(regaddr != (void*)0)
    {
        *regaddr = (tmp & REG_ADDR_MASK) > > REG_ADDR_OFFSET;
    }
    return 0;
}


GMAC_INLINE int gmac_set_mdio_data(uint8_t id, uint16_t data, uint16_t regaddr)
{
    (void)id;
    uint32_t tmp = 0;
    tmp = (((uint32_t)regaddr<

1 MDC时钟

我这里时钟是60MHz,设置CR为0,即分频42,理论上60/42=1.429MHz

实测MDC频率为1.449MHz

图片

图片

设置CR为3,即分频26,理论上60/26=2.31MHz

实测MDC频率为2.326MHz

图片

图片

2 NTC

NTC=0,帧发送完后MDC立即结束

图片

图片

NTC=7,帧发送完后MDC保持7个CLK

图片

图片

3 PSE

PSE=0,发送32个前导1

图片

图片

PSE=1,发送1个前导1,可以看到这个PHY是不支持前导抑制的,即发送1个前导时不能读写。

图片

5.2 C22读写

驱动代码如下

int iot_gmac_mdio_read(uint8_t id, uint8_t phyadd, uint8_t reg, uint16_t *data, uint32_t clk)
{
    int timeout = IOT_GMAC_MDIO_TIMEOUT;
    while(gmac_is_mdio_busy(id) && (timeout-- > 0));
    if(timeout <= 0)
    {
        return -1;
    }


    gmac_cfg_mdio_address(id, 0, 0, phyadd, reg, 0, clk, 0, GMAC_CMD_PHY_RD, 0);


    timeout = IOT_GMAC_MDIO_TIMEOUT;
    while(gmac_is_mdio_busy(id) && (timeout-- > 0));
    if(timeout <= 0)
    {
        return -1;
    }


    gmac_get_mdio_data(id, data, (void*)0);
    return 0;
}


int iot_gmac_mdio_write(uint8_t id, uint8_t phyadd, uint8_t reg, uint16_t data, uint32_t clk)
{
    int timeout = IOT_GMAC_MDIO_TIMEOUT;
    while(gmac_is_mdio_busy(id) && (timeout-- > 0));
    if(timeout <= 0)
    {
        return -1;
    }


    gmac_set_mdio_data(id, data, 0);
    gmac_cfg_mdio_address(id, 0, 0, phyadd, reg, 0, clk, 0, GMAC_CMD_PHY_WR, 0);
    timeout = IOT_GMAC_MDIO_TIMEOUT;
    while(gmac_is_mdio_busy(id) && (timeout-- > 0));
    if(timeout <= 0)
    {
        return -1;
    }


    return 0;
}

如下是往0号寄存器写0x9040即Reset软复位PHY

图片

如下是读0号寄存器为0x1040即Reset软复位PHY完成,硬件自清零了Reset位。

图片

5.3 C45读写

驱动代码如下

int iot_gmac_mdio_readc45(uint8_t id, uint8_t phyadd, uint8_t dev, uint16_t reg, uint16_t *data, uint32_t clk)
{
    int timeout = IOT_GMAC_MDIO_TIMEOUT;
    while(gmac_is_mdio_busy(id) && (timeout-- > 0));
    if(timeout <= 0)
    {
        return -1;
    }
    gmac_set_mdio_data(id, 0, reg);
    gmac_cfg_mdio_address(id, 0, 0, phyadd, dev, 0, clk, 0, GMAC_CMD_PHY_RD, 1);


    timeout = IOT_GMAC_MDIO_TIMEOUT;
    while(gmac_is_mdio_busy(id) && (timeout-- > 0));
    if(timeout <= 0)
    {
        return -1;
    }


    gmac_get_mdio_data(id, data, (void*)0);
    return 0;
}


int iot_gmac_mdio_writec45(uint8_t id, uint8_t phyadd, uint8_t dev, uint16_t reg, uint16_t data, uint32_t clk)
{
    int timeout = IOT_GMAC_MDIO_TIMEOUT;
    while(gmac_is_mdio_busy(id) && (timeout-- > 0));
    if(timeout <= 0)
    {
        return -1;
    }


    gmac_set_mdio_data(id, data, reg);
    gmac_cfg_mdio_address(id, 0, 0, phyadd, dev, 0, clk, 0, GMAC_CMD_PHY_WR, 1);
    timeout = IOT_GMAC_MDIO_TIMEOUT;
    while(gmac_is_mdio_busy(id) && (timeout-- > 0));
    if(timeout <= 0)
    {
        return -1;
    }


    return 0;
}

波形如下:两个包,一个是地址包,一个是数据包

图片

图片

5.4 C22模式读写C45寄存器

以下是RTL8211F的MMD寄存器,不支持直接C45模式,但是支持C22模式读C45寄存器,

通过13和14号寄存器实现。

图片

驱动代码如下

int dwc_mdio_c22readc45(uint8_t id, uint8_t phyadd, uint8_t dev, uint16_t reg, uint16_t *data, uint32_t clk)
{
    iot_gmac_mdio_write(id, phyadd, 13, (0< < 14) | dev, clk);
    iot_gmac_mdio_write(id, phyadd, 14, reg, clk);
    iot_gmac_mdio_write(id, phyadd, 13, (1u< < 14) | dev, clk);
    iot_gmac_mdio_read(id, phyadd, 14, data, clk);
    return 0;
}


int dwc_mdio_c22writec45(uint8_t id, uint8_t phyadd, uint8_t dev, uint16_t reg, uint16_t data, uint32_t clk)
{
    iot_gmac_mdio_write(id, phyadd, 13, (0< < 14) | dev, clk);
    iot_gmac_mdio_write(id, phyadd, 14, reg, clk);
    iot_gmac_mdio_write(id, phyadd, 13, (1u< < 14) | dev, clk);
    iot_gmac_mdio_write(id, phyadd, 14, data, clk);
    return 0;
}

测试代码如下

uint16_t c45reg = 0;
    dwc_mdio_c22writec45(p_ctrl.unit,p_ctrl.phy_addr,3,0,1u< < 10,p_ctrl.clk);
    dwc_mdio_c22readc45(p_ctrl.unit,p_ctrl.phy_addr,3,0,&c45reg,p_ctrl.clk);
    printf("PC1R=%xrn",c45reg);
    c45reg = 0;
    dwc_mdio_c22readc45(p_ctrl.unit,p_ctrl.phy_addr,3,1,&c45reg,p_ctrl.clk);
    printf("PS1R=%xrn",c45reg);
    c45reg = 0;
    dwc_mdio_c22readc45(p_ctrl.unit,p_ctrl.phy_addr,3,20,&c45reg,p_ctrl.clk);
    printf("EEECR=%xrn",c45reg);
    c45reg = 0;
    dwc_mdio_c22readc45(p_ctrl.unit,p_ctrl.phy_addr,3,22,&c45reg,p_ctrl.clk);
    printf("EEEWER=%xrn",c45reg);
    c45reg = 0;
    dwc_mdio_c22readc45(p_ctrl.unit,p_ctrl.phy_addr,7,60,&c45reg,p_ctrl.clk);
    printf("EEEAR=%xrn",c45reg);
    c45reg = 0;
    dwc_mdio_c22readc45(p_ctrl.unit,p_ctrl.phy_addr,7,61,&c45reg,p_ctrl.clk);
    printf("EEELPAR=%xrn",c45reg);

打印结果如下

可以看到PC1R的bit10设置为了1,其他寄存器对照手册可以看到都是默认值

图片

波形如下

写4步完成

图片

读4步完成

图片

六. 总结

以太网驱动编写调试的第一步都是调通MDIO接口,重点是要去抓取信号分析实际的波形,比如寄存器的每一个参数对应波形的什么变化,这在驱动编写调试中很重要,一定要对寄存器每一个bit的功能都非常清晰。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 测试
    +关注

    关注

    8

    文章

    5269

    浏览量

    126599
  • 嵌入式
    +关注

    关注

    5082

    文章

    19104

    浏览量

    304815
  • 以太网
    +关注

    关注

    40

    文章

    5419

    浏览量

    171599
  • 寄存器
    +关注

    关注

    31

    文章

    5336

    浏览量

    120230
  • 驱动
    +关注

    关注

    12

    文章

    1838

    浏览量

    85262
收藏 人收藏

    评论

    相关推荐

    TOSUN 车载以太网仿真测试解决方案

    TOSUN车载以太网仿真测试解决方案随着自动驾驶、车联网和智能化系统的广泛应用,车载电子组件和传感器的数量与复杂性都在持续增加,为了满足这些更为复杂性的需求,车载以太网作为一种新型车载网络进入汽车网
    的头像 发表于 12-07 01:07 424次阅读
    TOSUN 车载<b class='flag-5'>以太网</b>仿真<b class='flag-5'>测试</b>解决方案

    聊一聊以太网发送描述符

    相对于其他总线,以太网的知识庞杂,当然,可获取的资料也丰富。以太网的知识从驱动层到上层协议栈,很难一下消化,所以,不妨从点开始,不断地拓展和链接,从而形成完整地以太网知识框架,进而更好
    的头像 发表于 10-22 15:09 322次阅读
    聊一聊<b class='flag-5'>以太网</b>发送描述符

    适用于工业应用的使用MDIO以太网PHY配置

    电子发烧友网站提供《适用于工业应用的使用MDIO以太网PHY配置.pdf》资料免费下载
    发表于 09-21 10:24 0次下载
    适用于工业应用的使用<b class='flag-5'>MDIO</b>的<b class='flag-5'>以太网</b>PHY配置

    Test House-第三方测试认证服务——以太网一致性PMA测试案例讲解#车载以太网

    以太网
    北汇信息POLELINK
    发布于 :2024年08月19日 18:38:12

    车载以太网线束传输性能——汽车线束故障定位实际测试结果分析#车载以太网

    车载以太网
    北汇信息POLELINK
    发布于 :2024年08月16日 18:13:19

    车载以太网与传统以太网的区别

    车载以太网与传统以太网在多个方面存在显著的差异,这些差异主要体现在传输速率、实时性、可靠性、物理层标准、应用场景以及技术发展等方面。
    的头像 发表于 07-25 11:12 1762次阅读

    Banana Pi BPI-M4 Berry 开源硬件开发以太网口和WiFi测试

    Banana Pi BPI-M4 Berry 开源硬件开发以太网口和WiFi测试
    的头像 发表于 07-02 16:16 882次阅读
    Banana Pi BPI-M4 Berry 开源硬件<b class='flag-5'>开发</b>板<b class='flag-5'>以太网</b>口和WiFi<b class='flag-5'>测试</b>

    CANape&VN5620监控记录以太网数据操作演示#车载以太网 #CANape

    车载以太网
    北汇信息POLELINK
    发布于 :2024年06月11日 15:53:15

    工业以太网和普通以太网区别在哪

    工业以太网和普通以太网是两种不同的以太网技术,它们在设计、性能、应用和可靠性等方面存在显著差异。本文将详细介绍这两种以太网技术的区别。 设计差异 工业
    的头像 发表于 06-11 10:30 2617次阅读

    使用VN5620监控记录以太网总线数据#车载以太网 #CANape

    以太网硬件
    北汇信息POLELINK
    发布于 :2024年06月09日 16:45:04

    车载以太网硬件接口VN5620设备展示与介绍#车载以太网

    车载以太网
    北汇信息POLELINK
    发布于 :2024年05月31日 10:27:03

    车载以太网接口VN5650使用场景介绍#车载以太网

    以太网
    北汇信息POLELINK
    发布于 :2024年05月11日 17:58:05

    以太网交换芯片是什么 以太网交换芯片的作用有哪些

    以太网交换芯片是一种专门设计用于处理以太网数据包的集成电路,它是网络交换机的核心组件。这种芯片负责在网络中转发数据包,确保数据能够从源端口传输到目的端口。以太网交换芯片的功能包括但不限于数据包的接收、过滤、转发、错误检测和处理,
    的头像 发表于 03-21 16:14 1920次阅读

    以太网MDIO协议工作原理与应用

    MDIO主机(即产生MDC时钟的设备)通常被称为STA(Station Management Entity),而MDIO从机通常被称为MMD(MDIO Management Device)。通常STA都是MAC层器件的一部分,而
    发表于 02-27 09:32 3359次阅读
    <b class='flag-5'>以太网</b>中<b class='flag-5'>MDIO</b>协议工作原理与应用

    汽车技术的未来:Netropy如何测试和确保汽车以太网的性能

    在汽车行业持续创新的今天,汽车以太网的性能和可靠性成为了关键焦点。如何测试和确保汽车以太网的性能?我们来看看BroadR-Reach技术如何革新车载网络,并通过综合性能测试来确保网络在
    的头像 发表于 01-20 08:04 535次阅读
    汽车技术的未来:Netropy如何<b class='flag-5'>测试</b>和确保汽车<b class='flag-5'>以太网</b>的性能