1. 拿到RK3588以太网先别急着改代码这块板子在我手上放了三天串口能进系统显示屏能亮唯独网口ping不通。做BSP调试的人看到这个现象第一反应通常是翻设备树、改驱动、重新编译折腾一整天最后发现自己连PHY芯片用的是哪颗都没确认清楚。RK3588的以太网调试其实没那么玄但套路必须对否则就是在原地打转。这个内容适合谁看主要是做嵌入式Bring-up的工程师尤其是拿到新板子、参考设计改过、或者换了PHY型号之后需要重新适配的人。也适合正在做RK3588相关产品的驱动开发者哪怕你用的是Linux 6.x内核而不是老式4.19排查思路依然通用。先说结论RK3588以太网调试本质是三段链路的逐级确认——MAC是否工作、MDIO能否访问PHY、PHY是否完成Link Up。这三段分别对应设备树配置、MDIO通讯、PHY寄存器读写。任何一层出问题表象都可能是“网口不通”但排查路径完全不同。所以拿到板子第一件事不是改代码是先把硬件链路图、PHY地址、复位/中断GPIO、时钟来源全部确认清楚。1.1 核心思路网络调试从硬件链路图开始做BSP多年我养成一个习惯拿到新板子先画一张链路图哪怕只是手写在草稿纸上的。以太网链路尤其需要因为RK3588自带两个GMAC控制器但每路GMAC对应哪颗PHY、PHY地址是多少、复位脚和中断脚挂在哪个GPIO这些信息在原理图里一目了然在代码里却不直观。先查三样东西第一RK3588的GMAC引脚复用了哪组IO是否和SDIO、UART或其它外设冲突第二PHY芯片的地址通常由硬件上PHY_ADDR引脚上下拉决定常见0x1、0x4、0x7第三时钟来源GMAC的125M RXC/TXC时钟是来自PHY还是来自SoC这直接决定设备树里clocks该怎么配。我在某项目的调试记录里写过一段话如果硬件工程师说“参考设计都一样的”那大概率就是这里不一样。换过PHY型号、改过复位脚、调整过时钟源设备树还按老的写必然起不来。1.2 BSP视角驱动、设备树、PHY各管哪一段很多人习惯把“以太网驱动”当成一个整体但对BSP调试来说必须拆开看。RK3588在Linux下走的是stmmac驱动框架也就是DesignWare MAC系列。设备树负责描述“MAC外部有什么”包括PHY挂在哪个MDIO总线上、PHY地址是多少、RGMII模式下需要多少时钟延迟、复位脚是哪个。PHY驱动程序负责和具体的PHY芯片寄存器打交道比如Marvell的mvneta是MAC驱动而PHY驱动一般是通用phy驱动加上厂商特定的配置页。定位问题的顺序很重要先确认PHY有没有被正确探测再确认MAC和PHY之间的链路是否协商成功最后才轮得到DMA、中断、收发包路径。跳过前面直接看ping丢包率等于没找到病根就开始吃药。2. 设备树配置一个坑一个坑填RK3588的以太网设备树节点很多工程师第一眼看到就头疼因为属性实在太多了。但其实核心就两个节点gmac0和gmac1对应内核里的两个以太网控制器。我这里以实际项目中常用的一个gmac1节点为例展开讲每个属性的含义和坑点。gmac1 { status okay; phy-mode rgmii; clock_in_out input; snps,reset-gpio gpio2 RK_PB3 GPIO_ACTIVE_LOW; snps,reset-active-low; snps,reset-delays-us 0 10000 50000; assigned-clock-parents cru CLK_GMAC1_RX_TX; assigned-clock-rates 0, 125000000; pinctrl-names default; pinctrl-0 gmac1_miim gmac1_tx_bus2 gmac1_rx_bus2 gmac1_rgmii_clk gmac1_rgmii_bus; tx_delay 0x21; rx_delay 0x1f; phy-handle phy0; mdio { compatible snps,dwmac-mdio; #address-cells 1; #size-cells 0; phy0: ethernet-phy0 { reg 0x0; }; }; };2.1 RK3588 GMAC控制器地址与DTS框架RK3588的GMAC0和GMAC1各有独立的中断号、时钟和复位控制器在设备树里通常位于根节点下的gmac0和gmac1节点。注意不是所有RK3588板子都会把两个GMAC同时启用有些方案的GMAC1直接没有接口软件配置时最好先在TRM里确认SoC的引脚分配。这里的gmac1写法是因为公版dtsi里已经定义了gmac1节点板级dts只需要覆盖(status、pinctrl、phy属性)。千万别自己新建节点而是要在板级dts里以gmac1方式追加修改否则内核会把重复节点合并得莫名其妙你都不知道是哪个生效。还有就是pinctrl那一段。gmac1_miim是MDIO两根线的复用gmac1_tx_bus2是发送数据线gmac1_rx_bus2是接收数据线gmac1_rgmii_clk和gmac1_rgmii_bus是RGMII模式下的时钟和数据总线。如果这些pinctrl配置不全内核启动时可能探测到eth0但接口一直是down。2.2 关键属性phy-handle、phy-mode、tx/rx延迟phy-handle指向mdio节点下的某个PHY子节点这个引用关系很直接但写的值必须和硬件一致。比如上面mdio子节点里ethernet-phy0的reg 0x0意味着PHY地址是0。如果硬件实际是1在Linux里你会在启动日志中看到PHY 0:00 not found或者探测到错误的PHY。phy-mode rgmii有两种常见写法rgmii和rgmii-id。两者的区别非常有迷惑性。rgmii模式默认不做任何延迟补偿需要你在MAC侧的tx_delay/rx_delay手动配rgmii-id表示PHY侧已经内置了延迟MAC侧无需再补偿。RK3588大多数板子用的是rgmii然后在DTS里手动配tx_delay和rx_delay。这两个值的单位是纳秒但DTS里通常写成十六进制整数实际意思是步进值。更坑的是这两项不是万能数值。不同PCB走线长度不一样别的板子用0x30好使你的板子就得0x21。通常我会把tx_delay从0x00开始调到0x3f每次改bin都要重编麻烦但有效。最快的方法是在u-boot里用mdio命令直接改PHY寄存器或者在Linux下用devmem改MAC寄存器先找到能通的值再固化到DTS。2.3 时钟频率与复位脚最容易翻车的两个点clock_in_out input表示GMAC的时钟来自外部PHY回传的125MHzoutput则相反由SoC向外供时钟。这个必须和硬件原理图对应。常见错误是PHY的CLK_OUT到SoC的XCLK走线没连但你配了input看起来初始化正常实际link up以后收发都不通。复位脚的三个属性也很容易出错snps,reset-gpio指定GPIOsnps,reset-active-low表示低电平复位snps,reset-delays-us三个值分别是复位前延时、复位持续时间和复位后延时。我遇到过一次复位后延时给太短PHY还没完全从硬件复位恢复MDIO系统就开始读寄存器结果读到全0xFFPHY直接识别失败。后来把第二个值从5000us调到50000us问题就消失了。这个教训送给所有做BSP的人设备树里的延时参数不是摆设尤其是在PHY上电和复位这种硬件时序敏感的场景里宁可多给不要抠门。3. PHY移植与MDIO通讯调试设备树写完之后下一步是最容易劝退新人的环节MDIO总线上读不到PHY。MDIO就是用来管理以太网PHY的一组两根线MDC是时钟、MDIO是数据。RK3588的GMAC内部集成了MDIO控制器驱动通过读写PHY寄存器来获取状态、配置速度和双工模式。3.1 PHY地址和MDIO总线探测PHY地址不是软件随便定的而是PHY芯片上电时根据引脚电平锁存的。最常见的地址是0x1和0x7但RK3588的方案里也有不少用0x0、0x4。拿到板子第一时间用万年历测PHY_ADDR引脚电平或者干脆挨个扫描。Linux下最简单的验证方式是启动后在/sys/bus/mdio_bus/devices/下看设备目录。比如rootrk3588:/sys/bus/mdio_bus/devices# ls 30be0000.ethernet-0:00如果有这个目录说明MDIO读到PHY了其中30be0000.ethernet是GMAC节点的reg地址后面的:00就是PHY地址0。如果什么都没有先检查设备和PHY的供电、MDIO上拉电阻、时钟而不是怀疑内核代码。3.2 内核PHY驱动配置与识别日志内核启动日志里有一行很关键的mdio_bus 30be0000.ethernet-1: MDIO device at address 1 is unknown这说明MDIO能访问到地址1但内核认不出是哪颗PHY。常见情况是内核开启了CONFIG_PHYLIB但没有启用对应PHY厂商的驱动。比如PHY芯片是裕太微的需要在设备树里配置compatible ethernet-phy-id1234.5678或者内核配置里打开该驱动。用ethtool eth0查看也能辅助判断Settings for eth0: Supported ports: [ TP ] Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 1000baseT/Full PHYAD: 0 Transceiver: external Auto-negotiation: on如果PHYAD显示0说明驱动已经识别到PHY。这里还要注意一点有些PHY需要写厂商私有的配置寄存器比如百兆千兆切换阈值、LED输出模式、EEE节能以太网不做初始化的话能link但性能差。这类寄存器的初始化通常放在PHY驱动里的config_init回调中或者通过DTS的marvell,reg-init之类的属性填。3.3 百兆通千兆不通先别怀疑芯片这类问题很容易让人误判成“PHY坏了”。实际上RK3588平台上我遇到的大多是RGMII时钟延迟没调对。千兆RGMII模式边沿采样要求非常严格TX和RX路径上的SKEW一旦超出容限就会表现为偶尔能通、大概率不通或者网卡显示1000M但实际丢包严重。我的排查手法是先把phy-mode临时改成“百兆模式强制”比如ethtool -s eth0 speed 100 duplex full autoneg off如果能稳定工作几乎可以断定RGMII延迟配置有问题而不是DMA或者驱动问题。这种“降速复现法”帮我解决过至少五个项目。4. 从ping不通到跑满带宽的排查路径写这一节时我把过去在RK3588平台上遇到过的以太网问题按现象归了类方便你对照排查。注意这里的顺序很重要不要跳步。4.1 点灯还灭供电、复位、晶振三板斧如果ethtool eth0里面Link detected: no而且PHY灯不亮那软件还没到协议层先查硬件。第一看PHY母座附近有没有3.3V和1.0V/2.5V供电尤其部分差分PHY用1.0V的DVDD单独一路LDO供电查起来隐蔽。第二看复位脚电平低电平复位是正常但有些设计把RC复位时间拉得很长导致内核开始MDIO探测时PHY还没起来。第三看25MHz晶体两脚波形。我在一个项目里发现PHY完全无响应最后用示波器看晶振才发现焊接虚了MDIO当然什么都读不到。所以这一步别嫌麻烦万用表和示波器比改代码快得多。4.2 能识别但不Linkphy-mode没那么简单PHY能被MDIO识别说明硬件的管理通道没问题但数据通道不一定通。典型现象设备树里phy-mode rgmii-idPHY也内置了延迟但PCB走线过长时序裕量不够。这时先确认内核日志里的PHY协商状态rk_gmac-dwmac fe2c0000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx协商到1Gbps但网线插上后反复Link Up/Down大概率是物理层信号质量问题。先试试加tx_delay和rx_delay如果依旧把phy-mode改成rgmii并同时关闭PHY侧延迟两种方式交叉测试很快能定位出是MAC侧还是PHY侧延迟不足。4.3 能Link但ping不通MAC、PHY、MDIO逐级定位链路已经Up说明物理层协商成功了但Ping不通问题转移到协议栈以下的数据通路。先看一眼ip addr show eth0如果MAC地址全是零比如00:00:00:00:00:00说明从OTP或EEPROM读MAC失败包发出去也回不来。解决方式要么在U-Boot里把MAC写入环境变量要么在DTS里加mac-address [00 00 00 00 00 00]配置固定的地址但这只是临时方案。量产板子最好把MAC烧进OTP或靠烧录工具写。MAC地址正常接着看DMA状态和收发计数ethtool -S eth0重点关注tx_errors、rx_errors、rx_missed、tx_dropped这几项。如果rx_errors在增长多半是FIFO溢出或者描述符不够如果只有tx_dropped增长可能是上层驱动对DMA映射处理有问题。5. 性能优化让RK3588的GMAC跑满千兆有些场景下第4节的步骤都完成了板子也能正常上网但吞吐率上不去。比如iperf3测出来只有五六百兆在高负载项目里完全没法交差。RK3588的GMAC理论带宽是千兆实际跑满需要做一些调优。5.1 关闭以太网自适应协商的坑自适应协商对普通办公网络友善但对高性能传输场景会引入额外开销。第一次协商时如果因为对端交换机不支持EEE或者链路抖动很容易锁定在百兆。所以固定千兆全双工往往最稳定尤其在做点对点数据采集时关闭Auto-Neg没关系反正两端都是可控设备。但注意强制千兆时交换机和测速仪也必须锁定千兆全双工只锁一端会出现严重丢包。命令是ethtool -s eth0 speed 1000 duplex full autoneg off5.2 中断合并、DMA描述符与Ring Buffer调参RK3588的GMAC驱动中断开销很大尤其小包转发场景每个包一个中断直接让CPU爆掉。这时候调整中断合并是个有效手段但前提是驱动支持。stmmac驱动里有两种方式一种是打开NAPI并且合理配置gro_flush_timeout另一种是修改DMA的tx_coalesce和rx_coalesce参数。另外Ring Buffer默认值往往偏保守默认256个描述符对大流量会显得不够产生rx_missed。调大它ethtool -G eth0 rx 1024 tx 1024调完后用ethtool -g eth0确认生效。要记住这不是一劳永逸有些PHY或者高延时网络下过大的ring buffer反而会加大延迟需要根据实际应用场景权衡。5.3 CPU亲和性和中断绑定RK3588是四核A76加四核A55的大小核架构如果你把以太网中断默认跑到A55小核上大流量时CPU占用率直接升高到无法看系统其它任务。Linux的irqbalance服务在运行时会自动均衡但调试阶段最好手动绑定到A76大核上。先看中断号和当前CPUcat /proc/interrupts | grep eth0找到IRQ号之后绑定到CPU2或CPU3A76簇的核echo 4 /proc/irq/36/smp_affinity这里4对应二进制100即CPU2。同时把处理收包的应用线程也用taskset绑定到同一个核能明显降低跨核调度带来的缓存抖动。5.4 iperf3测速时的常见幻觉调优完第一件事不是兴奋而是冷静看数据。iperf3默认单线程可能跑不满千兆要用-P 4或-P 8开启多流。还有TCP在大延迟网络下受窗口限制测速时优先用UDP模式确认物理层能到多少iperf3 -c 192.168.1.10 -u -b 1000M -l 1450 -t 10UDP能跑满千兆TCP差很多再考虑调TCP缓冲区UDP本身都跑不满那回来继续查PHY延迟、DMA和中断。6. 常见问题排查清单与调试心得这一节是纯实战记录很多坑我都是跳到第N次才总结出来的现在一次性写下来希望你能跳过。6.1 快速排查清单现象优先检查项常见根因PHY不被识别MDIO总线上设备列表PHY地址不对、复位时间不够、MDIO上拉缺失Link Up但ping不通MAC地址、tx/rx_error计数MAC未烧写、DMA描述符不够、时钟延迟错误千兆协商失败phy-mode、tx_delay/rx_delayRGMII时序偏移超限1000M协商成功但丢包示波器测RXC/TXCPCB走线等长问题、PHY内置延迟和MAC侧延迟叠加性能只有600MCPU亲和、ring buffer中断跑到小核、ring太小开机偶尔Link不上reset-delays-us复位后延时太短这张表是我做BSP这些年最常用的自查索引。每次网口出现问题先对号入座不要把时间浪费在“重编内核”上。6.2 调试心得多用工具链少靠猜最后再分享几个我个人特别依赖的工具和命令。除了ethtool还有个神器是mii-tool虽然老但在排查PHY协商时非常好用。另外Linux内核打开CONFIG_DEBUG_FS之后/sys/kernel/debug/stmmaceth/目录下能看到MAC内部寄存器的值调延迟参数时比一遍遍重编DTS高效得多。PHY寄存器读写用phytool也很顺手比如直接读PHY的基础状态寄存器phytool read eth0/phy/0/0x01看到0x7d通常表示协商完成且全双工链路正常。我自己踩过最深刻的一次坑是连续两天以为驱动有问题反复改DTS结果只是PHY芯片的中断脚没有接到RK3588的GPIO导致链路状态变化时Linux感知不到。后来把这个中断脚配好问题直接消失。所以拿到硬件一定先看原理图把PHY中断和复位脚理清楚再动代码。RK3588的GMAC本身不复杂复杂的是外部的PHY、时钟、电源和PCB走线BSP调试的功夫基本都花在这些“看不见的外围”上了。