markdown复制## 1. 项目背景与核心挑战
最近在给一块定制开发板做Linux内核移植时,发现原厂提供的BSP包里的网络驱动无法在Ubuntu 20.04上正常工作。板子用的是Realtek 8211E千兆PHY芯片,但内核自带的r8169驱动频繁出现丢包和链路异常。这种情况在嵌入式开发中很常见——当硬件设计或外围电路与原厂参考设计有差异时,往往需要手动调整驱动参数。
网络驱动移植的特殊性在于:
1. 涉及MAC控制器、PHY芯片、MDIO总线三层交互
2. 需要同步考虑uboot环境变量、设备树配置、内核驱动三个层面
3. 不同Linux发行版的内核配置可能存在差异
## 2. 驱动移植前的准备工作
### 2.1 硬件环境确认
首先用示波器抓取了开发板的网络接口信号:
- MDC/MDIO时钟频率实测为2.5MHz(标准值)
- RX/TX差分对阻抗控制在100Ω±10%
- 发现复位信号时序与PHY手册要求有200ns偏差
### 2.2 软件环境搭建
在Ubuntu 20.04上需要特别注意:
```bash
# 安装必备工具链
sudo apt install build-essential libncurses-dev bison flex libssl-dev
# 获取官方内核源码(与当前发行版一致)
apt source linux-image-$(uname -r)
重要提示:Ubuntu 20.04默认使用5.4内核,但官方仓库的源码可能不包含某些驱动补丁,建议直接从kernel.org下载相同版本源码。
通过dmesg发现以下关键错误:
code复制r8169 0000:01:00.0: eth0: link up (1000Mbps/Full)
r8169 0000:01:00.0: eth0: rx unit 0xf0000b80
r8169 0000:01:00.0: eth0: tx timeout
解决方法是在驱动中增加PHY复位延时:
c复制// 修改drivers/net/ethernet/realtek/r8169_main.c
static void rtl8169_init_phy(struct rtl8169_private *tp)
{
// 增加复位保持时间
mdelay(50); // 原为20ms
phy_reset(tp->phydev);
}
在arch/arm/boot/dts/中添加PHY属性:
dts复制&mac {
phy-mode = "rgmii";
phy-handle = <&phy0>;
phy-reset-gpios = <&gpio2 15 GPIO_ACTIVE_LOW>;
phy-reset-duration = <50>; // 单位ms
};
&mdio {
phy0: ethernet-phy@0 {
compatible = "ethernet-phy-id001c.c915";
reg = <0>;
reset-gpios = <&gpio2 15 GPIO_ACTIVE_LOW>;
reset-assert-us = <50000>; // 50ms
};
};
现象:网络时断时续,ifconfig显示RX包计数不增长
在/etc/sysctl.conf中添加:
conf复制# 增大TCP窗口大小
net.core.rmem_max = 4194304
net.core.wmem_max = 4194304
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 16384 4194304
# 关闭IPv6减少中断开销
net.ipv6.conf.all.disable_ipv6 = 1
建立自动化测试脚本:
bash复制#!/bin/bash
# 持续ping测试
ping -c 1000 192.168.1.1 | tee ping.log
# 带宽测试
iperf3 -c 192.168.1.1 -t 60 -i 10
# 中断负载监控
watch -n 1 'cat /proc/interrupts | grep eth0'
关键指标要求:
在实际移植中发现了几个容易忽略的细节:
对于需要深度定制的场景,可以考虑:
code复制