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

    文章

    5148

    浏览量

    126436
  • 嵌入式
    +关注

    关注

    5067

    文章

    19008

    浏览量

    302891
  • 以太网
    +关注

    关注

    40

    文章

    5371

    浏览量

    171024
  • 寄存器
    +关注

    关注

    31

    文章

    5308

    浏览量

    119975
  • 驱动
    +关注

    关注

    12

    文章

    1824

    浏览量

    85167
收藏 人收藏

    评论

    相关推荐

    聊一聊以太网发送描述符

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

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

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

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

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

    使用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 1748次阅读

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

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

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

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

    以太网滤波器平衡测试

    以太网滤波器平衡测试是一种用于测量以太网信号传输过程中平衡特性的测试方法。平衡测试的目的是确保信号在传输过程中能够正确传输,避免信号失真或干
    的头像 发表于 12-14 09:21 405次阅读

    亚信推出低功耗AX88772E免驱动USB 2.0转百兆以太网芯片

    亚信电子最新推出的AX88772EUSB2.0转百兆以太网控制芯片,具有小封装、低功耗和免驱动(Driverless)的特性,不仅满足客户对节能减碳的产品需求,并可轻松实现简便地即插即用
    的头像 发表于 11-29 08:11 637次阅读
    亚信推出低功耗AX88772E免<b class='flag-5'>驱动</b>USB 2.0转百兆<b class='flag-5'>以太网</b>芯片