<RT1176系列9>ENET入门级应用和基础API解析(PHY配置)

1、概述

        本文通过NXP官方SDK讲解如何移植ENET的驱动,面向刚入门的小白。

官方IDE:MCUXpresso,SDK:MIMXRT1170-EVK。

2、SDK工程导入

        详细步骤参照文章:<RT1176系列3>LPSPI入门级应用和基础API解析-CSDN博客

        这次导入ENET_1G的例程做代码分析:

3、MDIO/MDC

3.1 定义

        MDIO(Management Data Input/Output,管理数据输入 / 输出)是一种用于以太网物理层(PHY)和媒体访问控制层(MAC)之间进行管理通信的标准接口,广泛应用于嵌入式系统和网络设备中。它定义了一套简单的总线协议,让 MAC 能够读取和配置 PHY 的寄存器,从而实现对 PHY 工作状态的监控、模式设置(如速率、双工模式)、故障诊断等功能。

3.2 MDIO 的核心组成

MDIO 接口由两条信号线组成,二者共同构成管理总线:

  • MDC(Management Data Clock,管理数据时钟):由 MAC 提供的时钟信号,用于同步 MDIO 总线上的数据传输。时钟频率通常在 10MHz 以下(常见为 2.5MHz 或 5MHz,具体需参考 PHY 芯片手册)。
  • MDIO(Management Data Input/Output,管理数据输入 / 输出):双向数据线,用于 MAC 和 PHY 之间传输管理数据(寄存器地址、读写命令、数据值等)。

3.3 MDIO 的通信协议

        MDIO 采用主从式通信模式(MAC 为主机,PHY 为从机),通过一套固定的帧格式实现数据传输。每次通信由 MAC 发起,帧结构包含以下关键部分(共 32 位):

位段功能描述
前导码(2 位)固定为 “01”,表示帧的开始(Start of Frame,SOF)。
操作码(2 位)定义操作类型:“10” 表示读操作,“01” 表示写操作。
PHY 地址(5 位)标识目标 PHY 的地址(0-31),由 PHY 的硬件引脚(如 PHYAD0~PHYAD4)配置,用于在多 PHY 系统中区分不同设备。
寄存器地址(5 位)表示要访问的 PHY 内部寄存器编号(0-31),不同 PHY 的寄存器功能不同(需参考手册)。
turnaround(2 位)用于切换 MDIO 总线的方向(从 MAC 输出到 PHY 输入,或反之),避免总线冲突。读操作时为 “10”,写操作时为 “01”。
数据(16 位)读操作时,PHY 返回的寄存器值;写操作时,MAC 发送的要写入寄存器的数据。

3.4 MDIO 使用注意事项

1)PHY 地址唯一性:多 PHY 系统中,每个 PHY 的地址必须不同(通过硬件引脚设置),否则会导致 MDIO 通信冲突。

2)时钟频率限制:MDC 时钟频率需符合 PHY 芯片要求(通常≤10MHz),过高会导致数据传输错误。

3)总线空闲状态:MDIO 线需通过上拉电阻(通常 10kΩ)保持空闲时为高电平,避免噪声干扰。

4)操作时序:需严格遵循协议规定的时序(如建立时间、保持时间),尤其是在高速通信时。

3.5 时序图

4、PHY部分代码解析

4.1 RESET PHY

        上电复位PHY,优点是可以保证PHY每次上电工作正常,缺点是热复位时复位phy会导致以太网断一下。 IOMUXC_GPR_GPR5_ENET1G_RGMII_EN_MASK,配置GPR5的RGMII_EN位,使得可以使用千兆网。

IOMUXC_GPR->GPR5 |= IOMUXC_GPR_GPR5_ENET1G_RGMII_EN_MASK; /* bit1:iomuxc_gpr_enet_clk_dir
bit0:GPR_ENET_TX_CLK_SEL(internal or OSC) */
GPIO_PinInit(GPIO11, 14, &gpio_config);
/* For a complete PHY reset of RTL8211FDI-CG, this pin must be asserted low for at least 10ms. And
* wait for a further 30ms(for internal circuits settling time) before accessing the PHY register */
SDK_DelayAtLeastUs(10000, CLOCK_GetFreq(kCLOCK_CpuClk));
GPIO_WritePinOutput(GPIO11, 14, 1);
SDK_DelayAtLeastUs(30000, CLOCK_GetFreq(kCLOCK_CpuClk));

4.2 配置phy句柄

        通过定义phy_ops获取相关phy操作的接口,这种写法非常规范,代码直接分割的很清晰。

extern phy_rtl8211f_resource_t g_phy_resource;
#define EXAMPLE_ENET ENET_1G
#define EXAMPLE_PHY_ADDRESS 0x01U
#define EXAMPLE_PHY_OPS &phyrtl8211f_ops
#define EXAMPLE_PHY_RESOURCE &g_phy_resource

typedef struct _phy_rtl8211f_resource
{
mdioWrite write;
mdioRead read;
} phy_rtl8211f_resource_t;

extern phy_rtl8211f_resource_t g_phy_resource;
#define EXAMPLE_ENET ENET_1G
#define EXAMPLE_PHY_ADDRESS 0x01U
#define EXAMPLE_PHY_OPS &phyrtl8211f_ops
#define EXAMPLE_PHY_RESOURCE &g_phy_resource

const phy_operations_t phyrtl8211f_ops = {.phyInit = PHY_RTL8211F_Init,
.phyWrite = PHY_RTL8211F_Write,
.phyRead = PHY_RTL8211F_Read,
.getAutoNegoStatus = PHY_RTL8211F_GetAutoNegotiationStatus,
.getLinkStatus = PHY_RTL8211F_GetLinkStatus,
.getLinkSpeedDuplex = PHY_RTL8211F_GetLinkSpeedDuplex,
.setLinkSpeedDuplex = PHY_RTL8211F_SetLinkSpeedDuplex,
.enableLoopback = PHY_RTL8211F_EnableLoopback,
.enableLinkInterrupt = PHY_RTL8211F_EnableLinkInterrupt,
.clearInterrupt = PHY_RTL8211F_ClearInterrupt};

/* Set SMI to get PHY link status. */
phyConfig.phyAddr = EXAMPLE_PHY_ADDRESS;
phyConfig.ops = EXAMPLE_PHY_OPS;
phyConfig.resource = EXAMPLE_PHY_RESOURCE;
phyConfig.autoNeg = true;

4.3 初始化phy直到link和自适应上或者超时

  • Link(链路):指 PHY 与对端设备通过网线建立的物理连接状态,link只表示物理上连接。

    • 有效(Up):双方信号同步、物理参数兼容,可传输数据;
    • 无效(Down):可能因网线问题、信号衰减或参数不兼容导致。
      可通过 PHY 状态寄存器的 “链路状态位” 查看。
  • 自适应(Auto-negotiation):PHY 与对端自动协商最优通信参数的功能。

    • 协商内容:传输速率(10/100/1000Mbps 等)、双工模式(全双工 / 半双工)等;
    • 作用:自动匹配双方都支持的最高性能模式,无需手动配置;
    • 控制:通过 PHY 控制寄存器的 “自适应使能位” 开启 / 关闭,关闭时需手动配置参数且需与对端一致。
do
{
result = PHY_Init(&phyHandle, &phyConfig);
if (result == kStatus_Success)
{
PRINTF("Wait for PHY link up...\r\n");
/* Wait for auto-negotiation success and link up */
count = PHY_AUTONEGO_TIMEOUT_COUNT;
do
{
PHY_GetAutoNegotiationStatus(&phyHandle, &autonego);
PHY_GetLinkStatus(&phyHandle, &link);
if (autonego && link)
{
break;
}
} while (--count);
if (!autonego)
{
PRINTF("PHY Auto-negotiation failed. Please check the cable connection and link partner setting.\r\n");
}
}
} while (!(link && autonego));

5、通用配置phy的步骤

总结一般配置phy的过程:

1)复位PHY,通过芯片上的RESET管脚拉低拉高给复位信号;

2)MDIO初始化,保证后续通信读与写;

3)PHY初始化,调用PHY_INIT接口,一般在里面配置相应的状态寄存器,并且回读PHY ID确保与PHY之间通信正常;

4)INIT完成后获取PHY的LINK状态、自适应状态以及通信速率和全双工半双工等信息用于后面ENET的配置和初始化;

6、phy配置接口解析(phyrtl8211f)

6.1 PHY_RTL8211F_Init

        INIT中进行了检查PHY ID、重置PHY寄存器、配置RGMII延迟、配置中断引脚、清除中断、设置自动协商模式以及启用链路中断的操作。

status_t PHY_RTL8211F_Init(phy_handle_t *handle, const phy_config_t *config)

6.2 PHY_RTL8211F_Write

        底层是通过MDIO/MDC进行写操作。

status_t PHY_RTL8211F_Write(phy_handle_t *handle, uint8_t phyReg, uint16_t data)

6.3 PHY_RTL8211F_Read

        底层是通过MDIO/MDC进行读操作。

status_t PHY_RTL8211F_Read(phy_handle_t *handle, uint8_t phyReg, uint16_t *pData)

6.4 PHY_RTL8211F_GetAutoNegotiationStatus

        读取相关寄存器配置返回自适应状态。

status_t PHY_RTL8211F_GetAutoNegotiationStatus(phy_handle_t *handle, bool *status)

6.5 PHY_RTL8211F_GetLinkStatus

        读取相关寄存器配置返回link状态。

status_t PHY_RTL8211F_GetLinkStatus(phy_handle_t *handle, bool *status)

6.6 PHY_RTL8211F_GetLinkSpeedDuplex

        读取相关寄存器配置返回通信速率以及全双工/半双工状态。

status_t PHY_RTL8211F_GetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t *speed, phy_duplex_t *duplex)

6.7 PHY_RTL8211F_SetLinkSpeedDuplex

        写入相关寄存器配置通信速率以及全双工/半双工状态。

status_t PHY_RTL8211F_SetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t speed, phy_duplex_t duplex)

6.8 PHY_RTL8211F_EnableLoopback

        启用/禁用回环测试,回环测试用于测试和诊断链路完整性。

status_t PHY_RTL8211F_EnableLoopback(phy_handle_t *handle, phy_loop_t mode, phy_speed_t speed, bool enable)

6.9 PHY_RTL8211F_EnableLinkInterrupt

        启用链路中断变化。

        “链路中断变化” 指的是 PHY 与对端设备之间的物理连接状态(即链路状态)发生的从 “正常连接(Link Up)” 到 “断开(Link Down)” 或从 “断开(Link Down)” 到 “正常连接(Link Up)” 的切换事件。

status_t PHY_RTL8211F_EnableLinkInterrupt(phy_handle_t *handle, phy_interrupt_type_t type)

6.10 PHY_RTL8211F_ClearInterrupt

        清除链路变化中断。

status_t PHY_RTL8211F_ClearInterrupt(phy_handle_t *handle)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值