背景描述
前段时间在弄嵌入式的Linux系统,其实我主要负责的工作是QT应用层的维护开发,但是突然更换硬件平台,人手不够也就顺便搞了下驱动的移植。
对于Linux嵌入式设备而言,其主要构成也就是核心电路、flash、lcd、网口、串口、I2C、其他外设。
而驱动大都由芯片厂商提供了,从0开始写驱动基本上是不太现实的,基本步骤都是从已有的平台移植驱动,或者修改相似驱动。
最多的还是对驱动进行配置,也就是配置启用即可。
基本流程
- 复制驱动代码到相应的驱动目录,并修改
Kconfig
、Makefile
文件。Kconfig
是用于图形化菜单配置(make menuconfig
)的配置文件,用于控制配置项以及在菜单中显示相关描述信息。配置项就是一个宏,保存后会生成一个.config
文件,会根据配置项在Makefile中编译对应的.c
程序文件。 - 在
menu config
中打开驱动的选项。Enter进入次级目录,Y是选中编译(*),N是取消选中(空),M是编译为模块(M)。[ ]
方括号的选项是 * 和空 (一般选中后还有二级选项),< >
尖括号的选项可以是 * /空/M,( )
圆括号的选项是多个选项中选择一项。 - 修改DTS设备树,添加配置节点。
如果无法使用make menuconfig
命令,提示未安装ncurses libraries
,那么安装一个便是。Ubuntu可以使用sudo apt-get install libncurses5-dev
直接安装;使用yum
安装可以先用yum search ncurses
搜索一下,找到一个对应的进行安装即可。
硬件平台
我这边使用的是周立功的 A3352-WB128Li 核心板 + 公司的拓展底板。系统是从以前公司基于 Ti AM3352
自己做的核心板进行移植,芯片是同款芯片,移植起来稍微轻松些。
Linux 系统版本为 4.9.26。
周立功使用的phy芯片是Ti公司自家的 DP8384
,而我们使用的是Microchip的SMSC LAN8720
,两者的成本差距在几十块左右,所以还是有必要更换的。
本来是在周立功的平台上找他们专业工程师进行技术支持的,但是那边回复太慢了,寄过去也要一段时间,而且自己对BSP部分的了解还比较薄弱,因此还是决定自己搞。
移植记录
首先查看周立功提供的内核源码是否有LAN87xx
相关的驱动。
可以直接进入make menuconfig
里面进行搜索查找,也可以使用查找文件字符串的方式直接搜索。
进入到驱动文件夹drivers
,使用命令grep -rn "LAN87"
,其中r
表示递归,n
表示
搜索结果中看到了相关输出,还是比较幸运,周立功内核中带的有这个驱动,可以省去很多步骤了。
net/phy/smsc.c:215: .name = "SMSC LAN8700",
net/phy/smsc.c:260: .name = "SMSC LAN8710/LAN8720",
net/phy/smsc.c:283: .name = "SMSC LAN8740",
可以看到是smsc.c
的文件中有相关信息。
于是使用make menuconfig
在4.9的内核中打开SMSC网卡的驱动进行编译(同时也开启了PHY中的SMSC选项)。
在周立功提供的内核源码中,只需要去掉./build
脚本中的对应注释即可直接打开配置菜单。
该脚本在linux-4.9.28/board/am335x-T
目录下,这个目录也存放了am335x-T.dts
设备树源码。
想要知道通过菜单配置的驱动是否已经编译进了内核,可以在驱动文件的probe
相关函数中,添加kprintf
,即可以在驱动挂载时从内核输出信息了。
驱动代码已经编译通过了,并且有我们自己添加的输出,说明驱动本身没有任何问题。
查看内核启动日志,始终是两个网口,地址分别为:4a100000
和4a101000
。
正常的只有4a101000
这个地址才对,打算找一下地址的配置,也就是pinmux引脚里面,可以看到cpsw_default配置了两个slave。将Slave 2
注释掉。
// 屏蔽Slave 2
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
AM33XX_IOPAD(MII1_CRS, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs_dv */
AM33XX_IOPAD(MII1_RXERR, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxerr.rmii1_rxerr */
AM33XX_IOPAD(MII1_TXEN, PIN_OUTPUT | MUX_MODE1) /* mii1_txen.rmii1_txen */
AM33XX_IOPAD(MII1_TXD1, PIN_OUTPUT | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */
AM33XX_IOPAD(MII1_TXD0, PIN_OUTPUT | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */
AM33XX_IOPAD(MII1_RXD1, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */
AM33XX_IOPAD(MII1_RXD0, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */
AM33XX_IOPAD(MII1_REFCLK, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_refclk */
/* Slave 2 */
/*AM33XX_IOPAD(GPMC_A0, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */
/*AM33XX_IOPAD(GPMC_A1, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rctl */
/*AM33XX_IOPAD(GPMC_A2, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */
/*AM33XX_IOPAD(GPMC_A3, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */
/*AM33XX_IOPAD(GPMC_A4, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */
/*AM33XX_IOPAD(GPMC_A5, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */
/*AM33XX_IOPAD(GPMC_A6, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */
/*AM33XX_IOPAD(GPMC_A7, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */
/*AM33XX_IOPAD(GPMC_A8, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */
/*AM33XX_IOPAD(GPMC_A9, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */
/*AM33XX_IOPAD(GPMC_A10, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */
/*AM33XX_IOPAD(GPMC_A11, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */
>;
};
屏蔽后启动输出稍微有些不一样,但还是无法使用网络,并且仍然提示
[ 1.598551] davinci_mdio 4a101000.mdio: davinci mdio revision 1.6
[ 1.604958] libphy: 4a101000.mdio: probed
[ 1.611981] smsc phy probe !![ 1.614942] davinci_mdio 4a101000.mdio: phy[0]: device 4a101000.mdio:00, driver SMSC LAN8710/LAN8720
[ 1.627433] cpsw 4a100000.ethernet: No slave[1] phy_id, phy-handle, or fixed-link property
[ 1.636109] cpsw 4a100000.ethernet: Detected MACID = 44:ea:d8:ad:a8:1a
[ 1.645316] cpsw 4a100000.ethernet: cpts: overflow check period 500 (jiffies)
..........
[ 4.789015] SMSC LAN8710/LAN8720 4a101000.mdio:00: attached PHY driver [SMSC LAN8710/LAN8720] (mii_bus:phy_addr=4a101000.mdio:00, irq=-1)
[ 4.804095] libphy: PHY not found
[ 4.809679] net eth0: phy "" not found on slave 1, err -19
[ 4.822573] 8021q: adding VLAN 0 to HW filter on device eth0
后面终于找到这个配置的地方,在cpsw_emac0
节点里面,给phy_id
指定了1
。
我猜可能就是这里导致明明有mdio:00 内核却依然选择mdio:01 的原因,修改了先试一下。
&cpsw_emac0 {
/* phy_id = <&davinci_mdio>, <1>; */
phy_id = <&davinci_mdio>, <0>;
phy-mode = "rmii";
};
这里提一下phy-mode
的几种方式。详细介绍可以参考 这篇博客
- MII(Media Independent Interface)即媒体独立接口,以4位半字节方式传送数据双向传输,时钟速率25MHz。其工作速率可达100Mb/s。
RMII(Reduced Media Independent Interface)是简化媒体独立接口,是标准的以太网接口之一,比MII有更少的I/O传输。RMII收发使用2位数据进行传输,收发时钟均采用50MHz时钟源。
SMII(Serial Media Independant Interface),串行MII接口。它包括TXD,RXD,SYNC三个信号线,共用一个时钟信号,此时钟信号是125MHz,信号线与此时钟同步。
GMII(Gigabit Media Independent Interface),千兆MII接口。GMII采用8位接口数据,工作时钟125MHz,因此传输速率可达1000Mbps。同时兼容MII所规定的10/100Mbps工作方式。
编译后重新烧录一遍设备树,发现启动日志终于有输出正常挂载PHY地址的信息了,虽然还是有错误的地方,但是不影响。
尝试连接上网线,终于输出了期待已久的 Link up
,SSH
也可以正常登录了。
cpsw 4a100000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
Comments | NOTHING