1. 项目背景与核心挑战
最近在调试一块基于Rockchip RK3568的开发板时,遇到了一个典型问题:官方SDK提供的U-Boot默认配置无法正常驱动板载千兆网卡。作为嵌入式开发的老兵,我决定记录下整个调试过程,分享给同样在Rockchip平台上挣扎的同行们。
这个问题的特殊性在于,Rockchip的SoC通常采用独特的PHY配置方式,与常规的U-Boot网络驱动存在差异。官方SDK虽然提供了基础支持,但针对具体硬件设计往往需要手动调整。我的开发板采用裕太微电子的YT8531C千兆PHY芯片,需要通过RGMII接口与SoC连接,这种组合在社区中的现成解决方案并不多见。
2. 环境准备与基础验证
2.1 硬件环境确认
首先需要明确硬件连接方式,这对后续驱动配置至关重要。通过查阅原理图确认以下关键信息:
- PHY芯片型号:YT8531C
- 接口类型:RGMII
- PHY地址:0x00(通过硬件引脚配置)
- 参考时钟:125MHz由SoC提供
- 复位信号:GPIO0_B5控制
重要提示:Rockchip平台的网络调试必须确认时钟配置。RGMII需要125MHz时钟,如果硬件设计使用PHY提供时钟,则需在驱动中特别声明。
2.2 SDK基础环境搭建
使用Rockchip官方提供的SDK版本:
code复制SDK版本:rk356x_linux_release_20211020
U-Boot版本:v2017.09
编译环境配置:
bash复制sudo apt install gcc-arm-linux-gnueabihf
export CROSS_COMPILE=arm-linux-gnueabihf-
make rk3568_defconfig
3. 关键驱动配置解析
3.1 DTS设备树配置
网络驱动的核心在于正确的设备树配置。需要修改arch/arm/dts/rk3568-evb.dtsi中的相关节点:
dts复制&gmac0 {
phy-mode = "rgmii";
clock_in_out = "output";
snps,reset-gpio = <&gpio0 RK_PB5 GPIO_ACTIVE_LOW>;
snps,reset-active-low;
snps,reset-delays-us = <0 10000 50000>;
assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>;
assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>;
assigned-clock-rates = <0>, <125000000>;
pinctrl-names = "default";
pinctrl-0 = <&gmac0_miim>, <&gmac0_tx_bus2>, <&gmac0_rx_bus2>,
<&gmac0_rgmii_clk>, <&gmac0_rgmii_bus>;
phy-handle = <&rgmii_phy0>;
status = "okay";
};
&mdio0 {
rgmii_phy0: phy@0 {
compatible = "ethernet-phy-id0100.0c10";
reg = <0x0>;
phy-mode = "rgmii";
};
};
关键参数说明:
clock_in_out:配置时钟方向,开发板由SoC提供时钟故设为outputreset-gpio:必须与硬件原理图的复位引脚一致assigned-clock-rates:RGMII需要明确的125MHz时钟配置
3.2 PHY驱动适配
YT8531C需要特殊的初始化序列,在drivers/net/phy/phy.c中添加:
c复制static int yt8531c_config_init(struct phy_device *phydev)
{
int val;
/* 硬件复位后等待稳定 */
mdelay(100);
/* 配置RGMII时序 */
phy_write(phydev, MDIO_DEVAD_NONE, 0xa003, 0x1b00);
phy_write(phydev, MDIO_DEVAD_NONE, 0xa006, 0x7200);
/* 使能RGMII延迟 */
val = phy_read(phydev, MDIO_DEVAD_NONE, 0xa001);
val |= 0x1800;
phy_write(phydev, MDIO_DEVAD_NONE, 0xa001, val);
return 0;
}
static struct phy_driver YT8531C_driver = {
.name = "YT8531C",
.uid = 0x01000c10,
.mask = 0xfffffff0,
.features = PHY_GBIT_FEATURES,
.config_init = &yt8531c_config_init,
.config_aneg = &genphy_config_aneg,
.read_status = &genphy_read_status,
.suspend = genphy_suspend,
.resume = genphy_resume,
};
在phy_device.c的phy_drivers数组中注册该驱动:
c复制int phy_driver_register(struct phy_driver *drv, ...)
{
...
phy_drivers[count++] = &YT8531C_driver;
...
}
4. 编译与烧录实战
4.1 编译配置调整
执行make menuconfig确保以下选项开启:
code复制Device Drivers --->
[*] Network device support --->
[*] Ethernet PHY (physical media interface) support
[*] Support for Vitesse PHYs
[*] Support for ICPlus PHYs
4.2 编译与烧录
bash复制make -j8
./tools/mkimage -n rk3568 -T rksd -d tpl/u-boot-tpl.bin idbloader.img
cat spl/u-boot-spl.bin >> idbloader.img
sudo dd if=idbloader.img of=/dev/sdX seek=64 conv=notrunc
sudo dd if=u-boot.itb of=/dev/sdX seek=16384 conv=notrunc
5. 调试与问题排查
5.1 常见问题速查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| PHY无法识别 | 1. MDIO总线未初始化 2. PHY地址错误 |
1. 检查DTS的mdio节点 2. 用示波器测量MDIO波形 |
| 连接不稳定 | 1. 时钟配置错误 2. RGMII时序不匹配 |
1. 确认assigned-clock-rates 2. 调整PHY的RGMII延迟参数 |
| 无法DHCP | 1. 网络初始化未完成 2. 环境变量错误 |
1. 检查autoneg状态 2. 设置正确的bootargs |
5.2 关键调试命令
在U-Boot命令行中验证网络:
code复制=> mii info # 查看PHY寄存器
=> mii dump 0 0 # 读取PHY ID
=> ping 8.8.8.8 # 测试网络连通性
=> setenv ipaddr 192.168.1.100
=> setenv serverip 192.168.1.1
=> tftp 0x08000000 uImage # 测试TFTP传输
6. 性能优化技巧
6.1 RGMII时序校准
通过PHY寄存器优化信号质量:
code复制# 读取当前时序配置
=> mii read 0x0 0xa001
# 调整RX/TX延迟(单位0.1ns)
=> mii write 0x0 0xa001 0x18FF
6.2 网络启动加速
在include/configs/rk3568.h中添加预配置:
c复制#define CONFIG_BOOTCOMMAND \
"mmc dev 0; " \
"dhcp; " \
"tftp 0x08000000 uImage; " \
"bootm 0x08000000"
7. 经验总结
经过三天调试,最终实现的网络性能:
- TFTP传输速率:58MB/s(千兆满速)
- Ping延迟:<1ms(局域网内)
几个关键教训:
- Rockchip的时钟树配置必须精确匹配硬件设计,差1MHz都会导致RGMII失步
- YT8531C的复位时序要求严格,至少保持10ms低电平
- U-Boot 2017.09版本对RGMII支持较好,不建议随意升级版本
这个配置方案已稳定运行在批量生产的工业设备上,特别适合需要网络引导的嵌入式场景。对于其他PHY芯片(如RTL8211F),只需调整DTS中的compatible字段即可适配。