ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

深入解析以太网MAC与PHY:从原理到设备树调试的完整指南

深入解析以太网MAC与PHY:从原理到设备树调试的完整指南 做嵌入式网络这行几乎天天跟 MAC、PHY 这两个缩写打交道。前阵子有朋友问我“网口不就是网口吗为什么原理图上总有一个 MAC 加一个 PHY能不能一个芯片搞定”这个问题其实问到了点子上。MAC 和 PHY 是整个以太网链路里最核心的两层也是硬件工程师画原理图、FPGA 工程师配 IP、Linux 驱动工程师调设备树都绕不开的部分。这篇把“知识点滴 - MAC and PHY”这个话题彻底展开从两者分工、接口选型、硬件设计、设备树配置到实际排障一次讲透适合刚接触网络的嵌入式工程师、做 FPGA 网络加速的同学也适合想搞明白网线另一头到底在发生什么的软件工程师。1. 先把概念钉死MAC 和 PHY 分别干了什么1.1 从 OSI 分层看职责以太网协议栈里最容易被混淆的就是 MAC 和 PHY 这两个角色。简单说MACMedia Access Control工作在第 2 层数据链路层负责组帧、解帧、填充、FCS 校验、地址过滤、流控还要参与 CSMA/CD 的访问控制逻辑。对上它拿到的是完整的数据包对下交给 PHY 的是一串比特流。PHYPhysical Layer工作在第 1 层物理层负责把比特流变成线缆上的电信号或光信号。具体包括编码方式的选择10M 用曼彻斯特编码100M 用 4B/5B MLT-31G 用 8B/10B10G 用 64B/66B、时钟恢复、发送均衡、接收均衡、自协商Auto-Negotiation以及最后驱动 MDI 接口上的差分线对。关键区别一句话就能记住MAC 处理的是“帧”PHY 处理的是“比特和符号”。MAC 是纯数字逻辑基本不关心介质是双绞线还是光纤PHY 是典型的数模混合电路一头是数字接口MII/RGMII/SGMII 这类另一头是模拟通道变压器、RJ45、光模块所以设计门槛比 MAC 高不少。用生活化的类比MAC 是快递分拣中心负责贴面单、拆包、验重量PHY 是运输车辆和司机负责把包裹按路线送到目的地。至于车子是油车还是电车、走哪条路、路上怎么变速分拣中心完全不关心。1.2 为什么 MAC 和 PHY 要分开很多人会问干脆把 MAC 和 PHY 做到一个芯片里不就好了答案是好但不全是。分开做有历史和工程上的双重原因。介质标准变化快PHY 必须跟着线缆标准走10M、100M、1G、2.5G、5G、10G 一路演进而 MAC 相对稳定只需要升级接口带宽即可。工艺上模拟 PHY 和数字 MAC 放在一起对工艺要求不同分开可以用不同工艺分别做优化成本和良率都好控制。产业分工SoC 厂商普遍内置 MAC外接的 PHY 由专业 PHY 厂商提供两边通过标准化接口互配这样用户可以根据成本、速率、温度等级自由选 PHY。当然现在很多 MCU / SoC 会把百兆 MAC 和百兆 PHY 也集成在一起一片芯片直接拉变压器接 RJ45BOM 成本最低。但到了千兆及以上或者工业、车载这类对温漂和抗干扰要求高的场景外部 PHY 仍是绝对主流。这也解释了为什么你在绝大多数开发板上都能看到“一个 MAC 一个 PHY”的经典结构。1.3 顺带说清 MAC 地址的小知识题目里出现 MAC很多人第一反应是 MAC 地址这里一并说清楚。MAC 地址全称 Media Access Control Address48 位写作六组十六进制比如 00:0C:29:xx:xx:xx。前 24 位是 OUI组织唯一标识符由 IEEE 统一分配。比如 00:0C:29 这个 OUI 属于 VMware所以看到 000c 29 开头的 MAC 地址大概率就是虚拟机网卡排查内网设备时这个信息非常有用。不过要纠正一个误区MAC 地址只在同一条二层链路内有意义数据包经过路由器时源 MAC 会被改写成路由器出口的 MAC所以别把 MAC 地址当成全球唯一的设备身份证。调试网络时真正要盯的是 IP 和端口MAC 只是用来在同网段内定位设备的。另外抓包时经常看到某些固定 OUI 的设备用 OUI 查询工具能快速判断是什么厂商的设备这也是个实用小技巧。2. MAC 与 PHY 之间的“对话”接口从 MII 到 SGMII2.1 主流接口对照与选型MAC 和 PHY 之间需要一组标准接口来传输数据、时钟和控制信息。这个接口家族很大但实际项目里高频出现的就那几个我对常用的做了个汇总接口数据宽度时钟频率支持速率数据引脚数典型场景MII4 bit25 MHz / 2.5 MHz10/100M16 左右老平台、工业控制器RMII2 bit50 MHz 固定10/100M7 左右低成本 MCU、路由器GMII8 bit125 MHz1000M24 左右老 FPGA、高端 SoCRGMII8 bit DDR 双沿125 MHz1000M12 左右当前最主流的千兆接口SGMII1 路串行差分1.25 Gbps10/100/1000M4 左右交换芯片、FPGA、多口设备几个选型时的关键点RMII 固定 50 MHz 参考时钟MAC 和 PHY 必须共用一个同源时钟通常由外部晶振或者 MAC 侧提供这个时钟的精度和相位一致性很重要否则会偶发丢包。RGMII 是双沿采样125 MHz 下 8 根数据线在时钟上下沿各采 4 bit因此时钟和数据的相对延时skew是设计成败的关键。这也是后面要重点说的 rgmii-id、rgmii-txid、rgmii-rxid 这些模式差异的由来。SGMII 是串行差分接口物理上就 4 根线内部用 8B/10B 编码MAC 和 PHY 之间会跑一段类似自协商的握手逻辑来协商 10/100/1000M 速率。注意别把 SGMII 和 1000BASE-X 混为一谈两者在电平上几乎一样但协议行为不同连错会 link 不起来。原来的 MII 在 10M 下只需 2.5 MHz 时钟到了 100M 就要 25 MHz接口是半字节并行。RMII 是为了省引脚把 4 bit 改成 2 bit代价是参考时钟频率反而提高到 50 MHz而且必须同源。GMII 是全 8 bit 并行引脚多到板子很难走线所以后来 RGMII 用 DDR 技术在 8 根线上同时传收发数据一根线干两倍的活引脚数直接砍一半。SGMII 则是把接口彻底串行化适合背板和交换芯片这类高密度场景。选谁本质上是在引脚数、速率、走线难度、功耗之间找平衡。2.2 SGMII 的 MAC 模式和 PHY 模式到底谁配谁这是 FPGA 开发者问得最多的问题SGMII IP 核和 PHY 芯片一起使用时IP 应该配置成什么模式答案是 MAC 模式不是 PHY 模式。很多人一开始会搞反原因在于不熟悉 SGMII 的角色定义。SGMII 标准里规定得很清楚一端是 MAC另一端是 PHY。MAC 侧的 PCS 和 PHY 侧的 PCS 虽然物理上对称但角色不同自协商时发送的 ordered set、时钟关系、寄存器行为都不一样。PHY 芯片的 SGMII 接口天生就是按“PHY 侧”设计的所以 FPGA 里的 SGMII IP 只有配置成 MAC 侧才能和 PHY 正确对接。那什么时候配 PHY 模式呢典型场景是两个 FPGA 通过 SGMII 背靠背直连一端必须作为 PHY 模式又比如 FPGA 的 SGMII 直接去接 SFP 光模块当 1000BASE-X 用时行为更接近 PHY 侧具体还是要看 IP 支持哪种工作模式再定。记住一句话就行SGMII 是点对点的双角色接口你和谁对接就扮演谁的另一端。配反了的典型症状是MDIO 能正常读到 PHY 的寄存器但 SGMII 的 PCS status 一直不过link 信号起不来抓寄存器发现自协商状态机卡在某一步不动。遇到这种情况先别怀疑硬件先检查 IP 配置里的 mode。2.3 电压型 PHY 和电流型 PHY 的实质选 PHY 时经常能看到“电流型”“电压型”的说法这里也顺便解释清楚。这俩指的是 PHY 发送通道的驱动实现方式。电流型驱动current-mode内部用恒流源加开关结构输出摆幅和共模更可控抗干扰能力好但功耗相对高很多千兆 PHY 采用这类方案。电压型驱动voltage-mode直接用电压开关输出功耗低、外围简单但输出阻抗需要对端接电阻精细匹配对变压器和 Layout 更敏感。落到实际设计上最大的影响是网络变压器中心抽头的接法。电流型 PHY 的抽头往往要接到电源或通过电阻接电源电压型 PHY 的抽头接法又不同。替换 PHY 型号时如果只对着网口原理图改了芯片型号没改变压器和抽头电路很可能出现“百兆能跑、千兆频繁掉 link”的怪毛病。这也是国产 PHY 替换进口 PHY 时翻车率极高的原因驱动寄存器改对了硬件前端没跟着改性能就是上不去。所以别只盯着“能不能到百兆”这个指标要把驱动类型、变压器、端接电阻一起看。3. 让软件找到硬件从原理图到设备树3.1 硬件设计上先确认的 5 件事把 MAC 和 PHY 画到板子上之前或者拿到一块陌生板卡准备移植系统时下面 5 项先确认清楚能省掉一半的调试时间。复位时序PHY 的上电复位必须满足要求一般要求电源稳定后再保持复位至少几毫秒然后释放。很多 PHY 的 strap 引脚会在复位释放瞬间被采样决定默认 MDIO 地址、默认速率、LED 模式所以 strap 电阻不能省也不能在复位还没稳定时就上电配置。时钟来源到底是 MAC 给 PHY 提供参考时钟还是 PHY 自己挂晶振两种都常见。但设备和驱动配置必须跟上搞反了 MDIO 经常读不到数据。MDIO 上下拉MDC 频率一般 2.5 MHz 左右MDIO 数据线需要上拉电阻常见 1.5k 到 2.2k 上拉到 3.3V。新手上板 MDIO 全读到 0xFFFF一半是 PHY 地址对不上另一半就是上拉缺失或者 MDC 频率拉得太高。中断PHY 的 link 状态变化中断接或不接影响的是驱动效率和低功耗表现。接中断要注意 PHY 引脚的开漏特性和上拉电压是否匹配。LED 和 strap有些 PHY 把速率选择、自协商开关放在 strap 脚上接错会强制成固定速率你后面再怎么配置自协商都白搭。这个清单是我每次画图之前必过的少看一项后面多半要返工。特别是 strap 电阻很多人觉得“反正 PHY 有寄存器可以配置”实际上 strap 决定的是上电初始状态寄存器写的配置在复位释放后可能又会被 strap 覆盖非常容易踩坑。3.2 设备树配置示例让 MAC 找到 PHYLinux 下 MAC 和 PHY 的连接关系完全靠设备树描述。最典型的结构是 MAC 节点通过 phy-handle 指向 mdio 总线上的 PHY 节点mac0 { status okay; phy-mode rgmii-id; phy-handle phy0; }; mdio0 { phy0: ethernet-phy0 { reg 0; compatible ethernet-phy-id1234.5678; max-speed 100; reset-gpios gpio1 15 GPIO_ACTIVE_LOW; reset-assert-us 10000; reset-deassert-us 100000; interrupt-parent gpio1; interrupts 16 IRQ_TYPE_LEVEL_LOW; }; };几个字段的实际含义reg 是 PHY 的 MDIO 地址范围 0 到 31具体地址由 PHY 的 strap 引脚决定原理图里能查得到。compatible 可以写具体的 PHY ID比如 ethernet-phy-id1234.5678也可以让驱动自动探测通常写 PHY ID 更保险。reset-gpios 配合 reset-assert-us、reset-deassert-us 是标准的复位控制写法新内核里别再写老的 phy-reset-gpios那是旧接口。max-speed 可以把千兆 PHY 限速到百兆很多只要求百兆的工业设备这么干能省一些自协商的问题。interrupt 用 PHY 中断引脚比轮询状态寄存器高效尤其设备数量多的时候能显著降低 CPU 占用。设备树写完不是重启就完事强烈建议启动后用 ethtool 确认接口起来没有再用 mdio-tools 或者驱动自带的寄存器 dump 功能核对 PHY 是否被正确探测到。3.3 RGMII 延时是个细节活RGMII 最大的坑就是延时。因为是双沿采样数据和时钟之间必须有合适的相对延迟否则接收端采到的数据不稳定。通常有两条路实现PHY 内部加延迟或者 MAC/FPGA 在输出时钟上做延迟。设备树的 phy-mode 取值直接对应这个行为rgmii不加任何内部延迟靠 PCB 绕线和 MAC 侧自己去处理。rgmii-idPHY 内部收发两个方向都加延时这是多数 PHY 的推荐用法。rgmii-txid只加发送方向延时。rgmii-rxid只加接收方向延时。最典型的问题是两边都加了延时变成双份延迟。轻则能 link 但抓包全是坏帧重则直接 link 不起来。调试这种问题示波器看 RX_CLK 和 RXD 的相位关系是最快的如果改 phy-mode 之后症状立刻消失基本锁定就是这个原因。还有一种做法是看 MAC 驱动里有没有 rgmii 内部的 delay 配置寄存器有些 SoC 会把延时放在 MAC 侧而不是 PHY 侧两边要配合好。3.4 国产百兆 PHY 的适配经验这几年国产百兆 PHY 用得越来越多价格便宜、供货稳定替换进口料的需求也大。但项目里用下来我确实踩过几个典型坑值得单独说说。第一寄存器不兼容。很多国产 PHY 标称“兼容某国际大厂驱动”实际上只有基本寄存器0、1、4、5 这些一致厂商私有寄存器定义完全不同。所以不要拿进口 PHY 的初始化代码原样套上电先做一次完整寄存器 dump 对比。第二LED 行为差异。LED 的闪烁模式、link/activity 定义可能不一样硬件上直接替换的话面板灯显示会和设计文档对不上。第三复位时间更长。部分国产 PHY 上电复位需要更长的稳定时间设备树里的 reset-deassert-us 给足一点否则会出现“前几次能起来冷启动起不来”的玄学问题。第四Auto MDI-X 支持。现在多数 PHY 都支持 MDI 极性自动翻转但个别国产料在某些配置下不生效接到直连网线上 ping 不通时先怀疑这个。第五EMI 和电源纹波。国产 PHY 在传导发射测试里对共模电感选型和电源去耦要求往往比进口料更严格Layout 阶段别省磁珠和电容不然过了功能测试认证测试再返工就非常痛苦。第一次点亮国产 PHY建议上电后用 MDIO 工具把寄存器 0x00 到 0x1F 完整 dump 一遍并留存。后面出任何问题拿这份快照对比就能快速判断是 PHY 状态变了还是配置被人改了。很多所谓“坏片”其实只是寄存器状态不对读一下 Basic Mode Status Register0x01就真相大白。4. 联调与排障起不来网口的那些坑4.1 问题速查表联调阶段最崩溃的就是网口起不来。这里整理一张我常用来对着查的速查表现象优先怀疑检查方法MDIO 读全是 0xFFFFPHY 地址、上拉、复位、时钟确认 MDIO 上拉循环扫描地址 0~31link 灯不亮PHY 自协商没完成、变压器/连接器读寄存器 0x01 的 link 位换网线和端口能 link 但 ping 不通RGMII 延时、TX/RX 反接、时钟偏差示波器看数据与时钟相位核对 phy-mode丢包严重/坏帧率高电平、端接、变压器、电源纹波看统计寄存器 rx_errors、FCS errors查电源协商成 10M 而非 100M网线质量、PHY 被 strap 成强制模式看 0x04/0x05 自协商结果换标准网线这张表是“第一板工具”不是最终答案但能帮你把问题范围快速缩小到某一层。实际排查时我还习惯看驱动日志里有没有类似“MAC、IP、PORT”这类关键字的报错这种日志通常指向 MAC 侧的端口配置或者内部表项问题而不是 PHY 本身别在 PHY 上浪费时间。4.2 常见日志与链路状态怎么看系统起来后先看 dmesg 里网卡驱动有没有报 MDIO 错误再用 ethtool 看接口状态。ethtool 是排查神器ethtool eth0 ethtool -s eth0 speed 100 duplex full autoneg off # 强制百兆全双工 ethtool -S eth0 # 查看统计计数器如果自协商开着但 link 不起来强制到百兆全双工再试一下。这个动作能帮你快速分层强制能起说明主要是自协商或网线问题强制也起不来那就是 PHY 硬件通道、变压器、接口或 MAC 配置的问题。对于 SGMII 场景很多 MAC 驱动会打印 PCS link 状态。注意看这个状态很有用PCS 不过说明是 SGMII 层的问题PCS 已经过但网线侧不上 link说明是 PHY 模拟前端和线路的问题。这个分层定位的能力在千兆和万兆系统里特别重要。4.3 分层排查方法论我的排查习惯是从底层往上查每层先问一句“这一层通没通”物理信号层示波器看 MDC/MDIO 波形确认 MDIO 能稳定读写 PHY 寄存器这是基础中的基础。PHY 状态层读 0x01 寄存器的 link 状态、自协商完成位读 0x05 确认协商出来的速率和双工模式。MAC-PHY 接口层检查 RGMII 数据线和时钟的时序SGMII 就查 PCS 状态和错误计数。MAC 驱动层看驱动的缓冲区描述符错误、FCS 错误计数、丢包统计。网络协议栈层ping 网关抓包确认有没有回包判断是本端发出去了没收到回包还是对端压根没收到。这个顺序很朴素但能避免从中间开始瞎猜。我遇到过一次“ping 通了但传大文件就卡死”的案例折腾网络栈半天最后发现是 SGMII 降到 100M 时 MAC 侧的发包节流配置不对属于接口速率切换的配置问题跟协议栈一点关系都没有。4.4 一些独家小经验最后分享几条从项目里攒出来的经验给每一款 PHY 建一个“寄存器快照库”。换新板卡、改配置之前先把默认寄存器完整 dump 下来后续出问题随时对比。这个习惯救过我太多次。拿到新 PHY 板卡先别急着把驱动初始化写得很复杂尽量用 PHY 默认配置先 link 一次确认硬件通路是好的再逐条把配置加回去。很多“连不上”的问题其实是被初始化代码掩盖的默认配置能通但加了配置就挂问题多半在配置本身而不是硬件。设备树 reset-deassert-us 宁可给大不要给小。几次冷启动失败往往就是复位时间不够、MDIO 探测太快导致的。千兆 PHY 对电源纹波非常敏感Layout 阶段一定要给 PHY 电源加磁珠和足够的去耦电容。前期省下的成本后期都会变成“偶发掉 link”的排查时间还回去。我个人做网络硬件这么久最大的感受是MAC 和 PHY 的知识点其实不算难难的是那些藏在数据手册角落里的时序参数、寄存器位定义和 strap 配置。每次遇到起不来的网口别急着怀疑硬件坏了先老老实实读寄存器、看时序、分层次排查大多数问题都能定位出来。最后再分享一个小技巧把常用的 PHY 寄存器地址和关键位定义做成一页速查卡放桌面联调的时候真的能救命。
返回列表