如果你是因为 STM32MP255F 的 eth1 driver error 搜到这里,那我们先对个暗号:eth0 千兆好好的,eth1 要么在ifconfig -a里根本不出现,要么每个包都丢得一塌糊涂,内核日志里翻来覆去就是 stmmac 那几行。这块芯片是 STM32MP25 家族里的新面孔,自带两路千兆 GMAC,照理说驱动和 MP1 时代一样成熟,但恰恰因为多了第二路网口,BSP 里默认给 eth1 的配置并不总是完整的。这篇文章不谈手册复读,只记录我在这类板子上从"看到 driver error"到"把 eth1 跑满千兆"的完整排查思路。适合正在调 STM32MP25 BSP、或者被其它 SoC 双网口驱动问题折磨的嵌入式工程师。
1. 为什么偏偏是eth1:STM32MP255F的双网口资源布局
很多人在 eth1 上报错后,第一反应是去翻 stmmac 驱动源码,这是最浪费时间的一条路。因为 eth0 能正常起来,说明驱动本身在你的内核里是能工作的,eth1 的问题几乎都集中在实例化这一层:设备树节点、引脚复用、时钟、PHY 复位。
1.1 从芯片资源看GMAC0与GMAC1的差异
STM32MP255F 内部集成了两个独立的千兆 MAC,我习惯把它们叫 GMAC0 和 GMAC1,对应 Linux 里的 eth0 和 eth1。两个 MAC 的 IP 核本身是同一个,都支持 RGMII/RMII,但它们在 SoC 里的资源并不完全对等。
用一张表可以看得很清楚:
| 对比项 | GMAC0(通常为 eth0) | GMAC1(通常为 eth1) |
|---|---|---|
| 典型接口 | RGMII / RMII | RGMII / RMII |
| 常见外接 PHY | 板载千兆 PHY | 第二路 PHY 或交换芯片 |
| 时钟输入 | ETH0CK_K、ETH0PTP_K | ETH1CK_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里没有 eth1,dmesg 里也没有任何 stm32-dwmac probe eth1 的记录 | 设备树或驱动 probe 之前失败 | 检查节点 status、pinctrl、时钟 |
dmesg 里有 stmmac MAC 初始化日志,但随后报no PHY found或Cannot attach to PHY | PHY 探测阶段 | 检查 PHY 地址、复位、MDIO 引脚、PHY 驱动 |
eth1 存在,ip link show显示 DOWN,插上网线也不变 UP | PHY 已经识别,但 link 建立失败 | 检查 phy-mode、时钟方向、网口变压器/线缆 |
| eth1 显示 UP,但 ping 不通或吞吐极低 | 链路已通,数据通路异常 | 检查 RGMII delay 配置、时钟频率、MAC 地址冲突 |
这个分类非常关键。我见过有人在no PHY found阶段跑去改 stmmac 的 DMA ring buffer 大小,折腾两天毫无意义。先定位到"卡在哪一步",再去动设备树或驱动,效率完全不同。
2. 排查前必须确认的三件事:设备树、内核配置与时钟供给
在把 dmesg 从头翻到尾之前,建议先做三个基础确认。这三个地方任何一个有问题,都会让 eth1 以一种非常类似"驱动 error"的形式表现,但实际都不是驱动代码问题。
2.1 设备树节点与aliases:eth1到底被系统认了没有
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*"找到类似ethernet@482d0000的目录后,查看它的 status:
cat /proc/device-tree/soc/ethernet@482d0000/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_ETH=y CONFIG_STMMAC_PLATFORM=y CONFIG_PHY_MOTORCOMM=y CONFIG_PHY_REALTEK=y CONFIG_PHY_MICREL=y为什么把 PHY 驱动单独列出来?因为 dwmac 只能保证 MAC 正常工作,PHY 芯片需要对应的驱动去读 ID、配置寄存器。如果板子上的 PHY 是裕太微 YT8531,而内核里CONFIG_PHY_MOTORCOMM没开,MDIO 总线上就扫不到 PHY,最终报的错同样是no PHY found。
ETH0 正常不代表这些配置没问题,因为板子上 eth0 和 eth1 用的可能是不同厂商的 PHY。我遇到过一块板子,eth0 是 Micrel PHY,eth1 是 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-phy@1 { 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 都负责各自的 delay,rgmii表示两边都不加 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] (irq=POLL) [ 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.ethernet:
ls /sys/bus/platform/drivers/stm32-dwmac/如果驱动名和这个不完全一样,可以在/sys/bus/platform/devices/下找设备:
ls /sys/bus/platform/devices/ | grep ethernet然后手动 unbind 再 bind:
echo "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 默认只启用了 eth0,eth1 的节点在 dtsi 里存在,但板级 dts 里没有把 status 改成 okay。这时候 eth1 在系统里完全不存在,dmesg 里干干净净,只有 eth0 的 probe 日志。
修改方式是在板级设备树里追加:
&gmac1 { status = "okay"; pinctrl-names = "default", "sleep"; pinctrl-0 = <ð1_rgmii_pins>; pinctrl-1 = <ð1_rgmii_sleep_pins>; phy-mode = "rgmii-id"; max-speed = <1000>; phy-handle = <&phy1>; mdio { #address-cells = <1>; #size-cells = <0>; phy1: ethernet-phy@1 { 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 error",dmesg 会开始报错。看到报错别慌,按第 3 节的日志顺序继续走。
4.2 PHY探测时序与reset-GPIO问题修复
另一个高发问题是 PHY 探测失败。有一次我把 eth1 的节点全配好了,ifconfig -a也能看到 eth1,但ip link set eth1 up之后一直 Link is Down,dmesg 里反复出现:
stm32-dwmac 482d0000.ethernet eth1: no PHY found我第一个反应是 PHY 地址错了。用下面的命令查 MDIO 总线上实际挂的 PHY:
ls /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-phy@0 { 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 环境里,需要确认:
ethaddr=00:80:e1:12:34:56 eth1addr=00:80:e1:12:34:57如果 env 里没有 eth1addr,内核就会用随机 MAC,虽然能上网,但每次重启地址都变,给后续开发带来很多麻烦。也可以在设备树节点里加固定 MAC:
&gmac1 { 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 搏斗的你省下几个小时。