BSP之以太网接口学习笔记

以太网接口学习笔记


前言:

在嵌入式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)。
    • 时钟源模式
      1. PHY Mode:PHY 接晶振,输出 50MHz 给 SoC。
      2. 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 总线,它也是一种简单的串行总线,只有两根信号线:

  1. MDC (Management Data Clock): 时钟线。
    • 关键点: 这根线永远是由 MAC (SoC) 产生并输出的。MAC 是绝对的 Master,PHY 是 Slave。
  2. 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,还需要掌握更底层的工具。

  1. ethtool 进阶
    • ethtool -S eth0:查看统计计数。重点关注 rx_crc_errors (物理层干扰/时序问题), rx_fifo_overflow (DMA搬运太慢/系统负载高)。
    • ethtool -r eth0:重置自协商。用于测试链路恢复能力。
    • ethtool -d eth0:Dump MAC寄存器。直接查看MAC控制器的原始状态。
  2. 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)。
  3. 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 都不回)。
  • 原因 1RGMII Delay 不匹配。这是最经典的问题。尝试遍历 rgmii, rgmii-id, rgmii-rxid, rgmii-txid。
  • 原因 2Interrupt 极性错误 。如果 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 中有提供。
相关推荐
UTwelve2 小时前
【UE】笔记:用 @param 标记,为蓝图节点的输入输出引脚添加注释
笔记
wadesir2 小时前
Debian dd命令详解(磁盘备份与恢复完整教程)
linux·运维·debian
峰顶听歌的鲸鱼2 小时前
15.docker:容器
运维·笔记·docker·容器·学习方法
风123456789~2 小时前
【健康管理】第14章 健康保险与健康管理
笔记·考证·健康管理
渡我白衣2 小时前
计算机组成原理(4):计算机的层次结构与工作原理
运维·c语言·网络·c++·人工智能·笔记·硬件架构
YJlio2 小时前
Active Directory 工具学习笔记(10.9):AdInsight——命令行选项与自动化采集模板
笔记·学习·自动化
询问QQ:4877392782 小时前
用NSGA - II算法在Matlab中实现微电网多目标优化调度
linux
FakeOccupational3 小时前
电路笔记(信号):Ansys HFSS 求解器激励(Excitation)类型 Driven Modal 和 Driven Terminal & 设置细节
笔记
Tonya433 小时前
测开学习DAY39
学习