问题简述
使用命令 udhcpc -i ethx 无法获取动态 IPv4 。
给当前网卡添加静态 IPv4(已确认该 IPv4 没有被占用),无法去 ping 通同一网段下的其它主机。
问题定位
更换 PHY 芯片
由于 T536 Demo 板是能正常通信的,它用的 PHY 芯片是 rtl8211 ,而我们自己的 T536 的 PHY 芯片是 yt8531H。尝试更换为 rtl8211 后,发现能正常通信。
这时就把问题定位到 PHY 芯片。
双网卡对测
不同板子对测
把我司的 T536 和原厂的 Demo 板对测(已确认 Demo 板的所以网卡都能正常通信)。
下面用板 A 代表我司的 T536 ,板 B 代表原厂的 Demo 板。
板 A 和板 B 的 eth0 连接彼此。
设置板 A 的 eth0 :
root@T536:~# ifconfig eth0 192.168.1.11
[ 212.664547] sunxi:sound-mach:[WARN]: 372 asoc_simple_parse_ucfmt(): set data late to default
[ 212.674095] sunxi:sound-mach:[ERR]: 488 simple_parse_of(): simple_dai_link_of failed
[ 212.822861] dwmac-sunxi 4500000.ethernet eth0: PHY [stmmac-0:01] driver [Generic PHY] (irq=POLL)
[ 212.843105] dwmac4: Master AXI performs fixed burst length
[ 212.849408] dwmac-sunxi 4500000.ethernet eth0: Enabling Safety Features
[ 212.867340] dwmac-sunxi 4500000.ethernet eth0: IEEE 1588-2008 Advanced Timestamp supported
[ 212.877403] dwmac-sunxi 4500000.ethernet eth0: configuring for phy/rgmii link mode
[ 215.957540] dwmac-sunxi 4500000.ethernet eth0: Link is Up - 1Gbps/Full - flow control off
[ 215.967218] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
设置板 B 的 eth0 :
root@T536:~# ifconfig eth0 192.168.1.22
[ 417.033317] dwmac-sunxi 4500000.ethernet eth0: PHY [stmmac-0:01] driver [RTL8211F Gigabit Ethernet] (irq=POLL)
[ 417.046276] dwmac4: Master AXI performs fixed burst length
[ 417.052574] dwmac-sunxi 4500000.ethernet eth0: Enabling Safety Features
[ 417.060348] dwmac-sunxi 4500000.ethernet eth0: IEEE 1588-2008 Advanced Timestamp supported
[ 417.071640] dwmac-sunxi 4500000.ethernet eth0: configuring for phy/rgmii link mode
[ 420.179643] dwmac-sunxi 4500000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
[ 420.189161] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
板 B PING 板 A ,在板 B 使用tcpdump -i eth0 去抓包:
在板 A 使用tcpdump -i eth0 去抓包:
通过对比可知,板 B 往板 A 发送数据,板 A 是能正常接收的。同时也发现板 A 发出 reply 包给板 B ,但这是 tcpdump 从软件驱动层面上捕获的数据包,我们并不清楚这个数据包是否传输给对端。看板 B ,它接收不到来自板 A 的 reply 包,而且先前已确认板 B 的 eth0 能正常通信,所以可确定板 A 的 eth0 的 TX 有问题。
为了再次定位问题,我重新给板 A 的 eth0 与交换机连接,使用 tcpdump -i eth0 去抓包:
发现是能正常接收的,结合以上总总原因和结果,确定 TX 通信有问题。
同一块板子
如果一块板子有两个及以上的网卡,可参考以下文章去对测:
双网口回环测试(亲自测试有效)_多网口回环测试-CSDN博客
检查 RX 和 TX 的波形
在我司的 T536 硬件原理图,看 TX 和 RX 的时钟:
使用示波器看它们两的时钟波形(当前网卡的模式是 100M FULL ):
RX:
TX:
发现 RX 的时钟频率为 25M ,是正常的。但是 TX 的时钟频率仅有 5M ,正常来说,TX 的时钟频率是 25M 。
所以从硬件上定位到问题,就是 TX 的时钟频率过低,导致根据 5M 时钟频率从 TX 发出的数据,对端 RX(时钟频率 25M )无法正常接收。
解决问题
查看 EPHY0-CLKOUT-125M
与裕太工程师沟通后,去检查 PHY 芯片的 Pin 35 引脚,即 EPHY0-CLKOUT-125M :
以下是它引出部分:
使用示波器检查该引脚发现时钟频率仅有 25M 。
再次与裕太工程师沟通后,得知需要检查 PHY 芯片的 ext 0xa012寄存器,以下是该寄存器的作用:
在终端输入以下命令:
root@T536:~# phytool write eth0/0/30 0xa012
root@T536:~# phytool eth0/0/31
ieee-phy: reg:0x1f val:0x00c8
可知现在 ext 0xa012寄存器的值为 0x00c8 ,现在的状态为:25M reference clk 、clk 输出 25M 、link down 时也允许 clk 输出和 enable clk 输出。
然后我尝试把 25M reference clk 改为 from PLL 125M ,clk 输出 25M 改为 clk 输出 125M 。
root@T536:~# phytool write eth0/0/30 0xa012
root@T536:~# phytool write eth0/0/31 0x00d0
再次查看:
root@T536:~# phytool write eth0/0/30 0xa012
root@T536:~# phytool eth0/0/31
ieee-phy: reg:0x1f val:0x00d0
使用示波器去看时钟波形,发现 PHY 芯片的 Pin 35 已输出 125M 。
同时,TX 和 RX 的时钟频率都是 25M 。然后使用 udhcpc -i ethx 去获取动态 IPv4 ,发现获取成功,说明现在能正常通信了。
核心板上的 PHY1 的操作步骤和以上的一致。
在终端操作 PHY 寄存器
以下是给 yt8531 设置 125M 时钟输出的脚本:
#!/bin/bash
ETH=$1
point_synce_reg() {
phytool write ${ETH}/0/30 0xa012
}
ifconfig ${ETH} up
point_synce_reg
echo "before (`phytool ${ETH}/0/31`)"
point_synce_reg
phytool write ${ETH}/0/31 0x00d0
point_synce_reg
echo "after (`phytool ${ETH}/0/31`)"
在 PHY 驱动操作寄存器
在通用 PHY 驱动内修改不方便,所以在裕太的 PHY 驱动内修改。
每次启动网卡时,会启动对应的 PHY 芯片,期间会调用 struct phy_driver 内定义的 .config_init(),来初始化 PHY 芯片。在裕太 PHY 驱动中,有对 yt8531 的 .config_init() ,即 yt8531_config_init() 。在该函数内添加以下代码,把 0x00d0 写入到 ext 0xa012 寄存器:
static int yt8531_config_init(struct phy_device *phydev)
{
int ret = 0, val = 0;
...
+ ret = ytphy_write_ext(phydev, 0xa012, 0x00d0);
+ if (ret < 0)
+ return ret;
ytphy_soft_reset(phydev);
return 0;
}