1. 项目概述
在嵌入式Linux开发中,网络功能的重要性不言而喻。正点原子IMX6ULL开发板搭载双网口设计,为开发者提供了灵活的网络连接方案。本教程将详细讲解如何在Linux 7.0内核环境下,为IMX6ULL开发板配置双网口功能,涉及FEC控制器和KSZ8081/8041 PHY芯片的完整移植过程。
作为嵌入式开发者,我们经常需要同时连接多个网络:一个用于调试和开发,另一个用于实际应用。IMX6ULL的双FEC控制器设计正好满足这一需求。通过本教程,你将掌握从设备树配置到驱动调试的完整流程,让你的开发板具备稳定的双网口功能。
2. 硬件架构解析
2.1 i.MX6ULL网络子系统架构
i.MX6ULL处理器内置两个独立的FEC(Fast Ethernet Controller)控制器,每个控制器通过RMII接口连接外部PHY芯片。正点原子开发板选用的是Micrel(现Microchip)的KSZ8081 PHY芯片,这是一款低功耗、高性能的10/100M以太网PHY。
FEC控制器的主要特点包括:
- 支持10/100Mbps速率
- 支持RMII和MII接口(本设计使用RMII)
- 内置DMA引擎,减轻CPU负担
- 支持硬件CRC校验和帧校验
2.2 RMII接口详解
RMII(Reduced Media Independent Interface)相比传统MII接口,引脚数量从16根减少到7根,更适合嵌入式应用。RMII接口包含以下关键信号:
- TXD[1:0]:发送数据线(2位)
- RXD[1:0]:接收数据线(2位)
- TX_EN:发送使能
- CRS_DV:载波侦听/数据有效(合并了MII中的CRS和RX_DV)
- REF_CLK:50MHz参考时钟(由PHY提供)
在硬件设计上,REF_CLK信号的稳定性至关重要。KSZ8081内置时钟发生器,可以提供稳定的50MHz时钟信号给FEC控制器。
3. 设备树配置详解
3.1 FEC1控制器配置
FEC1的设备树节点配置是双网口移植的基础。以下是完整的配置示例:
c复制&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1 &pinctrl_enet1_reset>;
phy-mode = "rmii";
phy-handle = <ðphy0>;
phy-supply = <®_peri_3v3>;
status = "okay";
};
关键参数说明:
phy-mode:必须设置为"rmii"以匹配硬件设计phy-handle:指向MDIO总线下的PHY设备节点phy-supply:指定PHY芯片的电源(3.3V)status:必须设为"okay"使能控制器
3.2 FEC2控制器及MDIO总线配置
FEC2的配置与FEC1类似,但通常将MDIO总线挂在FEC2下:
c复制&fec2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet2 &pinctrl_enet2_reset>;
phy-mode = "rmii";
phy-handle = <ðphy1>;
phy-supply = <®_peri_3v3>;
status = "okay";
mdio {
#address-cells = <1>;
#size-cells = <0>;
ethphy0: ethernet-phy@2 {
compatible = "ethernet-phy-id0022.1560";
reg = <2>;
micrel,led-mode = <1>;
clocks = <&clks IMX6UL_CLK_ENET_REF>;
clock-names = "rmii-ref";
};
ethphy1: ethernet-phy@1 {
compatible = "ethernet-phy-id0022.1560";
reg = <1>;
micrel,led-mode = <1>;
clocks = <&clks IMX6UL_CLK_ENET2_REF>;
clock-names = "rmii-ref";
};
};
};
MDIO总线配置要点:
#address-cells和#size-cells:标准MDIO总线属性- PHY节点地址(reg属性)必须与硬件设计一致
micrel,led-mode:配置PHY芯片LED指示灯行为
3.3 引脚控制(pinctrl)配置
正确的引脚配置是网络功能正常工作的前提。以下是FEC1和FEC2的pinctrl配置示例:
c复制&iomuxc {
pinctrl_enet1: enet1grp {
fsl,pins = <
MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0
MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0
MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0
MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b031
>;
};
pinctrl_enet2: enet2grp {
fsl,pins = <
MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0
MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0
MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0
MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0
MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0
MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0
MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0
MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0
MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0
MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b031
>;
};
};
特别注意REF_CLK引脚的配置值0x4001b031,其中0x40000000表示该引脚配置为输入模式,接收来自PHY的50MHz时钟信号。
4. PHY芯片配置与调试
4.1 KSZ8081 PHY特性
KSZ8081是Microchip公司的一款高性能以太网PHY芯片,主要特性包括:
- 支持10/100Mbps自适应
- 低功耗设计(典型功耗120mW)
- 支持RMII接口
- 内置1.8V/2.5V/3.3V稳压器
- 工业级温度范围(-40°C至+85°C)
在设备树中,我们通过以下配置启用KSZ8081的特定功能:
c复制ethphy0: ethernet-phy@2 {
compatible = "ethernet-phy-id0022.1560";
reg = <2>;
micrel,led-mode = <1>;
clocks = <&clks IMX6UL_CLK_ENET_REF>;
clock-names = "rmii-ref";
};
其中:
ethernet-phy-id0022.1560:0022是Microchip的OUI,1560是KSZ8081的型号标识micrel,led-mode = <1>:配置LED0指示链接状态,LED1指示活动状态
4.2 PHY复位电路配置
PHY芯片通常需要通过复位引脚进行初始化。正点原子开发板使用GPIO控制PHY复位,有两种配置方式:
方法一:使用GPIO hog(静态配置)
c复制&gpio5 {
eth0-phy-reset {
gpio-hog;
gpios = <7 GPIO_ACTIVE_LOW>;
output-high;
line-name = "eth0-phy-reset";
};
eth1-phy-reset {
gpio-hog;
gpios = <8 GPIO_ACTIVE_LOW>;
output-high;
line-name = "eth1-phy-reset";
};
};
方法二:使用phy-reset-gpios(动态控制)
c复制&fec1 {
phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
phy-reset-duration = <26>; /* 复位持续时间(ms) */
phy-reset-post-delay = <100>; /* 复位后延迟(ms) */
};
实际项目中,方法二更为灵活,但需要确认内核版本是否支持相关属性。
5. 电源管理配置
5.1 PHY电源设计
KSZ8081需要稳定的3.3V电源。在设备树中,我们通过regulator节点配置PHY电源:
c复制/ {
reg_peri_3v3: regulator-peri-3v3 {
compatible = "regulator-fixed";
regulator-name = "VPERI_3V3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-always-on;
};
};
关键参数:
regulator-always-on:确保PHY电源不会被意外关闭enable-active-high:GPIO高电平使能电源- 建议在硬件设计上增加适当的去耦电容(如100nF+10μF)
6. 驱动加载与调试
6.1 内核配置要求
确保内核已正确配置FEC和PHY驱动:
bash复制# FEC控制器驱动
CONFIG_FEC=y
CONFIG_FEC_MXC=y
# PHY驱动
CONFIG_MICREL_PHY=y
可以通过以下命令验证驱动是否加载:
bash复制dmesg | grep -E "fec|phy|Micrel"
预期输出应包含类似以下内容:
code复制fec 2188000.ethernet: registered PHY driver [Micrel KSZ8081]
fec 2188000.ethernet eth0: Link is Up - 100Mbps/Full
6.2 网络接口验证
使用以下命令检查网络接口状态:
bash复制ip link show
ethtool eth0
ethtool eth1
重点关注以下信息:
- 链接状态(Link detected)
- 当前速率(Speed)
- 双工模式(Duplex)
- 自动协商状态(Auto-negotiation)
6.3 常见问题排查
问题1:网络接口未出现
可能原因:
- 设备树status未设为"okay"
- 内核未编译FEC或PHY驱动
- 硬件连接问题(检查电源、时钟、复位)
问题2:链接状态不稳定
排查步骤:
- 检查网线质量
- 测量REF_CLK信号质量(应为50MHz方波)
- 检查PHY供电电压(3.3V±5%)
- 尝试固定速率和双工模式:
bash复制ethtool -s eth0 speed 100 duplex full autoneg off
问题3:一个网口无法工作
检查要点:
- PHY地址配置是否正确(ethphy0@2, ethphy1@1)
- MDIO总线是否正常工作
- 两个PHY的复位信号是否独立控制
7. 性能优化技巧
7.1 中断亲和性设置
对于双网口应用,合理分配中断可以提升性能:
bash复制# 查看中断分配
cat /proc/interrupts | grep fec
# 设置eth0中断到CPU0
echo 1 > /proc/irq/[eth0-irq-num]/smp_affinity
# 设置eth1中断到CPU1
echo 2 > /proc/irq/[eth1-irq-num]/smp_affinity
7.2 DMA缓冲区优化
调整FEC的DMA缓冲区大小可以改善吞吐量:
c复制&fec1 {
/* 增加RX/TX环形缓冲区大小 */
rx-fifo-depth = <2048>;
tx-fifo-depth = <2048>;
};
7.3 网络协议栈调优
调整内核网络参数提升性能:
bash复制# 增加socket缓冲区大小
sysctl -w net.core.rmem_max=4194304
sysctl -w net.core.wmem_max=4194304
# 启用TCP窗口缩放
sysctl -w net.ipv4.tcp_window_scaling=1
8. 高级调试技巧
8.1 PHY寄存器访问
通过sysfs直接读写PHY寄存器:
bash复制# 查看PHY ID(前两个寄存器)
cat /sys/bus/mdio_bus/devices/2188000.ethernet:02/phy_id
# 读写特定寄存器(需要root权限)
# 读取寄存器0x01
mdio-tool -r eth0 0x01
# 写入寄存器0x0A值为0x0100
mdio-tool -w eth0 0x0A 0x0100
8.2 硬件信号测量
关键信号测量点:
- REF_CLK(PHY输出):50MHz方波,幅值3.3V
- 复位信号:上电后应为高电平(3.3V)
- 电源电压:3.3V±5%
- RMII数据线:活动时应有脉冲信号
8.3 内核跟踪调试
启用FEC驱动调试信息:
bash复制# 启用动态调试
echo "file drivers/net/ethernet/freescale/fec_main.c +p" > /sys/kernel/debug/dynamic_debug/control
echo "file drivers/net/phy/micrel.c +p" > /sys/kernel/debug/dynamic_debug/control
# 查看详细调试信息
dmesg -w
9. 实际应用场景
9.1 双网络隔离应用
典型应用场景:
- eth0:连接内部调试网络(SSH、NFS)
- eth1:连接外部应用网络(业务数据)
配置示例:
bash复制# eth0静态IP配置
ifconfig eth0 192.168.1.100 netmask 255.255.255.0 up
# eth2 DHCP获取IP
dhclient eth1
9.2 网络冗余设计
通过bonding实现网络冗余:
bash复制# 加载bonding模块
modprobe bonding mode=active-backup
# 创建bond接口
ip link add bond0 type bond
ip link set eth0 master bond0
ip link set eth1 master bond0
# 激活bond接口
ifconfig bond0 up
9.3 防火墙策略配置
针对双网口的安全策略:
bash复制# 允许eth0的SSH访问
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
# 禁止eth1的所有入站连接
iptables -A INPUT -i eth1 -j DROP
# 允许eth1的出站连接
iptables -A OUTPUT -o eth1 -j ACCEPT
10. 移植经验总结
在IMX6ULL上成功移植双网口功能后,我总结了以下几点关键经验:
-
设备树配置是关键:90%的网络问题源于不正确的设备树配置,特别是pinctrl和时钟设置。
-
PHY复位时序很重要:确保复位脉冲宽度足够(至少10ms),复位后等待足够时间(建议100ms)再进行MDIO访问。
-
时钟信号质量决定稳定性:使用示波器检查REF_CLK信号,确保无过冲、振铃和抖动。
-
驱动版本影响功能:较新的内核版本(如Linux 7.0)对FEC和KSZ8081的支持更完善,建议使用主线内核。
-
调试工具链要完备:准备好以下工具:
- 万用表(测量电源和信号电平)
- 示波器(检查时钟和数据信号)
- ethtool和mdio-tool(软件调试)
-
性能优化要循序渐进:先确保基本功能正常,再逐步优化中断亲和性、DMA缓冲区等高级参数。
-
文档与实测并重:PHY芯片手册中的推荐电路往往经过验证,应严格遵循,同时结合实际测试调整参数。
通过本教程的详细步骤和注意事项,你应该能够顺利完成IMX6ULL双网口的移植工作。如果在实际项目中遇到特殊问题,建议参考Linux内核文档和PHY芯片数据手册,这两者是最权威的参考资料。
