linux 系统移植(第十七期)---Linux 内核移植(5)-- 修改网络驱动(2)--- Ubuntu20.04

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

[一、修改 fec_main.c 文件](#一、修改 fec_main.c 文件)

[二、配置 Linux 内核,使能 LAN8720 驱动](#二、配置 Linux 内核,使能 LAN8720 驱动)

[三、修改 smsc.c 文件](#三、修改 smsc.c 文件)

四、网络驱动测试

总结


前言

上一期更新了一部分的网络驱动修改,这一期我们继续介绍剩余部分。


一、修改 fec_main.c 文件

要 在 I.MX6ULL 上使用 LAN8720A , 需 要 修 改 一 下 Linux 内 核 源 码 , 打 开

drivers/net/ethernet/freescale/fec_main.c,找到函数 fec_probe,在 fec_probe 中加入如下代码:

复制代码
3438 static int
3439 fec_probe(struct platform_device *pdev)
3440 {
3441 	struct fec_enet_private *fep;
3442 	struct fec_platform_data *pdata;
3443 	struct net_device *ndev;
3444 	int i, irq, ret = 0;
3445 	struct resource *r;
3446 	const struct of_device_id *of_id;
3447 	static int dev_id;
3448 	struct device_node *np = pdev->dev.of_node, *phy_node;
3449 	int num_tx_qs;
3450 	int num_rx_qs;
3451
3452 	/* 设置MX6UL_PAD_ENET1_TX_CLK和MX6UL_PAD_ENET2_TX_CLK
3453 	 * 这两个IO的复用寄存器的SION位为1。
3454 	 */
3455 	void __iomem *IMX6U_ENET1_TX_CLK;
3456 	void __iomem *IMX6U_ENET2_TX_CLK;
3457
3458 	IMX6U_ENET1_TX_CLK = ioremap(0X020E00DC, 4);
3459 	writel(0X14, IMX6U_ENET1_TX_CLK);
3460
3461 	IMX6U_ENET2_TX_CLK = ioremap(0X020E00FC, 4);
3462 	writel(0X14, IMX6U_ENET2_TX_CLK);
3463
3464 	......
3456 	return ret;
3657 }

第3455~3462就是新加入的代码,如果要在 I.MX6ULL 上使用 LAN8720A 就需要设置ENET1 和 ENET2 的 TX_CLK 引脚复位寄存器的 SION 位为 1。

二、配置 Linux 内核,使能 LAN8720 驱动

输入命令"make menuconfig",打开图形化配置界面,选择使能 LAN8720A 的驱动,路径如下:

复制代码
-> Device Drivers
  -> Network device support
    -> PHY Device support and infrastructure
      -> Drivers for SMSC PHYs

选中Device Drivers,按enter进入

选中Network device support,按enter进入

选中 PHY Device support and infrastructure,按enter进入

选中 Drivers for SMSC PHYs,按enter进入

三、修改 smsc.c 文件

之所以修改这个文件,是因为LAN8720A驱动此方面的文件有问题,容易出现NFS挂载失败。

首先需要找到 LAN8720A 的驱动文件,LAN8720A 的驱动文件是 drivers/net/phy/smsc.c,

在此文件中有个叫做 smsc_phy_reset 的函数,看名字都知道这是 SMSC PHY 的复位函数,因

此,LAN8720A 肯定也会使用到这个复位函数,修改此函数的内容,修改以后的 smsc_phy_reset

函数内容如下所示:

复制代码
1 static int smsc_phy_reset(struct phy_device *phydev)
2 {
3 	int err, phy_reset;
4 	int msec = 1;
5 	struct device_node *np;
6 	int timeout = 5000;
7 	if(phydev->addr == 0) /* FEC1 */ {
8 		np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");
9
10 		if (np == NULL) {
11 			return -EINVAL;
12 		}
13 	}
14
15 	if(phydev->addr == 1) /* FEC2 */ {
16 		np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
17
18 		if (np == NULL) {
19 			return -EINVAL;
20 		}
21 	}
22
23 	err = of_property_read_u32(np, "phy-reset-duration", &msec);
24 	/* A sane reset duration should not be longer than 1s */
25 	if (!err && msec > 1000)
26 		msec = 1;
27
28 	phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
29 	if (!gpio_is_valid(phy_reset))
30 		return;
31
32 	gpio_direction_output(phy_reset, 0);
33 	gpio_set_value(phy_reset, 0);
34 	msleep(msec);
35 	gpio_set_value(phy_reset, 1);
36
37 	int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
38 	if (rc < 0)
39 		return rc;
40
41 	/* If the SMSC PHY is in power down mode, then set it
42 	 * in all capable mode before using it.
43 	 */
44 	if ((rc & MII_LAN83C185_MODE_MASK) ==
45 		MII_LAN83C185_MODE_POWERDOWN) {
46
47 		/* set "all capable" mode and reset the phy */
48 		rc |= MII_LAN83C185_MODE_ALL;
49 		phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
50 	}
51
52 	phy_write(phydev, MII_BMCR, BMCR_RESET);
53 	/* wait end of reset (max 500 ms) */
54 	do {
55 		udelay(10);
56 		if (timeout-- == 0)
57 			return -1;
58 		rc = phy_read(phydev, MII_BMCR);
59 	} while (rc & BMCR_RESET);
60
61 	return 0;
62 }

第 7~13 行,获取 FEC1 网卡对应的设备节点。

第 15~21行,获取 FEC2 网卡对应的设备节点。

第 23 行,从设备树中获取"phy-reset-duration"属性信息,也就是复位时间。

第 28 行,从设备树中获取"phy-reset-gpios"属性信息,也就是复位 IO。

第 32~35 行,设置 PHY 的复位 IO,复位 LAN8720A。

最后我们还需要在 drivers/net/phy/smsc.c 文件中添加两个头文件,因为修改后的 smsc_phy_reset 函数用到了 gpio_direction_output 和 gpio_set_value 这两个函数,需要添加的头文件如下所示:

复制代码
#include <linux/of_gpio.h>
#include <linux/io.h>

四、网络驱动测试

修改好设备树和 Linux 内核以后重新编译一下,得到新的 zImage 镜像文件和 imx6ull-alientek-emmc.dtb 设备树文件,使用网线将 I.MX6U-ALPHA 开发板的两个网口与路由器或者电

脑连接起来,最后使用新的文件启动 Linux 内核。启动以后使用"ifconfig"命令查看一下当前

活动的网卡有哪些,结果如图所示:

从上图中可以看出,当前没有活动的网卡。输入命令"ifconfig -a"来查看一下开发板中存在的所有网卡,结果如下图所示:

上图中 can0 和 can1 为 CAN 接口的网卡,eth0 和 eth1 才是网络接口的网卡,其中eth0 对应于 ENET2,eth1 对应于 ENET1。使用如下命令依次打开 eth0 和 eth1 这两个网卡:

复制代码
ifconfig eth0 up
ifconfig eth1 up

再次输入"ifconfig"命令来查看一下当前活动的网卡,结果如下图所示:

可以看出,此时 eth0 和 eth1 两个网卡都已经打开,并且工作正常,但是这两个网卡都还没有 IP 地址,所以不能进行 ping 等操作。使用如下命令给两个网卡配置 IP 地址:

复制代码
ifconfig eth0 192.168.1.251
ifconfig eth1 192.168.1.252

上述命令配置 eth0 和 eth1 这两个网卡的 IP 地址分别为 192.168.1.251 和 192.168.1.252,注意 IP 地址选择的合理性,一定要和自己的电脑处于同一个网段内(也就是前三段),并且没有被其他的设备占用!设置好以后,使用"ping"命令来 ping 一下自己的主机,如果能 ping 通那说明网络驱动修改成功!比如我的 Ubuntu 主机 IP 地址为 192.168.1.250,使用如下命令 ping 一下:

复制代码
ping 192.168.1.250

可以看出,ping 成功,说明网络驱动修改成功了,我们在后面的构建根文件系统和 Linux 驱动开发中就可以使用网络调试代码。


总结

上一期更新了一部分的网络驱动修改,这一期介绍了剩余的部分。并进行了网络驱动的测试。

总结一下移植步骤:

①、在 Linux 内核中查找可以参考的板子,一般都是半导体厂商自己做的开发板。

②、编译出参考板子对应的 zImage 和.dtb 文件。

③、使用参考板子的 zImage 文件和.dtb 文件在我们所使用的板子上启动 Linux 内核,看能

否启动。

④、如果能启动的话就万事大吉,如果不能启动那就悲剧了,需要调试 Linux 内核。不过

一般都会参考半导体官方的开发板设计自己的硬件,所以大部分情况下都会启动起来。启动

Linux 内核用到的外设不多,一般就 DRAM(Uboot 都初始化好的)和串口。作为终端使用的串口

一般都会参考半导体厂商的 Demo 板。

⑤、修改相应的驱动,像 NAND Flash、EMMC、SD 卡等驱动官方的 Linux 内核都是已经

提供好了,基本不会出问题。重点是网络驱动,因为 Linux 驱动开发一般都要通过网络调试代

码,所以一定要确保网络驱动工作正常。如果是处理器内部 MAC+外部 PHY 这种网络方案的

话,一般网络驱动都很好处理,因为在 Linux 内核中是有外部 PHY 通用驱动的。只要设置好复

位引脚、PHY 地址信息基本上都可以驱动起来。

⑥、Linux 内核启动以后需要根文件系统,如果没有根文件系统的话肯定会崩溃,所以确定 Linux

内核移植成功以后就要开始根文件系统的构建。

相关推荐
qq_406176143 小时前
深入剖析TCP/IP协议:互联网通信的基石
网络
街灯L3 小时前
【kylin-Linux】Flash兼容插件包安装
大数据·linux·运维·kylin
Howrun7773 小时前
Linux_C++网络编程四种CS模型
linux·运维·服务器
vortex53 小时前
如何快速删除 Linux 中的海量小文件:告别rm命令的缓慢困境
linux·运维·服务器
QH139292318803 小时前
罗德与施瓦茨 R&S®ZNL6 ZNL20 ZNB8矢量网络分析仪
网络
General_G4 小时前
ROS2资源汇总
linux·机器人·ros2
梦6504 小时前
网络传输七层协议
开发语言·网络·php
工业甲酰苯胺4 小时前
TCP三次握手与四次挥手:两个“社恐”程序的破冰与告别仪式
网络