ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

STM32MP255F eth1 driver error排查:从设备树到PHY的完整实战指南

STM32MP255F eth1 driver error排查:从设备树到PHY的完整实战指南 如果你是因为 STM32MP255F 的 eth1 driver error 搜到这里那我们先对个暗号eth0 千兆好好的eth1 要么在ifconfig -a里根本不出现要么每个包都丢得一塌糊涂内核日志里翻来覆去就是 stmmac 那几行。这块芯片是 STM32MP25 家族里的新面孔自带两路千兆 GMAC照理说驱动和 MP1 时代一样成熟但恰恰因为多了第二路网口BSP 里默认给 eth1 的配置并不总是完整的。这篇文章不谈手册复读只记录我在这类板子上从看到 driver error到把 eth1 跑满千兆的完整排查思路。适合正在调 STM32MP25 BSP、或者被其它 SoC 双网口驱动问题折磨的嵌入式工程师。1. 为什么偏偏是eth1STM32MP255F的双网口资源布局很多人在 eth1 上报错后第一反应是去翻 stmmac 驱动源码这是最浪费时间的一条路。因为 eth0 能正常起来说明驱动本身在你的内核里是能工作的eth1 的问题几乎都集中在实例化这一层设备树节点、引脚复用、时钟、PHY 复位。1.1 从芯片资源看GMAC0与GMAC1的差异STM32MP255F 内部集成了两个独立的千兆 MAC我习惯把它们叫 GMAC0 和 GMAC1对应 Linux 里的 eth0 和 eth1。两个 MAC 的 IP 核本身是同一个都支持 RGMII/RMII但它们在 SoC 里的资源并不完全对等。用一张表可以看得很清楚对比项GMAC0通常为 eth0GMAC1通常为 eth1典型接口RGMII / RMIIRGMII / RMII常见外接 PHY板载千兆 PHY第二路 PHY 或交换芯片时钟输入ETH0CK_K、ETH0PTP_KETH1CK_K、ETH1PTP_K引脚复用压力较小常与 SDMMC、FDCAN、UART 复用BSP 默认使能情况基本都开启经常是 disabled 或缺少 pinctrl实际案例里GMAC1 的引脚冲突是最隐蔽的问题。很多开发板为了引出第二路网口需要把 GMAC1 的 TX/RX/CLK/MDIO 信号从其它外设的复用里让出来。原理图改了设备树没改驱动 probe 时拿不到正确的 pinctrl 状态就会直接报错但报错信息往往是failed to get clk或者resource not found这类泛泛的文本不会直接告诉你是引脚被占。另一个常见的差异是 MDIO 总线。两个 MAC 各有独立的 MII 管理接口可以在设备树里各挂各的 PHY。如果板子上实际用的是同一个 MDIO 总线、两个 PHY 挂在同一个 MDIO 上但设备树里 eth1 的 mdio 子节点没写对 PHY 地址就会出现eth0 能起来eth1 死活 no PHY found。1.2 先分清是MAC没起来还是PHY没起来ETH1 driver error 这个描述太宽泛了它可以是好几种完全不同的故障表现。如果不上板先做判断后面所有操作都会像无头苍蝇。上电后先跑三条命令ifconfig -a dmesg | grep -E stm32-dwmac|mdio|eth1 ip link show然后按下面的表格对号入座现象所处阶段主攻方向ifconfig -a里没有 eth1dmesg 里也没有任何 stm32-dwmac probe eth1 的记录设备树或驱动 probe 之前失败检查节点 status、pinctrl、时钟dmesg 里有 stmmac MAC 初始化日志但随后报no PHY found或Cannot attach to PHYPHY 探测阶段检查 PHY 地址、复位、MDIO 引脚、PHY 驱动eth1 存在ip link show显示 DOWN插上网线也不变 UPPHY 已经识别但 link 建立失败检查 phy-mode、时钟方向、网口变压器/线缆eth1 显示 UP但 ping 不通或吞吐极低链路已通数据通路异常检查 RGMII delay 配置、时钟频率、MAC 地址冲突这个分类非常关键。我见过有人在no PHY found阶段跑去改 stmmac 的 DMA ring buffer 大小折腾两天毫无意义。先定位到卡在哪一步再去动设备树或驱动效率完全不同。2. 排查前必须确认的三件事设备树、内核配置与时钟供给在把 dmesg 从头翻到尾之前建议先做三个基础确认。这三个地方任何一个有问题都会让 eth1 以一种非常类似驱动 error的形式表现但实际都不是驱动代码问题。2.1 设备树节点与aliaseseth1到底被系统认了没有Linux 里网络接口的名字不是驱动自己起的而是根据设备树 aliases 里的ethernet0、ethernet1映射出来的。如果 aliases 里没有第二个口驱动即使成功 probe 了 GMAC1接口名也可能是随机的enx...而不是 eth1。先看设备树别名cat /proc/device-tree/aliases/ethernet1这个文件的内容是一个 phandle不是字符串所以输出是二进制乱码或类似十六进制内容不用惊讶。你要确认的是这个文件是否存在。如果不存在或者值指向的节点不对eth1 的命名就会出问题。再看 eth1 对应的 MAC 节点到底有没有被使能find /proc/device-tree -name *ethernet*找到类似ethernet482d0000的目录后查看它的 statuscat /proc/device-tree/soc/ethernet482d0000/status如果输出是disabled那 eth1 的内核设备压根不会被创建后面所有 driver error 都谈不上。这时候不需要查驱动直接改设备树。还有一个非常容易被忽略的点即使 status 是okay如果节点缺少 pinctrl 配置驱动 probe 时也会失败而且日志可能非常简略只有几句stm32-dwmac ... probe failed。2.2 内核配置里的stmmac与PHY驱动确认内核已经编译了 stmmac 平台驱动zcat /proc/config.gz | grep -E STMMAC|PHY_MOTORCOMM|PHY_REALTEK|PHY_MICREL在我的内核里输出大致是CONFIG_STMMAC_ETHy CONFIG_STMMAC_PLATFORMy CONFIG_PHY_MOTORCOMMy CONFIG_PHY_REALTEKy CONFIG_PHY_MICRELy为什么把 PHY 驱动单独列出来因为 dwmac 只能保证 MAC 正常工作PHY 芯片需要对应的驱动去读 ID、配置寄存器。如果板子上的 PHY 是裕太微 YT8531而内核里CONFIG_PHY_MOTORCOMM没开MDIO 总线上就扫不到 PHY最终报的错同样是no PHY found。ETH0 正常不代表这些配置没问题因为板子上 eth0 和 eth1 用的可能是不同厂商的 PHY。我遇到过一块板子eth0 是 Micrel PHYeth1 是 Realtek PHY内核只编了 Micrel 的驱动结果就是 eth0 一切正常eth1 报 no PHY found。这个问题不看原理图根本想不到。2.3 时钟/复位/PHY模式看起来像驱动问题的硬件配置STM32MP255F 的 GMAC1 有独立的时钟设备树里必须配好。通常是这样gmac1 { clocks rcc CK_ETH1CK_K, rcc CK_ETH1PTP_K; clock-names stmmaceth, ptp_ref; };如果clocks缺失或写错驱动初始化时钟时会失败dmesg 里会出现类似stm32-dwmac 482d0000.ethernet: Enable eth clock failed这种情况下 eth1 完全无法创建看起来非常像driver error但根因只是时钟树配置。PHY 复位也是重灾区。设备树里通常通过 GPIO 控制 PHY 的 reset 引脚mdio { phy1: ethernet-phy1 { reg 1; reset-gpios gpioi 3 GPIO_ACTIVE_LOW; reset-assert-us 10000; reset-deassert-us 10000; }; };注意reset-assert-us和reset-deassert-us的单位是微秒。很多 PHY 要求复位释放后等待至少 10ms 才能响应 MDIO 访问如果这里写的太小或者板子上的 RC 复位电路本身很慢PHY 也会探测不到。最后是phy-mode。STM32MP255F 设备树里常见rgmii、rgmii-id、rmii。rgmii-id表示 MAC 和 PHY 都负责各自的 delayrgmii表示两边都不加 delay需要外接或由另一侧负责。如果写错dmesg 不一定报错但 eth1 的 link 状态会异常有的表现为插线后一直Link is Down有的表现为能 link 但吞吐量只有几十 Mbps。这种问题最容易让人误解成驱动性能 bug。3. 从dmesg完整还原eth1 driver error的现场定位问题最有效的资料就是 dmesg。我建议每次启动后先完整抓一份不要只看出错那几行因为 stmmac 的日志是顺序输出的前面的 MAC 初始化日志能告诉我们 probe 走到了哪一步。3.1 一份正常probe日志长什么样eth0对照如果你的 eth0 正常它开机时的 probe 日志就是最好的对照样本。正常 STM32MP25 BSP 上dwmac 的日志大致是[ 6.321654] stm32-dwmac 482d0000.ethernet: IRQ eth_wake_irq not found [ 6.321678] stm32-dwmac 482d0000.ethernet: IRQ eth_lpi not found [ 6.321701] stm32-dwmac 482d0000.ethernet: User ID: 0x10, Synopsys ID: 0x52 [ 6.321720] stm32-dwmac 482d0000.ethernet: DWMAC1000 [ 6.321741] stm32-dwmac 482d0000.ethernet: DMA HW capability register supported [ 6.321880] stm32-dwmac 482d0000.ethernet: RX IPC Checksum Offload supported [ 6.321899] stm32-dwmac 482d0000.ethernet: Wake-Up On Magic Pkg supported [ 6.324947] stm32-dwmac 482d0000.ethernet: Enabled RGMII mode [ 6.325388] stm32-dwmac 482d0000.ethernet eth1: PHY [stmmac-1:01] driver [YT8531 Gigabit Ethernet] (irqPOLL) [ 6.326001] stm32-dwmac 482d0000.ethernet eth1: No Safety Features support found [ 6.326109] stm32-dwmac 482d0000.ethernet eth1: IEEE 1588-2008 Advanced Timestamp supported [ 6.326226] stm32-dwmac 482d0000.ethernet eth1: registered PTP clock其中IRQ eth_wake_irq not found和IRQ eth_lpi not found是正常的很多 ST 平台没有单独的 wake 中断和 LPI 中断驱动会提示一下然后继续。关键看两行Enabled RGMII mode说明 MAC 的接口模式设置成功。PHY [stmmac-1:01] driver [YT8531 Gigabit Ethernet]说明 MDIO 总线上成功枚举到了 PHY。如果缺了第二行就是 PHY 探测失败如果连Enabled RGMII mode都没有问题大概率在 MAC 初始化早期。3.2 三种典型报错的根因链路我整理了一下实际调试中遇到最多的三类报错以及它们的完整检查链路。第一类是no PHY found。dmesg 通常长这样stm32-dwmac 482d0000.ethernet eth1: no PHY found stm32-dwmac 482d0000.ethernet eth1: Cannot attach to PHY (error -19)根因链路是MDIO 总线上没有读到 PHY ID。这时候按这个顺序查查设备树里phy-handle指向的 PHY 节点是否存在reg地址是否和板子上 PHY 地址跳线一致。查 PHY 的电源和复位 GPIO用万用表量 PHY 芯片的供电和 reset 引脚电平。查 MDIO 的时钟引脚和数据引脚是否在 pinctrl 里配成了对应 AF。查内核有没有编译对应 PHY 厂商驱动。第二类是clk_prepare_enable failed。dmesg 类似stm32-dwmac 482d0000.ethernet: clk_prepare_enable failed: -2 stm32-dwmac 482d0000.ethernet: probe failed with error -2根因基本在设备树的clocks/clock-names。重点检查ETH1CK_K和ETH1PTP_K这两个时钟是否被其它节点独占、是否在 RCC 里被关闭。也可以在用户态用 clk 调试接口看ls /sys/kernel/debug/clk/ | grep ETH1 cat /sys/kernel/debug/clk/ck_eth1ck_k/clk_rate第三类是Link is Down但 PHY 已经识别。这种严格来说不是 driver error但很多人会当成驱动问题来搜。根因可能是phy-mode的 delay 配置和板子实际设计不符也可能是 RGMII 的 TX 时钟方向不对。排查时可以先用 ethtool 看 PHY 状态ethtool eth1如果输出里Link detected: no而 eth0 同样插线能起来那重点查硬件链路和phy-mode。3.3 用sysfs手动unbind/bind复现probe过程设备树和驱动的排查有一个很实用的技巧用 sysfs 手动触发重新 probe。这样可以不用反复重启快速验证修改设备树前/后的差异。先找到 eth1 对应的平台设备名。在 sysfs 里通常显示为设备树节点名比如482d0000.ethernetls /sys/bus/platform/drivers/stm32-dwmac/如果驱动名和这个不完全一样可以在/sys/bus/platform/devices/下找设备ls /sys/bus/platform/devices/ | grep ethernet然后手动 unbind 再 bindecho 482d0000.ethernet /sys/bus/platform/drivers/stm32-dwmac/unbind echo 482d0000.ethernet /sys/bus/platform/drivers/stm32-dwmac/bindbind 之后立刻dmesg | tail -50如果报错稳定复现说明是静态配置问题不是偶发硬件故障。如果 bind 后 eth1 成功出现那有可能是启动时 PHY 还没准备好才 probe 失败可以考虑在设备树里增加 PHY 复位延时或者让驱动支持 deferred probe。在这个环节我的经验是不要急着去改驱动代码。stmmac 驱动在 ST 的 BSP 里已经很成熟真正需要改代码的场景极少。绝大多数 eth1 driver error最终都会收敛到设备树某个字段。4. 实战修复把eth1从不存在掰回UP前几节的排查方法最终都要落到一个具体的修复动作。下面分享两个最典型的案例一个是 status 未使能另一个是 PHY 探测时序问题。这两个加起来差不多覆盖了我见过的七成 eth1 故障。4.1 设备树修正一个普通的status禁用案例有一种很常见的状态拿到手的 BSP 默认只启用了 eth0eth1 的节点在 dtsi 里存在但板级 dts 里没有把 status 改成 okay。这时候 eth1 在系统里完全不存在dmesg 里干干净净只有 eth0 的 probe 日志。修改方式是在板级设备树里追加gmac1 { status okay; pinctrl-names default, sleep; pinctrl-0 eth1_rgmii_pins; pinctrl-1 eth1_rgmii_sleep_pins; phy-mode rgmii-id; max-speed 1000; phy-handle phy1; mdio { #address-cells 1; #size-cells 0; phy1: ethernet-phy1 { reg 1; reset-gpios gpioi 3 GPIO_ACTIVE_LOW; reset-assert-us 20000; reset-deassert-us 20000; }; }; };编译设备树时如果用的是 ST 官方 SDK一般在内核源码目录下make stm32mp255f-dk.dtb也可以用 Yocto 的 devtool 流程devtool modify linux-stm32mp # 修改 dts 后 bitbake linux-stm32mp -c compile -f替换 dtb 后重启再看ifconfig -a。这一步成功的话eth1 就应该出现了。这里要特别提醒把 status 改成 okay 只是第一步。如果 pinctrl 或 phy-handle 不对驱动会从设备不存在变成probe errordmesg 会开始报错。看到报错别慌按第 3 节的日志顺序继续走。4.2 PHY探测时序与reset-GPIO问题修复另一个高发问题是 PHY 探测失败。有一次我把 eth1 的节点全配好了ifconfig -a也能看到 eth1但ip link set eth1 up之后一直 Link is Downdmesg 里反复出现stm32-dwmac 482d0000.ethernet eth1: no PHY found我第一个反应是 PHY 地址错了。用下面的命令查 MDIO 总线上实际挂的 PHYls /sys/bus/mdio_bus/devices/如果输出里只有stm32-0:01没有stm32-1:01说明 GMAC1 的 MDIO 总线没扫到 PHY。再用 devmem 或者示波器确认 PHY 的地址引脚发现板子上 PHY 地址是 0而设备树里写的reg 1。改过来之后PHY 能被枚举了但依然 Link is Down。后来我把reset-assert-us和reset-deassert-us从 10000 调到 50000问题才真正解决。原因是板子的 PHY 复位电路上有一个较大的 RC 延时复位释放后 MDIO 访问太快PHY 还没准备好。具体表现就是有时能起来有时起不来或者冷启动起不来热重启能起来。这个坑在 eth0 上很少遇到因为很多评估板的 eth0 PHY 是直连 SoC 的复位信号由 SoC 上电时序保证eth1 因为后期扩展复位 GPIO 常常被软件控制时序问题就暴露出来了。修复后的设备树片段phy1: ethernet-phy0 { reg 0; reset-gpios gpioi 3 GPIO_ACTIVE_LOW; reset-assert-us 50000; reset-deassert-us 50000; };改完后重新编译 dtb 启动dmesg 里出现PHY [stmmac-1:00]eth1 才算真正活过来。4.3 最终验证与MAC地址那些容易忽略的细节eth1 能 link 起来不等于任务完成。至少要做三层验证第一层确认接口基本状态ip link show eth1 ethtool eth1重点看Link detected: yes以及Speed: 1000Mb/s。第二层配地址并测连通性ip addr add 192.168.10.2/24 dev eth1 ip link set eth1 up ping -I eth1 192.168.10.1 -c 5第三层跑吞吐测试# 对端执行 iperf3 -s -B 192.168.10.1 # eth1 所在设备执行 iperf3 -c 192.168.10.1 -t 30 -i 1如果吞吐能达到 900 Mbps 以上基本说明 eth1 的驱动和硬件都正常。还有一个容易被误判成 driver error 的点MAC 地址。如果 eth1 的 MAC 地址是 00:00:00:00:00:00或者和 eth0 一模一样某些应用会直接报错。dmesg 里会出现stm32-dwmac 482d0000.ethernet eth1: invalid MAC address, using random这种情况不是驱动故障而是 bootloader 没有给 eth1 设置eth1addr。在 STM32MP25 的 u-boot 环境里需要确认ethaddr00:80:e1:12:34:56 eth1addr00:80:e1:12:34:57如果 env 里没有 eth1addr内核就会用随机 MAC虽然能上网但每次重启地址都变给后续开发带来很多麻烦。也可以在设备树节点里加固定 MACgmac1 { local-mac-address [00 80 E1 12 34 57]; };优先级上u-boot 写入的 MAC 通常优先于设备树中的 local-mac-address具体看 BSP 的 bootargs 和驱动实现。最稳妥的做法还是把两个地址都在 u-boot 里配置好。回到开头那个问题STM32MP255F 的 eth1 driver error 并不是一个具体的错误码而是一类症状。我现在的固定动作是先跑四条命令dmesg | grep -E stm32-dwmac|mdio|eth1 ip link show ls /sys/bus/mdio_bus/devices/ cat /proc/device-tree/aliases/ethernet1看完基本能判断是设备树、时钟还是 PHY 的问题。希望这篇踩坑记录能给正在和 eth1 搏斗的你省下几个小时。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进