Zynq-7000 PetaLinux 千兆网卡 Link UP 但无法 Ping 通的终极排查与解决(以 KSZ9031 为例)

文章目录

  • [Zynq-7000 PetaLinux 千兆网卡 Link UP 但无法 Ping 通的终极排查与解决(以 KSZ9031 为例)](#Zynq-7000 PetaLinux 千兆网卡 Link UP 但无法 Ping 通的终极排查与解决(以 KSZ9031 为例))
    • [📌 问题背景与现象](#📌 问题背景与现象)
    • [🕵️‍♂️ 排查全过程(干货预警)](#🕵️‍♂️ 排查全过程(干货预警))
    • [🛠️ 终极解决方案(只需两步)](#🛠️ 终极解决方案(只需两步))
      • [步骤 1:在内核中开启特定 PHY 芯片驱动](#步骤 1:在内核中开启特定 PHY 芯片驱动)
      • [步骤 2:在设备树中开启 RGMII-ID 并微调皮秒级延迟(核心重点)](#步骤 2:在设备树中开启 RGMII-ID 并微调皮秒级延迟(核心重点))
      • [步骤 3:编译与验证](#步骤 3:编译与验证)
    • [💡 原理解析:为什么千兆必须要调 Skew?](#💡 原理解析:为什么千兆必须要调 Skew?)

📌 问题背景与现象

在进行 Zynq-7000 自制板卡的网络 Bring-up 时,遇到了一个嵌入式网络开发中最经典的"玄学"问题:

  1. 使用 PetaLinux 编译系统,从 NAND Flash(或 SD 卡)启动成功。
  2. 插入网线后,网口指示灯正常闪烁。
  3. 串口终端输入 ifconfig,网卡(eth0)已分配 IP,且显示 RUNNING
  4. 串口内核日志(dmesg)明确打印出:macb e000b000.ethernet eth0: link up (1000/Full)
  5. 致命现象:Zynq 无法 Ping 通直连的电脑,电脑也无法 Ping 通 Zynq,且 arp -a 查不到对方的 MAC 地址。

软硬件环境:

  • SoC: Xilinx Zynq-7000 (XC7Z020 / XC7Z010 等)
  • PHY 芯片: Micrel (Microchip) KSZ9031 千兆 PHY
  • 网络接口: RGMII
  • 操作系统: PetaLinux

🕵️‍♂️ 排查全过程(干货预警)

遇到"亮灯但 Ping 不通"的情况,切忌盲目怀疑硬件虚焊。这通常意味着 MDIO 管理接口正常(能读出 Link 状态),但 RGMII 数据通道异常(数据全是乱码被丢弃) 。按以下逻辑排查,可精准定位病根。

第一步:排除最低级的干扰(Windows 防火墙)

很多时候板子其实已经发出了请求,是电脑拒绝响应。
动作: 确保电脑端设置了同网段的固定 IP(如 192.168.0.1),并彻底关闭 Windows Defender 防火墙(专用网络与公用网络均关闭)。同时建议暂时禁用电脑的 Wi-Fi 避免路由冲突。

第二步:分析 Dmesg,揪出 "Generic PHY" 隐患

在 PetaLinux 终端输入:

bash 复制代码
dmesg | grep -i phy

如果你的输出包含类似以下内容:

Generic PHY e000b000.etherne:03: attached PHY driver [Generic PHY]

⚠️ 结论:这就是导致千兆 Ping 不通的罪魁祸首之一!
Generic PHY(通用驱动)只包含了 IEEE 基础寄存器控制,它能完成自协商(所以能 Link UP),但它不知道如何配置特定厂家的私有寄存器来开启 RGMII 的内部时钟延迟(Delay) 。千兆速率下不加延迟,采样必然全错。

第三步:网络降速测试(定位时序问题的试金石)

千兆(1000M)对 RGMII 时钟(125MHz)的延迟要求极度苛刻,而百兆(100M,时钟 25MHz)容错率极高。

我们在 Windows 电脑的"网络适配器 -> 属性 -> 配置 -> 高级"中,将"速度和双工"强制改为 100 Mbps 全双工 。(或在 Linux 端用 ethtool -s eth0 speed 100 duplex full autoneg off)。

等板子端提示 link up (100/Full) 后,再次 Ping 测试。
🎯 关键结论:如果百兆能 Ping 通,千兆 Ping 不通,100% 证明底层硬件链路和网线没问题,绝对是 PHY 芯片的千兆 RGMII 时钟延迟(Clock Skew)配置错误!


🛠️ 终极解决方案(只需两步)

针对上述排查结果,我们需要在 PetaLinux 中启用专属驱动,并在设备树中精准微调 KSZ9031 的时钟延迟。

步骤 1:在内核中开启特定 PHY 芯片驱动

在 PetaLinux 工程根目录下运行:

bash 复制代码
petalinux-config -c kernel

依次进入:
Device Drivers -> Network device support -> PHY Device support and infrastructure

找到 Micrel PHYs (或者你实际使用的 Marvell / Realtek),按空格键选中使其前面变成 [*]。保存并退出。

步骤 2:在设备树中开启 RGMII-ID 并微调皮秒级延迟(核心重点)

打开用户设备树文件:
project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi

将以太网节点(通常是 &gem0&macb0)修改为如下配置。
注意:KSZ9031 这颗芯片对 PCB 走线极度敏感,除了设置 phy-mode = "rgmii-id" 外,通常必须加入下方的 skew-ps 参数来强行微调发送/接收时钟的皮秒延迟。

devicetree 复制代码
/include/ "system-conf.dtsi"
/ {
};

&gem0 {
    status = "okay";
    
    /* 【核心1】强制开启 RGMII 内部双向延迟 */
    phy-mode = "rgmii-id"; 
    
    phy-handle = <&ethernet_phy>;

    mdio {
        #address-cells = <1>;
        #size-cells = <0>;
        
        /* 注意这里的 @3 需要与你实际硬件的 PHY 地址一致 */
        ethernet_phy: ethernet-phy@3 {
            reg = <0x3>;
            device_type = "ethernet-phy";
            
            /* 【核心2】KSZ9031 千兆时序微调专属参数 */
            /* 将数据和控制信号的延迟归零 */
            txen-skew-ps = <0>;
            rxdv-skew-ps = <0>;
            rxd0-skew-ps = <0>;
            rxd1-skew-ps = <0>;
            rxd2-skew-ps = <0>;
            rxd3-skew-ps = <0>;
            txd0-skew-ps = <0>;
            txd1-skew-ps = <0>;
            txd2-skew-ps = <0>;
            txd3-skew-ps = <0>;
            
            /* 将发送(txc)和接收(rxc)时钟的延迟强行设为 3000 皮秒 (3ns) */
            /* 确保时钟采样沿完美落在数据眼图的正中心 */
            txc-skew-ps = <3000>;
            rxc-skew-ps = <3000>;
        };
    };
};

步骤 3:编译与验证

保存设备树后,重新编译系统:

bash 复制代码
petalinux-build

将生成的 BOOT.BINimage.ub 烧录进开发板。

系统重启后,输入 dmesg | grep phy,确认驱动已变为 [Micrel KSZ9031 Gigabit PHY]

插上网线,执行 ping 192.168.0.1,享受丝滑的千兆网络吧!


💡 原理解析:为什么千兆必须要调 Skew?

在 RGMII 接口中,MAC 和 PHY 之间的数据线和时钟线是同步发出的(即边沿对齐)。

但在接收端要正确采样数据,时钟的跳变沿必须对准数据的正中心。这就要求我们必须在 PHY 芯片内部人为给时钟线加一个大约 2ns 的延迟。

  • phy-mode = "rgmii":不加任何延迟。
  • phy-mode = "rgmii-id":PHY 芯片内部自动给 TX 和 RX 加固定延迟(比如默认 2.0ns)。

由于不同自制板卡的 PCB 走线长度不同,默认的 2.0ns 可能不够。而 Micrel KSZ9031 的 Linux 驱动支持通过设备树读取 txc-skew-ps = <3000> 等参数,直接写入其底层内部寄存器,从而实现皮秒级的完美时序对齐。这就是为什么上面的几行代码能起到起死回生作用的根本原因。

相关推荐
Joker 0073 小时前
Ubuntu上安装FreeSurfer的详细流程
linux·深度学习·ubuntu
想你依然心痛3 小时前
从零开始:Mac/Windows/Linux 三系统开发环境配置完全指南
linux·windows·macos
weixin_450907283 小时前
[ZYNQ Linux] V4L2视频驱动
zynq
陳10303 小时前
Linux:第一个系统程序--进度条
linux·运维·服务器
克莱因3583 小时前
Linux 进程(2)服务管理指令
java·linux·服务器
不怕犯错,就怕不做4 小时前
Linux中的IS_ENABLED 函数实战使用demo
linux·驱动开发·嵌入式硬件
源远流长jerry4 小时前
软件定义网络 SDN 核心技术深度解析:从概念到实践
linux·网络·架构
橙露4 小时前
Linux 服务器性能排查:CPU / 内存 / 磁盘 / 网络一键定位
linux·服务器·网络
暴力求解4 小时前
Linux---命名管道与共享内存(一)
linux·运维·服务器