做嵌入式这几年,几乎绕不开以太网。不管是STM32+PHY做工业网关,还是FPGA接RGMII做高速数据采集,甚至是车载以太网里的SGMII,你总会遇到MAC、PHY、MII、RMII、GMII、RGMII这一堆缩写。第一次接触的人十有八九被绕晕:MAC和PHY到底谁干谁的活?MII、RMII、GMII、RGMII之间是什么关系?为什么有人用RMII、有人用RGMII,还有人直接上SGMII?这篇就从基本概念和接口演进的角度,把这一坨讲清楚。这是我的系列第一篇,先把地基打好,后续再深入讲协议栈、调试和实战排错,思路会更顺。
这篇内容适合刚接触以太网的嵌入式工程师、FPGA开发者,也适合想搞懂车载以太网和工业以太网底层原理的硬件/软件工程师。相信我,搞懂这几个接口的区别和背后的取舍,你做方案选型、查bug、看原理图的时候会舒服很多。
1. 整体认知:以太网的分层和“分家”逻辑
1.1 从一次网络通信说起:谁在干活
我们先从一次最简单的网络通信说起。你的板子要发一个UDP包给电脑,数据从应用程序出发,经过TCP/IP协议栈打包,到最后变成网线上的差分信号,这个过程里芯片到底做了什么?
很多人以为网卡一颗芯片就把事全干了,实际上在绝大多数嵌入式方案里,这是两颗芯片(或者一颗SoC内部的两个模块)配合完成的:一颗叫MAC,一颗叫PHY。MAC全称Media Access Control,媒体访问控制;PHY全称Physical Layer,物理层收发器。名字已经把分工写清楚了:MAC负责“控制”,PHY负责“物理”。
MAC这边管的是逻辑层面的活:把IP包封装成以太网帧,加上目的MAC、源MAC、类型/长度字段,算CRC校验;接收的时候反过来,解析帧、验证CRC、把数据交给上层。同时MAC还要管CSMA/CD(载波监听多路访问/冲突检测)这种信道访问机制——当然现在全双工链路下基本用不到了,但半双工时代这可是看家本领。
PHY这边管的是真正上线的活:把MAC送过来的并行数据变成串行比特流,再编码成适合在铜缆上传输的电平信号。比如100M用的MLT-3编码,1000M用的PAM-5编码,还包括时钟恢复、自动协商(Auto-Negotiation)、链路状态检测,以及和网口变压器、RJ45插座之间的模拟前端电路。换句话说,MAC是“文书官”,PHY是“装卸工+司机”,一个做协议处理,一个做信号传输。
1.2 为什么非要“分家”,不能合成一颗
既然分两颗芯片会让布线、成本、调试都变麻烦,为什么不直接做一颗MAC+PHY集成的芯片?实际上确实有这样的集成方案,很多MCU内部直接带MAC和PHY,比如STM32某些型号、部分工业SoC。但更常见的场景是MAC在MCU/FPGA/处理器内部,PHY在外部单独一颗,这背后有几个现实原因。
一是物理介质和工艺的差异。PHY要处理模拟信号,对抗ESD、浪涌、线缆退化,通常需要更成熟的模拟工艺和专门的模拟前端设计;MAC是纯数字逻辑,跟着SoC的制程走就好。把两者硬捏在一起,SoC的工艺选择会非常受限,成本也压不下来。
二是灵活性和可替换性。不同应用场景对PHY的要求不一样:工业现场可能要用支持宽温、长距离的PHY,消费电子更看重功耗和成本,车载则要过AEC-Q100认证和功能安全。如果把PHY固定在SoC里,你换一种应用场景就得换整个SoC。分开之后,MCU/FPGA随便选,PHY按项目需求挑,国产的、进口的、百兆的、千兆的,各自独立升级,这是硬件工程师最喜欢的解耦方式。
三是PCB布局和信号完整性的现实。PHY离网口变压器和RJ45越近越好,而MAC通常和主控逻辑在一起,两者物理位置天然有分离需求。分开布局可以各自优化,把高速数字信号和模拟信号隔离开,EMI也好控制。
明白了这个“分家”逻辑,后面所有接口问题都好解释了:MAC和PHY之间需要一套标准的数字接口,让两颗芯片能对话,这就是MII家族存在的意义。
2. MII系列接口逐个拆解:从MII到RGMII的演进逻辑
2.1 为什么需要这么多“MII”
MII全称Media Independent Interface,媒体独立接口。注意这个“Media Independent”,翻译过来就是“和具体传输介质无关”。这套接口的设计初衷就是让MAC不需要关心底层是双绞线、光纤还是别的什么介质,只要通过MII接口和PHY对接就行,介质相关的活儿全由PHY处理。
既然有了MII,为什么后面又冒出RMII、GMII、RGMII、SGMII?核心驱动力只有一个:带宽不够用了,得加宽或者提速。这跟道路拥堵了就修路、修完路还是堵就修高架,是一个道理。我们从最早的MII开始,看看每一代接口到底解决了什么痛点,出现了什么新问题。
这个过程理解透了,你看到任何一款芯片的接口列表,基本都能立刻判断出它大概是什么定位、内部架构大概什么样,甚至能推测出它的功耗和Pin脚规模。这是硬件工程师的“读图能力”里很重要的一块。
2.2 MII:100M时代的基准接口
MII出现在10/100M以太网时代,数据位宽4bit,时钟频率25MHz(100M模式)或2.5MHz(10M模式)。发送方向,MAC在TX_CLK的上升沿把4位数据打给PHY;接收方向,PHY在RX_CLK的上升沿把4位数据打给MAC。
MII总共需要几根关键信号线:
- TX_CLK:发送时钟,由PHY提供
- RX_CLK:接收时钟,由PHY提供
- TXD[3:0]:发送数据
- RXD[3:0]:接收数据
- TX_EN:发送使能
- RX_DV:接收数据有效
- CRS:载波侦听
- COL:冲突检测
- MDC/MDIO:管理接口,用来读写PHY寄存器
注意一个反直觉的点:TX_CLK和RX_CLK都是PHY提供的,因为PHY侧有本地晶振或从接收信号里恢复时钟,MAC只是被动适配PHY给出的时钟。这个细节在调试时很重要,排查时钟问题时别找错源头。
MII是10/100M时代的经典接口,但它的缺点也很明显:信号线多,一共十几根,而且时钟在25MHz时沿速率要求高,PCB布线上要考虑等长匹配。在MCU管脚紧张、PCB面积受限的场景下,MII并不友好。于是在MII基础上出现了精简版RMII。
2.3 RMII:为省管脚而生的简配方案
RMII全称Reduced Media Independent Interface,精简媒体独立接口。它最大的特点是把数据位宽从4bit砍到2bit,时钟频率从25MHz提到50MHz。位宽减半、频率翻倍,总带宽不变,但信号线数量大幅减少。
RMII只需要:
- REF_CLK:50MHz参考时钟
- TXD[1:0]:发送数据
- RXD[1:0]:接收数据
- TX_EN:发送使能
- RX_DV/CRS_DV:接收数据有效
- MDC/MDIO:管理接口
从十几根线减到7根左右,对于MCU这种管脚金贵的芯片来说,优势非常明显。而且RMII把收发时钟统一成一个REF_CLK,不再区分TX_CLK和RX_CLK,时钟域管理也更简单。很多STM32系列、低成本的交换芯片、LAN8720这类百兆PHY都支持RMII接口。
RMII的使用上有一个经典大坑:REF_CLK的来源。标准做法有两种,一种是外部晶振直接给PHY提供50MHz,PHY再把REF_CLK给MAC;另一种是MAC侧出50MHz给PHY。这两种时钟拓扑在初始化配置时完全不同,很多人在STM32+LAN8720的例程里看到“RMII时钟选择外部晶振”或者“MCO输出50MHz”的配置,其实根源就在这里。如果你的板子时钟拓扑和代码假设不一致,Link永远起不来,而且不容易排查。后面第4节我会展开讲具体怎么判断。
RMII是为100M设计的,它只支持10/100M速率,做不到千兆。千兆时代带宽需要25M*8bit = 200Mbps总吞吐,宽度不变的情况下时钟需要提到125MHz,于是有了GMII。
2.4 GMII:千兆时代的“宽马路”
GMII全称Gigabit Media Independent Interface,千兆媒体独立接口。它的设计思路很简单:数据位宽扩大到8bit,时钟频率125MHz,刚好满足1000Mbps的线速要求。向后兼容10/100M时,可以降到2.5MHz/25MHz工作。
GMII的信号线数量比MII还多:
- GTX_CLK:发送时钟,由MAC提供,125MHz/25MHz/2.5MHz
- RX_CLK:接收时钟,由PHY提供
- TXD[7:0]:发送数据
- RXD[7:0]:接收数据
- TX_EN:发送使能
- TX_ER:发送错误指示
- RX_DV:接收数据有效
- RX_ER:接收错误指示
- MDC/MDIO:管理接口
注意GTX_CLK的归属又变了:在GMII里,发送时钟由MAC提供,和MII正好相反。这是因为千兆的8bit接口对时钟同步要求极高,MAC作为数据源,自己提供时钟更合理。MII的发送时钟由PHY提供,是因为百兆时代MCU频率低,PHY的本地时钟更稳定。
GMII功能上很完美,但24根线的接口在PCB上就是一场灾难。尤其是125MHz的8bit并行数据线,等长、时序、串扰都要严格控制,小尺寸板子基本放不下。于是RGMII登场了。
2.5 RGMII:DDR技巧让线数减半
RGMII全称Reduced Gigabit Media Independent Interface,精简千兆媒体独立接口。它的思路非常巧妙:在时钟的上升沿和下降沿各采一次数据,也就是DDR(Double Data Rate,双倍数据率)方式。这样8bit数据被压缩到4bit,125MHz时钟不变,但实际数据吞吐翻倍,仍能满足千兆。
RGMII的信号线数量:
- TX_CLK:发送时钟,由MAC提供,125MHz/25MHz/2.5MHz
- RX_CLK:接收时钟,由PHY提供
- TXD[3:0]:发送数据,上升沿发低4位,下降沿发高4位
- RXD[3:0]:接收数据,同样DDR采样
- TX_CTL:发送控制信号,类似TX_EN和TX_ER的合并
- RX_CTL:接收控制信号
- MDC/MDIO:管理接口
这个设计把千兆MAC和PHY之间的连线从24根砍到12根以内,PCB面积压力剧减,所以RGMII成了当前FPGA、主流SoC、交换芯片、千兆PHY之间应用最广的接口。无论是Intel的MAC、Xilinx的三速以太网IP、还是市面上几乎所有千兆PHY(RTL8211系列、YT8531等),都支持RGMII。
但DDR方案带来的问题也很典型:数据在时钟的上下沿都要采样,对时钟和数据之间的相对延迟要求非常严格。RGMII规范里有个著名的2ns延迟要求——PHY输出的RX_CLK相对于RXD需要有一个约2ns的相移,来保证MAC在时钟沿采样时数据已经稳定。有的PHY内部已经做了这个延迟,有的需要你在PCB上走蛇形线,有的需要配置寄存器调整IO delay。这一块是RGMII调试里最磨人的部分,几乎每一个RGMII应用都会踩到这里,后面第5节专门讲。
2.6 SGMII及更高速接口的方向
SGMII是Serial Gigabit Media Independent Interface,串行千兆媒体独立接口。名字里的Serial已经说明问题了:它把数据从并行变成串行,一对差分线发送、一对差分线接收,速率1.25Gbps,通过8B/10B编码传输数据和控制信息。
SGMII的好处极其明显:引脚少到极致(一对差分TX、一对差分RX、一对管理接口),高速串行的信号完整性处理比宽并行总线简单得多,而且在FPGA里直接走GTP/GTX高速收发器,非常方便。SGMII常见于五口/八口交换芯片与上层SoC之间、车载以太网的一些方案里,以及FPGA三速以太网和PHY配合的场景。
很多人对SGMII有个疑问:明明前面讲了“配置成MAC模式还是PHY模式”,这是什么意思?SGMII是一种背靠背接口,它既可以工作在MAC侧,也可以工作在PHY侧。当FPGA里的IP核要和外部PHY芯片直连时,IP核里已经内置了SGMII的MAC侧逻辑,这时PHY自然工作在PHY模式;但当你要让FPGA直接对接另一个MAC(比如交换芯片的MAC口),就需要把其中一个配置成PHY模式来模拟PHY的行为。这就是“SGMII IP核与PHY芯片一起使用时,应配置成MAC模式”这句常见说明的来历。如果两边都配成MAC模式,电气上没法协商,链路直接起不来。
再往上,10G以太网有XGMII、XFI,更高速的直接走SerDes光接口。但那是另一个世界的故事了,先把千兆及以下的接口吃透,足以应对绝大多数嵌入式项目。
3. MAC和PHY内部的那些门道
3.1 MAC核心里有什么
如果把MAC比作一个快递分拣中心,它干的事就是把进来的包裹(IP数据包)拆包、重新打包、贴标签、算校验,然后交给运输队(PHY)送出去;收件的时候反过来检查运输队送来的包裹有没有破损。
一个完整的MAC核心通常包含:
- 发送通路(TX datapath):从FIFO取数据,加前导码(Preamble)、帧起始定界符(SFD)、目的MAC、源MAC、类型/长度字段,计算并附加FCS(帧校验序列,就是CRC32),按接口时序逐比特或逐字节发送
- 接收通路(RX datapath):检测前导码和SFD,解析MAC地址,验证FCS,把有效载荷写入FIFO,并向CPU/DMA发出中断或描述符通知
- 流量控制(Flow Control):全双工模式下通过Pause帧实现反压控制
- 统计寄存器:收帧计数、错帧计数、丢弃计数、CRC错误计数等,这些都是排查网络问题的重要线索
- DMA/缓冲管理:连接系统内存和MAC,把接收到的帧搬运到内存,把要发送的帧从内存读出来
不同厂家的MAC实现有差异,但基本骨架都差不多。FPGA里如果你用的是Xilinx的Tri-Mode Ethernet MAC IP或者Altera的TSE IP,配置界面里能看到这些通路的开关选项;MCU里STM32的Ethernet MAC也是一个独立的外设模块。
3.2 PHY芯片的“黑话”解读
PHY芯片看着不起眼,QFN封裝、几十个引脚,但内部结构相当讲究。以一颗典型的千兆PHY为例,内部的几个核心模块:
- PCS(Physical Coding Sublayer,物理编码子层):负责编码,千兆用8B/10B、百兆用4B/5B加MLT-3、十兆用Manchester编码。PCS还负责自动协商、Link状态管理
- PMA(Physical Medium Attachment,物理介质连接子层):负责并串转换、时钟恢复、线路驱动
- PMD(Physical Medium Dependent,物理介质相关子层):负责真正的电平收发,比如千兆的PAM-5电平,直接对应到变压器和网线
PHY对外除了MII系列数据接口,还有MDC/MDIO管理接口。MDIO是一个两根线的慢速串行接口,用来读写PHY的寄存器。通过MDIO可以做很多事情:
- 读Link状态(比如寄存器1的bit2)
- 配置速度和双工模式(比如寄存器0的bit13/bit8/bit6)
- 开启/关闭自协商
- 读取PHY的芯片ID(寄存器2和寄存器3)
- 做回环(Loopback)测试
- 调整RGMII的时钟延迟(千兆PHY常用,寄存器可能在不同页里)
很多人在调试PHY时只关注Link灯亮不亮,实际上通过MDIO去读寄存器能得到比LED多得多的信息。比如Link起来了但Ping不通,大概率是接口模式不匹配或者RGMII延迟不对,这种问题靠看灯是看不出来的。
3.3 网口变压器到底是不是“多余”的
硬件工程师画原理图时,RJ45到PHY之间一般会放一个网络变压器,常见的是带变压器的RJ45座,或者独立变压器加普通RJ45。新手常常疑惑:为什么别的通信接口(UART、SPI)都不需要变压器,以太网就非得要?
变压器的作用主要有三个:一是电气隔离,网线可能被雷击、静电放电、或者和设备地之间产生电位差,变压器能把这些危险能量挡在PHY外面,保护芯片和人身安全;二是共模抑制,双绞线上的共模干扰通过变压器的中心抽头和终端电阻处理掉,保证差分信号质量;三是信号整形,变压器可以看作一个带通滤波器,能改善信号的上升沿和摆幅。
所以变压器不是“多余的”,而是以太网物理层设计里必不可少的一环。在EMC测试、静电测试里,变压器的选型和布线质量直接影响过不过得了。选型上没有太多花活,跟着PHY的参考设计走就行,关键是注意:变压器的中心抽头怎么接、Bob Smith端接电阻和电容的取值、PHY芯片差分引脚到变压器的走线阻抗(通常100欧姆差分)。这些细节在PHY手册里的参考电路都画得清清楚楚,别自己发挥。
4. 接口选型和典型硬件设计要点
4.1 MCU百兆方案:STM32+RMII/MII怎么选
STM32的以太网控制器在F4、F7、H7系列上都有,支持MII和RMII两种接口模式。很多人在选型时纠结用MII还是RMII,这里直接给结论:
- 管脚充足、追求信号余量:选MII。MII数据位宽4bit,时钟25MHz,时序余量比RMII宽裕,PCB约束更宽松,调试难度低
- 管脚紧张、希望省IO:选RMII。RMII只需要约7根线,能省出一组GPIO,但50MHz的参考时钟必须处理好
- 注意:RMII模式下,STM32的ETH_ref_clk(PA1或PC1)必须输入50MHz,这个时钟从哪里来一定要和PHY芯片的时钟拓扑匹配起来
STM32的CubeMX配置里会让你选Media Interface:MII还是RMII,同时还要配置PHY地址(常见0或者1),这两个配置错了直接导致底层寄存器读写失败。PHY地址由芯片的PHYAD引脚电平决定,画板子时留上拉/下拉,出厂默认就能确定。还有一个小细节:STM32的MAC地址不是出厂烧好的,必须由软件设置,很多人第一次跑通例程前忘了写MAC地址,通信就起不来。
4.2 FPGA千兆方案:RGMII布线和时序约束
FPGA做千兆以太网,最常见的是接一颗RGMII千兆PHY。Xilinx的三速以太网IP核支持RGMII、GMII、MII,但实际项目中大家基本都选RGMII,因为引脚少、时序可控。
FPGA侧RGMII的实现有几个关键点:
第一,PHY芯片的RX_CLK(对FPGA来说是接收时钟)与RXD/ RX_CTL的关系。RGMII规范要求PHY的RX_CLK要相对数据延迟约2ns输出,这样FPGA时钟引脚采数据时落在数据稳定窗口内。如果PHY内部没做这个延迟,你需要在PCB上给RX_CLK走线加长,或者在FPGA的IO约束里做输入延迟约束。
第二,FPGA侧发送方向也要考虑时钟输出和数据输出的关系。MAC给PHY的TX_CLK是随路时钟,数据在TX_CLK上下沿都有效。FPGA中可以用ODDR原语把两个4bit半字节合并在一个时钟沿输出,也可以用DDR输出寄存器实现。
第三,约束文件里要写清楚时序路径。RGMII接口在SDC里需要设置set_input_delay和set_output_delay,特别是-max和-min延迟,不同PHY的芯片手册会给出时序参数,照着手册加,别拍脑袋。我见过太多人FPGA工程综合布线全过了,上板就是不通,后来一看约束文件里input delay根本没写,时序完全是随机碰运气,这种问题最阴间。
4.3 交换芯片和SoC侧:用什么接口更省事
如果你做的是带多口交换的设备,或者要接一颗五口/八口交换芯片,接口的选择又不一样。交换芯片通常提供两种上行接口:一种是RGMII/SGMII,用来接SoC的MAC;一种是MII/RMII,用来接PHY芯片或另一个MAC。
这里有个容易搞混的点:交换芯片的某个口到底是“MAC侧”还是“PHY侧”。要去看芯片手册里的接口模式定义,有的口是内部集成PHY的,对外是MAC接口逻辑,需要接外部PHY或MAC;有的是纯MAC口,需要外接PHY芯片;还有的是PHY口,直接接变压器上RJ45。选型时一定要先把各个口的属性理清楚,不然画完板子发现接错,返工成本极高。
工业场景和车载场景里,SGMII用得越来越多。SGMII的优势不仅仅在于引脚少,还在于它能通过SerDes跑更远的距离(板内走线即使有跨分割之类的问题,也比125MHz的并口好处理),而且传统的RGMII在车载环境EMC测试中经常因为时钟谐波问题被卡,SGMII的1.25Gbps信号频谱比较干净,更容易过测试。这也是车载以太网方案里很多SoC直接拉SGMII到PHY或者交换芯片的原因。
5. 实操中的常见问题和排查技巧实录
5.1 Link灯亮了但Ping不通,这个经典场景怎么查
这个场景在嵌入式和FPGA项目里反复出现,我把排查路径按优先级列出来,供大家参考。
第一步,确认MAC侧接口配置和PHY侧一致。MII/RMII/RGMII模式必须匹配,比如STM32配的RMII,结果PHY芯片接的是MII,有些PHY芯片不支持自动适配,就完全不通。这一步是纯软件配置问题,优先确认。
第二步,读PHY的寄存器确认Link状态和协商结果。通过MDC/MDIO读寄存器1(Basic Mode Status Register)的bit2,为1表示链路已建立。再读协商速度和双工,看是不是你要的100M全双工或1000M全双工。如果协商出来是半双工或者10M,检查线缆、对端设备、PHY配置。
第三步,检查接收方向数据是否有效。用逻辑分析仪或者FPGA的ILA抓RGMII接口的RX_CLK和RXD/RX_CTL,看有没有数据帧进来。如果RX_CTL一直为低,说明PHY没收到有效数据,问题大概率在物理层(变压器、RJ45、网线、对端设备);如果RX_CTL有脉冲但数据错乱,问题大概率在RGMII时序,重点是RX_CLK和数据之间的相位关系。
第四步,检查MAC侧有没有发出数据。抓TX_CLK和TXD/TX_CTL,看MAC有没有在发帧。如果MAC发了但PHY没出去,检查PHY的寄存器配置、发送端时钟和电压域。
第五步,确认MAC地址、IP配置、RMII时钟配置正常。这类问题经常是“配置性”的,比如MAC地址没写、IP地址没配、RMII的50MHz时钟源不对,看着是硬件问题,其实纯软件就能解决。
5.2 RGMII时序:调不通就想砸板子的元凶
RGMII的DDR结构让时序窗口非常紧张。千兆模式下125MHz,一个时钟周期8ns,但上下沿采样意味着每个数据窗口只有4ns,再算上输入输出延迟和抖动,留给设计者调整的余量很小。
实战中我总结出一套有效调试顺序:
先确定PHY芯片支持哪些延迟模式。RTL8211、YT8531这些主流千兆PHY,通常有寄存器选项控制RX delay和TX delay。默认配置可能已经是“开启内部延迟”,也可能需要你手动开,每家不一样,一定看手册。
再检查FPGA/SoC侧是否也做了延迟补偿。有些MAC侧会加额外的输入延迟约束,两边的延迟叠加会导致采样点偏移。我的经验是:优先依赖PHY内部延迟,把FPGA侧约束放宽;如果PHY不支持内部延迟,再在FPGA侧用IO delay或者约束文件修正。
最后用ILA抓包实测确认采样点。把ILA的时钟设成RX_CLK(允许时用IDELAY调整采样相位),观察RXD和RX_CTL,拨动PHY的延迟配置或者FPGA约束,直到数据窗口中间位置稳定出现正确的前导码(0x55字节序列)。这个“眼睛”调开了,基本就通了。
如果你手头有示波器,直接看RXD和RX_CLK的时序关系更快。理想状态是数据在时钟沿两侧各留2ns左右的建立保持窗口,如果看到数据翻转沿紧贴时钟沿,那就是延迟不对,迟早会出偶发丢包。
5.3 RMII时钟拓扑判断:一个容易忽略的大坑
前面提到RMII只有一根REF_CLK,但它的来源在标准里是可以多种的。实际操作中,如果PHY和MAC对时钟的“角色”认知不一致,链路必然失败。
时钟拓扑通常有两种:
- 拓扑A:外部晶振给PHY提供50MHz,PHY把REF_CLK输出给MAC。此时MAC的REF_CLK是输入
- 拓扑B:MAC输出50MHz到PHY的REF_CLK引脚。此时PHY把REF_CLK当输入
怎么看你的板子是哪种?看原理图上PHY的XI/XO引脚或者REF_CLK引脚连到哪里。如果XI/XO上有一颗晶振,接着PHY的REF_CLK输出脚连到MAC,那就是拓扑A;如果PHY的REF_CLK直接从MAC的MCO引脚来,那就是拓扑B。软件初始化时,MAC侧的时钟配置和这两套拓扑绑定,比如STM32的RMII模式下,如果要MCO输出50MHz给PHY,就得把PA8配成MCO1;如果PHY自己出时钟,PA8可能就空着。
我踩过的坑:用某国产PHY替代LAN8720时,原理图沿用旧板,发现PHY的时钟输出脚定义不完全一样,导致REF_CLK悬空。一看数据手册才发现技术参数有差异,重新接了一根线才好。所以做替代料验证时,时钟拓扑是第一个要核对的项目,别只看引脚兼容就偷懒。
5.4 抓包工具和调试方法:别让Wireshark白装了
调试以太网链路,Wireshark是终端调试的重要帮手。在PC端抓包能看协议层交互,但嵌入式侧很多环节它看不到。下面是我常用的几类调试手段:
- 板卡侧的寄存器读取脚本:通过MDIO读写PHY寄存器,写一个小工具或者脚本,把PHY的所有核心寄存器值dump出来,判断协商结果、中断状态、错误计数
- MAC侧统计寄存器:STM32/FPGA的MAC核都有统计计数器,RXCRC错误、帧对齐错误、过短帧、超长帧,这些数字能直接告诉你是物理层问题、还是MAC配置问题,还是对端行为异常
- 逻辑分析仪/ILA抓接口时序:调RGMII、RMII时序必备,抓波形才是硬道理
- 交换机和PC端抓包:用一台管理型交换机做流量镜像,对比板卡发出的帧到底对不对,结合PC侧Wireshark分析
想强调的是:一定要把抓包当习惯,而不是最后手段。我在调试一个FPGA+PHY项目时,一开始Link正常、能Ping通,但大流量传输时偶发丢包。通过MAC统计寄存器发现RXFCS错误持续增长,锁定PHY输出的数据有误码,最后发现是PHY的电源纹波在重负载时超标,数据采样窗口被压缩。这种问题如果只在应用层看,大概率要排查好几天。
5.5 几个容易被忽略的硬件小细节
最后整理几个我在画板、调试中反复遇到的硬件层面的小问题:
- PHY芯片的复位信号:很多PHY要求复位信号保持一定时间后释放,而且在释放后还要等待一段时间才能访问MDIO,这个时间通常在数据手册里写了。如果软件上电后立刻读PHY寄存器,可能读到0xFFFF,被误判为PHY不存在
- 时钟源的电平标准:RGMII/RMII的IO电平一般是2.5V或3.3V,有些PHY同时支持1.8V。电平不匹配会导致数据翻转缓慢、信号完整性问题。不同电压域之间最好加电平转换或选择IO电平匹配的器件
- 管理接口的上拉电阻:MDC和MDIO通常需要上拉电阻,有的PHY芯片内部已经有弱上拉,但为了稳定,外部加上拉更保险。上拉电阻取值不当(太大或太小)可能导致MDIO通信时好时坏
- 网口变压器的中心抽头接法:不同PHY对变压器中心抽头的接法要求不同,有的接电源、有的接地,务必按手册来。我之前见过一块板子把中心抽头接错了,导致Link一建立就丢包,PHY温度还异常高
- PHY地址的选择:PHYAD引脚一般有内部上下拉,默认地址可能是0或者1。实际项目中如果有多颗PHY,要规划好地址,而且确保和软件配置一致,否则管理接口无法正确访问
这些细节单独看都是小事,但组合在一起就决定了产品稳不稳定。做硬件的朋友应该深有体会:大多数难调的bug,回头一看都不是什么高深问题,全是细节没照顾到。
6. 调试工具准备与常用寄存器参考
6.1 必备工具清单
调以太网接口,我建议手头常备以下几类工具:
- USB转网口的调试板(USBNIC):有些场景需要模拟对端设备,一台USB转千兆网卡的设备能帮你快速确认对端MAC和PHY的行为
- 逻辑分析仪(至少100MHz以上采样率):调RMII没问题,调RGMII建议采样率500MHz起步
- 普通万用表:测PHY电源、复位电平、MDIO上拉电压,基础排查必备
- 示波器(带宽至少300MHz以上):真正要测RGMII时序和信号完整性时,示波器比逻辑分析仪更直观
- 管理型交换机(带端口镜像):五口千兆傻瓜型即可,能抓板卡发出的以太网帧,协议分析方便
- 各种长度的成品网线:别小看这个,线序不对、线缆质量差、过长,都会导致Link不稳定
工具不一定要顶级,但采样率和不丢帧很重要。逻辑分析仪如果采样率不足,抓到RGMII波形本身就是混叠的,没法做时序分析,反而误导人。
6.2 PHY核心寄存器快速参考
PHY的寄存器标准由IEEE 802.3定义,前16个寄存器是标准寄存器,不同厂商的PHY基本兼容;后面的寄存器属于厂商自定义,需要查对应的数据手册。
下面是几个调试中最常碰到的寄存器:
- 寄存器0(BMCR,Basic Mode Control Register):bit15复位、bit14回环、bit13速度选择、bit8全双工、bit12自动协商使能
- 寄存器1(BMSR,Basic Mode Status Register):bit12自动协商能力、bit11链路建立、bit9/8/7速度能力、bit5自动协商完成
- 寄存器2/3(PHY ID High/Low):读取PHY芯片的ID,用于代码里识别当前PHY型号
- 寄存器4(ANAR,Auto-Negotiation Advertisement Register):宣告本地支持的能力
- 寄存器5(ANLPAR,Auto-Negotiation Link Partner Ability Register):对端宣告的能力,从这里能看到协商结果
- 寄存器6(ANER,Auto-Negotiation Expansion Register):自动协商扩展信息
调试时我习惯先读寄存器1确认Link状态,再读寄存器4/5核对协商结果,如果链路异常再看寄存器6里的错误标志。如果这些寄存器都正常,再往MAC侧查。
一个实用小脚本逻辑(伪代码):
# 伪代码示意,实际按平台API调整 mdio_write(phy_addr, 0, 0x8000) # 软件复位PHY delay(100ms) mdio_read(phy_addr, 1) # 读状态,bit11应为1表示Link up mdio_read(phy_addr, 5) # 读对端能力,确认协商速度/双工 mdio_write(phy_addr, 0, 0x1000) # 开启自协商有MDIO读写能力的单片机和FPGA,写个简单的命令行调试小工具会非常方便。我在调试FPGA项目时通常会先写一个PC端脚本,通过JTAG/UART下发MDIO读写命令,把PHY的所有寄存器dump出来分析,比改一次编译一次上板有效率高一个量级。
7. 写在最后的经验心得
做以太网调试这么长时间,我最大的体会是:这类问题不怕难,就怕乱。很多新手拿到一个Link不上的板子,第一反应是改代码、换PHY、拆变压器,操作一顿操作猛如虎,问题依旧。实际上只要按“时钟→复位→MDIO→Link状态→数据接口→协议栈”这条链路一层层排查,大部分问题都能在半小时内定位。
顺便说一个个人体会:接口模式的匹配,比你想的更重要。RGMII配成RMII、GMII配成MII、SGMII两侧都配了MAC模式,这些是“模式级”的错误,特征是连Link都可能起不来。这比信号完整性问题更难排查,因为电气上看着全是正常的,但逻辑上完全没对上。所以拿到新板子,第一步一定是逐项核对接口模式、PHY地址、时钟拓扑,把“配置”这个变量先锁定,再去看波形。
再分享一个调试技巧:先用回环(Loopback)隔离问题。PHY芯片普遍支持内部回环和外部回环,配置寄存器0的bit14可以打开回环。如果在回环模式下数据自发自收正常,说明MAC侧和接口基本OK,重点排查PHY之外的物理链路;如果回环都不通,问题大概率在MAC侧或者接口时序上。这个技巧能帮你快速划清责任范围,省下大量无效操作。
以太网这个东西,越往底层走越能感受到“标准的力量”:那么多种芯片,不同厂商、不同工艺,只要都按IEEE 802.3来做,接口之间就能互通。理解了MAC和PHY的分工、MII系列接口的演变逻辑、常见调试方法和坑点,你再看任何以太网相关的原理图和代码,心里都会有一个清晰的框架。
这篇先到这里,后续有时间我再写协议栈、VLAN、流量控制、以及实际项目中以太网性能调优的一些内容。有具体问题也可以在评论区交流,我会挑典型的展开说。