Linux DM9000 Ethernet 网络驱动移植适配流程(8位数据, 挂载EMIF下 )

Linux DM9000 Ethernet 网络驱动移植适配流程

DM9000

Dm9000是一款单芯片快速以太网MAC控制器,支持8位,16位和32 -位接口访问内部存储器,以支持不同的处理器。
在这里插入图片描述

硬件接线

Dm9000模块与YL810A芯片的EMIF(外部内存访问接口)模块进行硬件连接,8位有效数据位,支持中断,片选,读写检测等信号引脚。
在这里插入图片描述

软件配置

menuconfig

按如图路径及配置方法对linux 源码的dm9k驱动进行支持。
│ Symbol: DM9000 [=y] │
│ Type : tristate │
│ Prompt: DM9000 support │
│ Location: │
│ -> Device Drivers │
│ -> Network device support (NETDEVICES [=y]) │
│ (1) -> Ethernet driver support (ETHERNET [=y]) │
│ Defined at drivers/net/ethernet/davicom/Kconfig:5 │
│ Depends on: NETDEVICES [=y] && ETHERNET [=y] && (ARM [=y] || MIPS || │
│ Selects: CRC32 [=y] && MII [=y]
在这里插入图片描述

DTS

EMIF:
在这里插入图片描述
DM9K:
在这里插入图片描述
从硬件电路图可以看到,dm9000是挂载到 EMIF 设备下的bank0 位置, 但是emi 驱动与其他挂载至通信协议模块(SPI,IIC)下的外设有所不同。如果将dm9000的设备树节点,作为三级节点挂载emi 的bank0位置下,那么驱动在加载过程中,就无法将设备树节点解析成resource, 那么驱动将无法获取设备树节点的属性,从启动log上就可以看到获取的物理空间地址就为null。设备树的转换为platform_device 必须满足一些两个条件:

  • 一般情况下,只对设备树中根的一级子节点进行转换,也就是多级子节点(子节点的子节点)并不处理。
  • 节点中必须有compatible属性。

综上所述,dm9k的设备树节点要挂载到一级节点, 即‘/’根节点下才能被驱动有效的解析。

驱动加载顺序

由于两个驱动emi,dm9k 都作为一级节点挂载至根节点下,并且两个驱动的加载的加载属于同一优先级,在yulong810的平台下进行调试过程中发现, dm9k的驱动先于emi的驱动加载, 由于dm9k的驱动是挂载至emi bank0位置, 如果EMI后于dm9k加载, 那么在dm9k加载过程中,emi mem便还没有进行初始化,dm9k在进行bank0的memery 映射时,便无法有效的的和dm9k模块进行交互。那么就无法获取设备ID,数据交互等信息。

所以,综上所述,需要修改驱动的加载顺序,麻烦的是,他们是同一优先级。

个人产尝试过几种方法:修改编译顺序,menuconfig 配置为“M”, dm驱动编译依赖EMI是否配置等方法,发现没有实际效果。后来,我修改了内核设置对应优先级的部分的代码, 个人对此解决方法持保留意见,也许会有更合理更有效的方法。但是我的方法也是完全解决了该问题, 并且修改的部分指针对dm9k的驱动,对其他驱动的优先级不会有影响。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
码里可以看到,两个驱动默认都是6 的加载优先级,但是dm9k 在实际的加载顺序是优先于emi的, 我这里将dm9k的驱动加载优先级降低至7 。 便实际解决了此问题。
驱动可以正常获取到ID。

BUG&FIX

  1. Q: 无法获取设备ID,读写异常。

问题背景:在初步调试过程中发现,无法读取读取设备ID, 读取的设备ID 不是0,就是一些很奇怪的数字。
问题分析: 芯片的寄存器数据访问按以往的方式获取:及地址+偏移 的方式,无法获取到,数据,并且用示波器进行信号采集,发现只有读写信号,没有数据过来。 后仔细对dm9k设备的交互方式分析,驱动读写源码分析,发现dm9k的驱动将emi mem 映射了两部分,一部分用于地址域,一部分用于数据域。从DTS上也可以看到物理地址是如何映射的:
在这里插入图片描述
在这里插入图片描述

解决方法: 将实际控制与外设外设交互的命令地址键入地址域, 然后从数据域里获取用户想要的数据。下图为emi驱动用于读写测试的emi mem bank0位置, 即dm9k 映射的区域,代码读写设备ID.
在这里插入图片描述
在这里插入图片描述
**

  1. Q:dm9k 作为三级节点挂载至emi bank0 下,驱动无法获取的设备节点属性,无法解析dts设备节点。
    问题背景:dm9k 作为三级节点挂载至emi bank0 下,驱动无法获取的设备节点属性,无法解析dts设备节点。驱动获取resource 为NULL, 返回错误。
    问题分析:查阅3.2章节, 不再赘述。
    解决方法:查阅3.2章节, 不再赘述。

  2. Q: dm9K 驱动无法正确读取设备ID,设备ID为0;
    问题背景:
    在这里插入图片描述

问题分析:查阅3.3章节, 不再赘述。
解决方法:查阅3.3章节, 不再赘述。

  1. Q: 无法正常获取设备IP;
    问题背景:驱动可以正常加载,也有多一个网络设备eth1, 但是接上网线后,无任何反应。
    问题分析:利用ethtool 工具进行测试,发现硬件连接是正常的。示波器分析中断信号线,发现中断信号是异常的,然后再中断服务例程中加入log, 运行发现没有进入中断函数中,所以由此可以判断,中断是有问题的。分析中断pin脚连接在EMI_CSN1位置,其复用功能为GPIO26。
    在这里插入图片描述
    在这里插入图片描述
    手动利用devmem 命令控制复用 功能寄存器,将其配置为GPIO,发现依旧无法正常进入中断函数,对驱动中断相关代码分析, dm9k驱动无法处理GPIO作为中断,它实际调用request_irq 向系统申请一个实际的外部中断对应的Linux irq。所以,需要将此中断信号线,接入系统外部中断控制引脚。
    在这里插入图片描述
    依旧利用devmeme 命令手动修改寄存器,配置ioreuse为EXT_IRQ2功能, 很惊喜,发现有中断了, 并且设备获取到了IP。
    解决方法: 暂利用ioremap方法,将ioreuse功能寄存器映射至虚拟地址,然后将对应的引脚功能配置为:EXT_IRQ2.(0x12048)
    在这里插入图片描述

  2. 设备树设置的中断号与驱动获取的中断号不一致。
    问题背景: 调试中断过程中发现,驱动初始化过程中申请的中断号为:33, 而实际配置的中断号为:52(注:datasheet 中断号从1开始,实际要减1)
    在这里插入图片描述
    问题分析:platform_get_irq()返回Linux IRQ号,而不是实际的硬件号。 当您有两个中断控制器(即两个irq_chip)可用时(例如GIC和GPIO IC),需要进行映射。 为了解决这个问题,Linux内核提出了IRQ域的概念,该域是硬件IRQ编号与内核内部使用的IRQ编号之间的明确定义的转换接口。 因此,GIC驱动程序创建其IRQ域并在init上进行转换。 kernel.org/doc/Documentation/IRQ-domain.txt
    解决方法:属正常处理方法,新知识get !!!

  3. 最后的坑:ID没问题 , IP 也可以获取到,中断也是正常,也没有任何异常提示,但是网络无法ping通。
    问题背景:网络无法ping通,无任何错误提示。
    问题分析:最后一步,本以为柳暗花明了,很开心的ping了一下网络,我人崩溃了,发现网络无法ping通,PC到板,板到pc,都不通。利用wireshark 进行抓包分析发现,板与PC 有实际的数据交互,但是无法解析。(大致能看出这些东西,没搞过网络协议,不是很懂)。然后回归代码,经同时帮忙分析,发现dts的配置有问题。Dts的reg 属性参考官方给的例程:reg = <0xe0000000 0x2 0xe0000004 0x2>, 第一个为地址,第二个为长度。在驱动加载过程中,利用platform_get_resource()函数获取地址, 利用resource_size() 函数获取长度。0x2是16个字节,应该是16位的设备使用的, 我们挂载的是8位的设备,所以dts 应该配置为0x1。
    在这里插入图片描述
    解决方法: 如上。

测试

硬件连接测试

测试工具:ethtool
测试方法:ethtool eth1
测试结果:
在这里插入图片描述

网络性能测试

测试工具:iperf3
测试方法:iperf3 -c -t 100
测试结果:
在这里插入图片描述

稳定性测试

测试工具:ping
测试方法:ping
测试结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38505858/article/details/126361063