做BSP调试这活儿图的就是一个“反着来”越觉得网口这种标配外设应该自己能好越得把每个环节拆开确认一遍。RK3588现在在很多板上都是主控核心千兆以太网几乎成了标配可恰恰是这块看起来最普通的网口在BSP阶段出问题的概率一点不小。这次想记录的是RK3588平台上从零开始调试以太网的全过程——硬件链路怎么理解、设备树节点怎么填、PHY为什么总认不到、RGMII延时那笔账怎么算以及几个踩过的坑。内容写给正要接手类似平台的同事也给自己留一份能照着做的流程。1. 动手之前先把RK3588以太网这套链路拆干净1.1 芯片侧与外设侧MAC、PHY、MDIO三者各自什么角色以太网调试最忌讳上来就敲命令。RK3588集成了MAC控制器MAC负责数据链路层的封包、CRC、流控这些逻辑但要把数据真正发到网线上还得靠一颗外置PHY芯片完成物理层的编码、调制、收发。MAC和PHY之间的握手就靠MDIO总线——一根时钟线加一根数据线用来读PHY寄存器、写PHY配置。板级实现上SoC通常通过RGMII接口与PHY相连。RGMII在千兆模式下使用125MHz参考时钟数据线按DDR方式传输发送和接收各4根线整体引脚不算多。接口本身不复杂容易出问题的是时序RGMII标准要求发送侧和接收侧各自做延时调整这个点会在设备树里用tx_delay和rx_delay体现后面专门展开。理解这条链路之后才会明白一个关键道理以太网起不来问题可能出在MAC、PHY、MDIO、时钟、电源、复位、网络变压器、网口座子任何一个环节。如果上来就怀疑驱动方向一开始就错了。BSP调试的核心素养就是把链路上每个环节的自检方式都准备在手边。1.2 软件侧的关键路径设备树、驱动、内核网络栈硬件链路之外软件侧也有自己的链条。RK3588的以太网驱动在主线内核里是dwmac-rockchip基于stmmac框架实现。设备树负责向内核描述“SoC外挂了哪颗PHY、走什么接口模式、时钟和复位怎么接”驱动按设备树配置去初始化MAC、通过MDIO枚举PHY、注册net_device。用户态方面常用的工具就是ifconfig或ip命令激活接口、ethtool查看链路状态和PHY寄存器、mii-tool做PHY层的传统检查、ping验证连通性、iperf测吞吐。这些命令看起来简单但每一条输出背后都对应着驱动和硬件的某个状态能不能读懂决定了排查效率。我习惯把调试分成三个层次链路层PHY识别、link建立、网络层IP、路由、ping、性能层吞吐、中断、延迟。一层层往上查能避免很多瞎猜。这个分层思路贯穿整篇后面所有操作都围绕它展开。2. 调试环境与前期准备连接方式、内核配置和工具链2.1 硬件连接怎么搭算稳妥调试以太网不是只插一根网线就完了。串口是必须的RK3588调试串口一般默认输出到UART波特率常用1500000通过串口转USB接到PC确保能完整看到内核日志。这一步没准备好后面任何信息都拿不到。网线端建议准备一根短网线调试早期直接连交换机或PC网口不建议接路由器甚至走外网少一个变量就多一分可控。如果PC有千兆网口用网线直连板子和PC配静态IP后面性能测试也方便。硬件上另外要注意电源。RK3588整板功耗不低PHY对供电噪声也比较敏感。我之前遇到过PHY稳定识别但link反复闪的情况查到最后是给PHY供电的LDO纹波偏大。BSP阶段越是玄学问题越要回头查供电和地线。2.2 内核配置需要打开哪些选项既然是BSP调试内核配置绕不开。RK3588的以太网驱动在ARM64 defconfig里通常默认开启但自己的内核要确认包含以下选项CONFIG_STMMAC_ETHstmmac核心驱动CONFIG_DWMAC_ROCKCHIP瑞芯微平台MAC驱动CONFIG_PHYLIBPHY子系统的基础CONFIG_MDIO_BUSMDIO总线支持CONFIG_PHY_REALTEK或者对应PHY厂商的驱动PHY驱动这块最容易漏。很多板子外挂的千兆PHY如果没有匹配的PHY ID驱动会回退到generic PHY。generic PHY驱动能完成基础配置但部分功能比如EEE、内部时钟输出、集成变压器配置可能失效。所以我建议BSP阶段把常见PHY驱动都编进去宁可内核大一点也要启动时直接看到正确的PHY绑定信息。此外CONFIG_DYNAMIC_DEBUG、CONFIG_DEBUG_FS最好都打开。驱动里很多pr_debug是在动态打印里输出的排查PHY ID识别和链路异常时通过debugfs或dynamic_debug控制打印级别非常有用。2.3 调试工具与根文件系统准备交叉编译一套用户态调试工具集是很值的。最核心的几样busybox自带ifconfig、ping、route、ethtool、mii-tool、iperf3、devmem直接读写寄存器排查IO状态和时钟时是杀手锏、strace怀疑应用层问题时用。我会把它们放进rootfs的/usr/bin配合NFS启动或者直接放SD卡。为了调试方便rootfs做成可写板子上临时改eth0配置、加载内核模块都灵活。这里有个小建议准备一个专门的调试内核和调试rootfs和量产配置分开。调试内核把各种CONFIG打开量产再关掉避免量产代码里残留一堆打印也减少环境差异导致问题复现不了的情况。3. 设备树RK3588以太网节点从零到能用的完整写法3.1 GMAC主节点与PHY子节点的配置要点RK3588的设备树以太网节点结构不算复杂但每个字段都有讲究。一个典型节点可以长这样以实际调试中使用的配置为蓝本gmac0 { status okay; phy-mode rgmii; clock_in_out input; snps,reset-gpio gpio4 RK_PB2 GPIO_ACTIVE_LOW; snps,reset-active-low; snps,reset-delays-us 0 10000 100000; pinctrl-names default; pinctrl-0 gmac0_rgmii_miim gmac0_rgmii_tx_bus gmac0_rgmii_rx_bus gmac0_rgmii_clk gmac0_rgmii_bus; mdio { compatible snps,dwmac-mdio; #address-cells 1; #size-cells 0; phy: ethernet-phy1 { reg 1; compatible ethernet-phy-id001c.c916; clocks cru CLK_GMAC0_PHY; reset-gpios gpio4 RK_PB2 GPIO_ACTIVE_LOW; reset-delay-us 10000; reset-post-delay-ms 100; }; }; };简单解读phy-mode决定接口模式rgmii是千兆最常见的配置。clock_in_out通常设为input表示125MHz主时钟由外部PHY提供给MAC这也是大多数板子的做法。reset相关字段有两种写法snps,reset-*前缀由MAC驱动控制放在PHY子节点里用reset-gpios则更贴近PHY初始化时机。个人更倾向放到PHY子节点复位时间点控制更精准。PHY子节点的compatibleethernet-phy-id后面跟着的是PHY芯片ID前四位是OUI后两位是型号和版本。这个ID可以从PHY手册查到也可以在驱动源码里搜更直接的办法是硬件接好之后用mdio工具读PHY寄存器2和3。ID写错会导致PHY驱动匹配失败退化成generic PHY某些寄存器就不会被正确配置。3.2 RGMII延时这笔账到底怎么算RGMII延时是RK3588以太网调试里最经典的知识点。RGMII标准里发送侧在时钟上升沿发送TXD[3:0]下降沿发送TXD[7:4]接收侧要准确采样数据相对时钟就必须有合适的相位差。标准规定源端或者宿端提供大约1.5ns到2ns的延时。设备树层面这个延时通常表现为tx_delay和rx_delay两个字段。RK3588的设备树里延时值有时是十六进制数新版内核也会用picosecond单位。调试时最常见的现象是link能建立、自协商正常但ping不通或者吞吐极低抓包全是不停的FCS错误或alignment错误十有八九是RX或TX的延时不对。我实际操作时会先把tx_delay和rx_delay都设成零然后查PHY数据手册里RGMII时序章节把推荐的典型延时值填进去跑一轮iperf确认rx_fcs_error为0。如果手册只给了ns注意换算成设备树要求的单位。一个可参考的经验值很多RGMII方案最终落在tx约1.5ns到2ns、rx约1.5ns到2ns区间不同PHY会有差异。遇到丢包问题没有示波器的情况下可以用二分法把延时从0到2.5ns扫几轮记录每个配置的错误包数基本也能找到最优窗口。这个操作看着笨但比盲目改代码有效的多。3.3 时钟与复位BSP阶段最容易翻车的两个坑以太网BSP调试里时钟错误是最痛苦的因为软件看着完全正常PHY也识别到了但吞吐和link就是不对。RK3588的GMAC有几个关键时钟RGMII的125MHz参考时钟、MAC内部时钟、MDIO时钟。设备树clocks属性必须和芯片手册对应clock_in_out也会影响时钟方向。如果MAC控制器时钟不对典型现象是PHY能通过MDIO枚举到但速率协商后通信异常dmesg里可能看到类似Could not set MAC clock的错误。排查时先确认SoC时钟树的PLL配置再确认驱动读到的clk频率是否符合phy-mode对应的预期值。还有一部分PHY需要独立的参考时钟输入如果板子上没接或者设备树没配PHY会完全不工作。复位也一样。MAC的复位在设备树resets属性描述PHY复位一般走GPIO。GPIO复位时序尤其关键复位释放后要等PHY内部上电稳定、晶体起振完成一般需要几十毫秒。reset-delays-us参数里有复位前置延时、复位宽度、复位后等待时间三个阶段。等待时间给短了PHY可能偶尔初始化不完整现象就是时好时坏。注意不同PHY复位恢复时间差异很大不能照抄默认值。我遇到过一颗很常见的PHY释放复位后必须等至少100ms才能访问MDIO否则会间歇性读回全F。项目上建议在批量调试之前实际测一下自己板子上复位到MDIO可访问的间隔然后把这个值放大一点写进设备树。4. 上电调试实操链路、数据、性能一步步验证4.1 第一步确认PHY被正确识别板子上电、内核起来之后先看dmesg里和eth/gmac/mdio相关的打印。正常启动会看到类似这样的输出dwmac fe1c0000.ethernet: IRQ eth_wol not found dwmac fe1c0000.ethernet: User ID: 0x52, Synopsys ID: 0x51 ... mdio_bus fdd50000.ethernet-1: MDIO device at address 1 is: ethernet-phy-id001c.c916关键信息是最后一行MDIO设备地址、PHY ID是否和你用的PHY对应。如果看到没有任何PHY枚举或者被generic PHY接管就要查设备树里ID写没写对、驱动核心里有没有对应条目。用ifconfig -a查看网络接口。RK3588的GMAC通常对应eth0具体由设备树aliases决定。确认接口存在后不要急着配IP先用ethtool eth0看支持的接口模式、PHY地址、link状态这一步基本能确认驱动和设备树是否跑通。4.2 第二步link建立与自协商检查设置IP之前先确保物理层link起来了。网线插好看板子网口灯状态同时执行ethtool eth0正常输出里Speed、Duplex会显示实际协商结果。看到link down按顺序查三件事PHY复位GPIO是否已经正确拉高MDIO总线能不能访问PHY寄存器用mii-tool或mdio工具读reg 0/1PHY供电和晶体时钟是否正常。link起来但速率不对也很常见。板子明明是千兆PHY却只协商到100M先看是不是千兆模式的4对差分线有断线或错配。也可以强制指定速率ethtool -s eth0 speed 1000 duplex full autoneg off强制能通而自协商不通多半是PHY寄存器里没有正确开启千兆能力或者PHY驱动没有完整初始化。这种情况要翻驱动里config_init函数看相关寄存器有没有被跳过。4.3 第三步数据通路与吞吐验证链路OK之后给板子配置IP再调通数据面。直连PC的经典配置ifconfig eth0 192.168.10.10 upPC一侧配同网段静态IP先用ping验证小包再加大包ping -s 1472 192.168.10.10MTU为1500时1472是最大无分片有效负载这个测试能同时验证收发路径和分片逻辑。吞吐测试用iperf3iperf3 -s # PC上运行服务端 iperf3 -c 192.168.10.10 -t 30 # 板子上作为客户端如果吞吐明显低于千兆线速比如只能跑几百M下一步看rx/tx错误计数和中断分布。ethtool -S eth0能查驱动统计cat /proc/interrupts看中断是否扎堆在某个核上。RK3588多核性能强一般不会因为CPU能力导致吞吐问题但如果驱动有bug某个核的软中断可能变成热点导致丢包。这种场景要确认eth0的IRQ亲和性是否合理用taskset之类工具可以调整。注意收方向吞吐掉一半同时RX差分线走线较长重点查rx_delay配置-往往不是驱动逻辑问题而是物理时序窗口不够。这个坑靠软件看半天看不出来回到时序上反而很快。5. 踩坑记录典型问题与排查思路5.1 问题速查表平时调试遇到的问题大多能归成几类整理成速查表遇到现象直接对号入座现象优先排查方向常用手段PHY地址扫不到MDIO总线、复位GPIO、PHY供电devmem读MDIO控制器寄存器、示波器抓MDC/MDIO内核报PHY ID错误设备树ID、驱动PHY ID表读PHY reg2/reg3对比数据手册link不起来PHY寄存器0/1、复位时序mii-tool -r强制重启、测量PHY时钟link正常但ping不通RGMII延时、MAC时钟方向ethtool -S查看错误计数、调整tx/rx_delay能通但吞吐低中断亲和性、电源噪声、PCB走线iperf3分段测试、cat /proc/interrupts开机偶发link失败复位等待时间、电源上电时序增加reset-delays-us、串口加log观察时序这张表不能替代实际分析但能让“没头绪”的时刻变成有序排查过程。遇到新问题的处理习惯是先写清楚复现条件、现象、最近改动再对照表里最接近的条目去查效率会高很多。5.2 实战案例PHY地址为什么读不到有一次调一块RK3588板子dmesg里完全没有MDIO设备枚举的信息。设备树地址写的0x01看起来没错。接着用devmem直接读GMAC MDIO控制器寄存器确认MDC时钟有没有在跑结果发现握手寄存器状态异常MDIO总线基本没有输出。一路追下去根因是PHY复位引脚和板子上某个测试点复用pinctrl里被误配置成别的功能GPIO被拉低PHY始终处于复位状态。这类问题靠软件栈很难直接发现但调试经验多之后会形成反射任何软件看起来没问题的PHY异常先量复位脚、电源脚、时钟脚三个电压比看十行日志都有效。也因为这个原因我现在拿到一块新板子第一件事是让硬件同事提供完整的IO复用和电源树文档而不是只看原理图里PHY那一页。5.3 实战案例link正常但ping不通最后竟是延时配置另一个印象深刻的案例是某块板子link和自协商都正常PHY驱动也没有报错但ping小包时通时不通丢包率大约30%。当时怀疑网线、交换机换过都不行。折腾一圈才想到去查rx错误计数ethtool -S eth0 | grep rx_error结果rx_fcs_error和rx_align_error非常夸张。FCS错误是物理层数据完整性出问题的典型症状PHY能收到数据但采样窗口落在数据跳变沿附近采到了错误比特。问题直接指向RGMII的rx延时配置。这块板上PHY的RXD路径比参考时钟走线长了大概几十mil驱动默认延时不够。于是把rx_delay从0.4ns扫到2.0ns发现1.2ns到1.5ns窗口里错误计数清零吞吐直接上千兆线速。之后把最优值固定进设备树。这个案例给我的教训是高速接口问题先怀疑时序再怀疑代码。5.4 吞吐跑不满先从软中断和电源上找吞吐跑不满千兆很多人第一反应是调驱动性能参数但以RK3588的CPU性能来说千兆纯软件层面根本不是瓶颈。我遇到过的两种典型原因一是软中断集中在一个核配合调度延迟导致吞吐波动二是PHY或MAC供电噪声在高速收发时导致物理层误码吞吐上不去还伴随FCS错误。处理方式分别是设置IRQ亲和性以及检查PHY供电脚位的纹波。这两个都没问题再看驱动ring buffer参数和NAPI权重比如ethtool -G eth0 rx 4096但这一步放到最后不要一上来就改参数。提示上面排查顺序大概率能覆盖80%场景。如果项目用的是USB转以太网或者PCIe以太网方案链路里会多一层桥接排查还要加上总线枚举那一环。5.5 排错过程中值得养成的几个习惯BSP阶段调试日志习惯决定效率。我之前调试经常吃“忘了记参数”的亏——调了一下午找到一个能用的延时值结果第二天环境变了原来的配置又不对但已经忘了之前试过哪些值。现在统一用调试记录模板包含时间、内核版本、设备树文件、硬件版本、现象、尝试过的参数组合、结果每轮实验必记。看起来麻烦但后期回看时这些记录全是财富。还有一点每次只改一个变量。延时、PHY模式、时钟频率这些参数都是联动的同时调两个变量出问题时根本说不清是哪个导致的。保持单变量原则排查速度会快很多。这个原则在BSP调试里永远不过时。另外建议把每次能稳定复现问题的内核日志存一份按日期命名用串口工具记录下来。很多问题在量产阶段才暴露如果没有当时的原始日志回查会非常痛苦。写在最后RK3588以太网BSP调试做到最后反而觉得最简单的地方最容易被忽略——RGMII的delay、PHY的复位等待、MDIO的总线时序这些东西资料上都有但不踩一遍就是不深刻。我的体会是每次调试前先在纸上把链路画出来标记好每个环节的预期状态和验证方法按顺序排查比拿着网线到处插管用得多。另一个值得养成的习惯就是前面说的记录命令、日志、寄存器、延时参数这些数据在量产阶段回看时都是宝贵资产。嵌入式外设调试七分靠逻辑三分靠手快。工具熟了思路顺了剩下的大多数问题都只是时间问题。这套流程在我手头已经验证过好几轮下一次换成别的SoC平台我还是会按同样的顺序来一遍。