以太网接口学习笔记
前言:
在嵌入式Linux BSP开发中,网络子系统(Network Subsystem)是复杂度仅次于存储和图形显示的模块。网络不通通常是软硬件协同问题的高发区。
作为BSP工程师,我们需要建立基于 OSI七层模型 的底层视角:
- Layer 1 (物理层) :这是 PHY (Physical Layer) 芯片的地盘。它负责模拟信号(电压、光脉冲)与数字信号之间的转换,处理编码(如Manchester, 4B/5B, 8b/10b)、链路状态检测等。
- Layer 2 (数据链路层) :这是 MAC (Media Access Controller) 的地盘,通常集成在SoC内部。它负责以太网帧的封装/解封、CRC校验、MAC地址过滤、流量控制(Flow Control)等。
核心公式:
Network Function = SoC MAC (Brain) + Interface (Nerves) + External PHY (Sensors)
这份笔记将深入剖析这三者的交互,特别是"神经系统"------数据接口与管理接口。
第一部分:以太网硬件架构深度解析
在嵌入式 Linux 系统中,网络通路的硬件链条通常如下:
SoC (CPU) <--> MAC (Media Access Control) <-->xMII接口 <--> PHY (Physical Layer) <--> Magnetics (网络变压器) <--> RJ45 接口
我们需要深入理解每个环节存在的意义:
- MAC (媒体访问控制层) :通常集成在 SoC 内部。它是数字逻辑电路,负责逻辑链路层功能,如以太网帧的封装/解封、CRC 校验生成/检查、以及 MAC 地址过滤。它只懂"0"和"1"的数字逻辑。
- PHY (物理层) :通常是板载的一颗独立芯片(如 Realtek RTL8211, Broadcom BCM54xx, TI DP83867)。
- 为什么要独立? 因为 PHY 涉及模拟信号处理(ADC/DAC、信号整形、滤波),需要特殊的半导体工艺,难以直接高性价比地集成到标准数字逻辑工艺的 SoC 中。
- 核心功能:负责将 MAC 传来的并行数字信号(xMII),转换为能在双绞线上长距离传输的模拟差分信号(MDI)。
- Magnetics (网络变压器) :
- 核心作用 :电气隔离 (防止网线引入的高压烧毁芯片)、共模抑制(减少 EMI 干扰)。BSP 开发虽然不直接控制它,但硬件设计如果选型错误(如中心抽头电压不对),会导致 Link 不稳定。
- xMII (Media Independent Interface) :MAC 和 PHY 之间的"普通话"。无论物理层是双绞线还是光纤,MAC 这一侧看到的接口都是标准的 xMII。BSP 工程师的主要工作就是通过软件配置,让 MAC 和 PHY 在这个接口上"握手"成功。
第二部分:数据接口详解 ------ 从并行到串行
数据接口决定了以太网帧(Frame)如何在MAC和PHY之间传输。
1. MII (Media Independent Interface)
- 定位:百兆时代的标准接口。
- 数据线:TXD[3:0], RXD[3:0] (4-bit 并行)。
- 时钟机制 :
- TX_CLK :由 PHY 提供 (2.5MHz @ 10Mbps, 25MHz @ 100Mbps)。
- RX_CLK :由 PHY 提供。
- 深度解析:由于TX_CLK是PHY发给MAC,MAC再根据这个时钟送出数据,这导致了往返延时问题,限制了速率无法做高。
- 控制信号:TX_EN, TX_ER, RX_DV, RX_ER, CRS, COL。
- BSP场景:老旧工控板、低成本MCU。调试时注意 TX_ER 信号如果被错误拉起,会导致发出的包被标记为错误包。
2. RMII (Reduced MII)
- 定位:为了减少引脚数(Reduced),常用于引脚紧张的SoC。
- 数据线:TXD[1:0], RXD[1:0] (2-bit 并行)。
- 时钟机制 (Critical) :
- 统一使用 50MHz 参考时钟 (REF_CLK)。
- 时钟源模式 :
- PHY Mode:PHY 接晶振,输出 50MHz 给 SoC。
- MAC Mode:SoC 内部 PLL 产生 50MHz 输出给 PHY。
- BSP坑点:硬件设计选择了哪种时钟方向,软件Device Tree必须对应配置时钟树,否则MAC逻辑不工作。
- 数据采样:每个时钟周期传2-bit,50MHz * 2bit = 100Mbps。
3. GMII (Gigabit MII)
- 定位:RGMII的前身,千兆标准。
- 数据线:8-bit 并行 (TXD[7:0], RXD[7:0])。
- 时钟:125MHz。
- 缺点:125MHz下做8位并行同步,对PCB走线要求高,且占用引脚太多,现已基本淘汰。
4. RGMII (Reduced Gigabit MII)
这是嵌入式Linux中最主流的接口,也是调试难度最高的接口之一。
- 原理 :使用 DDR (Double Data Rate) 技术,在时钟的上升沿 和下降沿 都采样数据。
- 4-bit 位宽 * 125MHz 时钟 * 2 (DDR) = 1000 Mbps。
- 信号线 :
- TXD[3:0], TX_CTL, TX_CLK (MAC提供)。
- RXD[3:0], RX_CTL, RX_CLK (PHY提供)。
- 注意:TX_EN 和 TX_ER 合并为 TX_CTL,通过时钟沿编码区分。
核心点:Skew (时钟偏斜)与 Timing Budget
在125MHz DDR模式下,数据有效的窗口期(Data Valid Window)非常短。
- 如果 PCB 走线完全等长,数据和时钟同时到达接收端。
- 由于接收端的建立时间(Setup Time)和保持时间(Hold Time)需求,时钟信号的跳变沿必须位于数据信号的中心(即延时90度,约2ns)。
phy-mode 四种模式的物理含义:
| 模式名称 (DTS) | 英文全称 | 物理含义 | 适用场景 |
|---|---|---|---|
| "rgmii" | No Internal Delay | PHY 不开启 内部延迟。认为 PCB 做了等长或 MAC 会负责。 | 历史遗留硬件,或老式PHY芯片。 |
| "rgmii-id" | Internal Delay | PHY芯片内部在TX和RX路径上开启2ns的数字延时器。PCB可以直连,无需蛇形走线。 | 现代设计首选。 |
| "rgmii-rxid" | RX Internal Delay | PHY只负责接收方向(RXD/RX_CLK)的延时。发送方向(TXD/TX_CLK)需要MAC端配置或PCB处理。 | 某些特殊MAC或PHY组合。 |
| "rgmii-txid" | TX Internal Delay | PHY只负责发送方向的延时。 | 较少见。 |
经验:
- 现象:Ping大包丢包,或者只有几Kbps速度,或者大量CRC Error。
- 对策:通常是延时配置不对。尝试在 rgmii 和 rgmii-id 之间切换。有些PHY(如RTL8211F)对TX-delay和RX-delay有单独的寄存器微调,不仅仅是开/关,还能调具体ns数(需查阅Datasheet扩展寄存器)。
5. SGMII (Serial Gigabit MII) ------ 高速串行趋势
- 原理 :基于 SerDes (Serializer/Deserializer)。将并行数据转为串行差分信号。
- 物理层:LVDS (Low Voltage Differential Signaling) 逻辑电平。
- 时钟:通常需要一对差分参考时钟(100MHz 或 125MHz),或者从数据中恢复时钟(CDR)。
- 速率:1.25 Gbaud (8b/10b编码后,有效带宽1Gbps)。
- In-band Status (带内状态) :SGMII不像RGMII那样有专门的引脚传Link状态。它可以将Link up/down、Duplex信息编码在数据流中发给MAC。
- BSP坑点:DTS中属性 managed = "in-band-status" 就是开启这个功能。如果PHY不支持或配置没对,MAC可能认为链路一直是Down的。
- AC耦合 :TX和RX线上通常串联 0.1uF 电容。如果板子上没贴这电容,SGMII大概率不通。
第三部分:管理接口- MDIO/SMI
1.MDIO 硬件连接:一主多从
MDIO 接口的设计非常像 I2C 总线,它也是一种简单的串行总线,只有两根信号线:
- MDC (Management Data Clock): 时钟线。
- 关键点: 这根线永远是由 MAC (SoC) 产生并输出的。MAC 是绝对的 Master,PHY 是 Slave。
- MDIO (Management Data Input/Output): 数据线。
- 关键点: 它是双向 的。MAC 用它发命令,PHY 用它回传数据(比如寄存器值)。而且它通常需要一个上拉电阻(Pull-up),因为在空闲状态下它需要保持高电平。
这种架构允许一个 MAC 控制器通过同一组 MDC/MDIO 线挂载多个 PHY 芯片(比如一个交换机芯片内部可能有 5 个 PHY)。在 MDIO 协议的标准帧格式中,专门预留了 5个 bit 用来存放 PHY 的地址。
MDIO 是配置PHY的唯一通道。如果不通,Kernel连PHY ID都读不到,网卡驱动直接报错退出。
2. 基础协议 (Clause 22)
- 帧结构:
PRE(32bit 1s) | ST(01) | OP(RW) | PHYAD(5bit) | REGAD(5bit) | TA(2bit) | DATA(16bit) - 限制 :
- PHY Address 只有5位 -> 最多32个PHY。
- Register Address 只有5位 -> 只能访问前32个寄存器 (Page 0)。
- 扩展寄存器访问 (Page Select):
由于现代PHY寄存器远超32个,厂商通常定义 Reg 31 为 Page Select Register。- 写:向Reg 31写入 0xXYZ (页码)。
- 读/写:操作 Reg 16-30 (该页下的数据)。
- 恢复:向Reg 31写入 0 (切回默认页)。
- BSP技巧:mdio-tool 工具通常支持这种分页读写。
3. 高级协议 (Clause 45)
- 专为万兆(10G)及以上设计,但也用于复杂的千兆PHY。
- 特点 :
- 支持 MMD (MDIO Manageable Device) 分层概念(如PMA/PMD, PCS, PHY XS等)。
- 地址空间扩大:Device Address (5bit) + Register Address (16bit)。
- 访问方式改为:Address Frame (发地址) + Data Frame (发数据),两步走。
- 兼容性:很多PHY支持 Clause 45 over Clause 22 (通过C22的Reg 13/14 间接访问C45寄存器)。
第四部分:Device Tree 与 Driver 配置
在 arch/arm64/boot/dts/... 中,网络节点的配置直接决定了驱动的行为。
1. RGMII 完整配置示例
c
&gmac0 {
status = "okay";
phy-mode = "rgmii-id"; /* 核心配置 */
phy-handle = <&rgmii_phy>;
/* MAC层级的高级配置 */
tx_delay = <0x3>; /* 某些SoC MAC支持微调内部延时 */
rx_delay = <0x3>;
/* 1. 固定链路 (无PHY场景, 如直连Switch) */
fixed-link {
speed = <1000>;
full-duplex;
};
mdio {
compatible = "snps,dwmac-mdio";
#address-cells = <1>;
#size-cells = <0>;
rgmii_phy: ethernet-phy@1 {
reg = <1>; /* 对应硬件 Strap Pin 设置的地址 */
/* 2. 厂商特定驱动 vs 通用驱动 */
/* 写具体的ID可以强制加载特定驱动,否则内核会通过读ID自动匹配 */
compatible = "ethernet-phy-id001c.c916";
/* 3. 复位时序精细控制 */
reset-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>;
reset-assert-us = <10000>; /* 保持复位电平 10ms */
reset-deassert-us = <30000>; /* 复位释放后等待 30ms 让时钟稳定 */
/* 4. 中断模式 (推荐) vs 轮询模式 */
/* 如果配置了中断,PHY状态变化时会触发中断,不用CPU一直轮询MDIO */
interrupt-parent = <&gpio1>;
interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
};
};
};
2. 时钟树 (Clock Tree) 检查
在 /sys/kernel/debug/clk/clk_summary 中,务必确认以太网相关的时钟频率正确。
- 如果是 RGMII,gmac_tx_clk 或类似时钟必须是 125MHz。
- 如果是 RMII,必须确认 50MHz 来源正确。
第五部分:调试命令与诊断
除了基础的 ifconfig,还需要掌握更底层的工具。
- ethtool 进阶
- ethtool -S eth0:查看统计计数。重点关注 rx_crc_errors (物理层干扰/时序问题), rx_fifo_overflow (DMA搬运太慢/系统负载高)。
- ethtool -r eth0:重置自协商。用于测试链路恢复能力。
- ethtool -d eth0:Dump MAC寄存器。直接查看MAC控制器的原始状态。
- mii-tool vs phytool
- mii-tool 已过时,只支持 Clause 22 的基本寄存器。
- 推荐使用 phytool (Linux MDIO tool) 或 mdio-tool。
- 读寄存器:phytool read eth0/1/0 (读 PHY地址1,寄存器0)。
- 写寄存器:phytool write eth0/1/0 0x1140 (配置Control Register)。
- Loopback 测试 (环回测试)
当网络不通时,如何区分是 MAC问题、PHY问题 还是 外部网线/交换机问题?- MAC Loopback:数据出MAC内部FIFO直接回转。如果通,说明驱动和DMA正常。
- PHY Digital Loopback:数据到了PHY内部PCS层回转。如果通,说明 RGMII/MII 接口通讯正常。
- PHY Analog Loopback:数据到了PHY模拟前端回转。
- 设置方法:通常通过写 PHY 的 Register 0 (Basic Control) 的 Bit 14 来开启 Loopback。
第六部分:常见问题排查
场景一:PHY ID 读取全为 0x0000 或 0xFFFF
- 原因 1:MDIO/MDC 引脚复用没配好(检查 pinctrl)。
- 原因 2:PHY 没上电或处于 Reset 状态(检查 GPIO 电平)。
- 原因 3:PHY 缺少参考时钟(对于某些PHY,没有 REF_CLK 甚至连 MDIO 都不回)。
场景二:Link 灯亮,但 ping 不通
- 原因 1 :RGMII Delay 不匹配。这是最经典的问题。尝试遍历 rgmii, rgmii-id, rgmii-rxid, rgmii-txid。
- 原因 2 :Interrupt 极性错误 。如果 DTS 配置了中断但极性配反,中断可能一直触发导致死锁,或者永远不触发导致 Link 状态无法更新。尝试在 DTS 中去掉中断相关行,强制回退到 Polling (轮询) 模式测试。
场景三:Ping 小包通,大包不通 (MTU问题)
- 现象:ping -s 10 ip 能通,ping -s 2000 ip 不通。
- 原因:通常也是时序(Skew)处于"临界状态"。小数据包由于长度短,可能正好避开了采样错误;大数据包连续传输,时钟漂移或抖动导致中间某一位采样错,CRC校验失败,包被丢弃。
- 解决:调整 Delay,或检查电源纹波干扰。
场景四:MAC 地址全是 00
- 原因:SoC 内部 OTP 区域未烧录 MAC 地址,且 U-Boot 环境变量也没设。
- 解决:在 U-Boot 中 setenv ethaddr xx:xx:xx:xx:xx:xx,或在 DTS 中添加 local-mac-address = [...]。
- 补充说明--RK系列芯片MAC读取策略(官方文档):
- 目前对 MAC 地址的读取策略是,优先使用 DTB 里面的 MAC 地址(uboot 也会写入),之后是烧写在IDB 中的 MAC 地址,若该地址符合规范,则使用,若不符合或没有烧写,则使用随机生成的地址(重启开机 MAC 地址会变化)。
- 在 RK3399、RK3328/RK3228H 及以后的版本中,对策略进行了完善:优先使用烧写在 IDB 或 vendor Storage 中的 MAC 地址,若该地址符合规范,则使用,若不符合或没有烧写,则随机生成 MAC 地址保存到 Vendor 分区中并使用,重启或恢复出厂设置不会丢失。烧写工具在 SDK 中有提供。