基于嵌入式Linux的千兆以太网卡驱动程序设计及测试

一. 引言

千兆以太网是一种具有高带宽和高响应的新网络技术,相关协议遵循IEEE 802.3规范标准。采用和10M以太网相似的帧格式、网络协议和布线系统,基于光纤和短距离同轴电缆的物理层介质,更适用于交换机、服务器等数据吞吐率大的设备。本文设计实现一种基于嵌入式Linux千兆以太网卡的驱动程序,并完成后续的测试工作和代码移植。

千兆以太网网卡工作在OSI网络架构的物理层和数据链路层,其中物理层由PHY芯片管理,数据链路层由千兆以太网控制器(GMAC)管理。硬件构架上,GMAC控制器由核心层、MTL(MAC Transaction Layer)层、DMA层和总线接口层构成,如下图1-1所示。核心层连接PHY芯片,管理和PHY芯片之间的通信;MTL层建立物理层和内存之间的数据通道,调整帧传输结构,控制数据流,转换时钟域;DMA层完成数据的传输任务。GMAC配置寄存器CSR(Control and Status register)通过系统总线和CPU交互,CPU通过总线slave端配置DMA 和MAC区的CSR,其中MAC区的CSR可以设置PHY的芯片寄存器,通过对CSR的设置可以控制网卡切换工作状态。

                                                   图 1-1

千兆以太网卡的数据传输任务由DMA完成,DMA传输操作通过预先在内存中建立描述符的方式完成。描述符的作用是指定MAC帧数据所在的缓存地址,每个描述符可以最多指定两个缓存地址,缓存大小有严格控制,一个描述符不能指定全部一个帧的缓存数据,需要多个描述符构成描述符链来完成。

                                                          图1-2

有两种描述符链结构:环状描述符和链状描述符。链状描述符中的第二个buffer指定了下一个描述符所在的物理地址,而第一个buffer指定帧数据缓存的位置,环状结构描述符的位置是有序排放的,两个buffer都指向帧数据的缓存地址,最后一个描述符指向第一个描述符所在物理地址形成桶状描述符链。环状和链状结构如图1-2所示,一个描述符链只能用来存储一个MAC帧的数据,DMA每个通道一次最多完成两个MAC帧的传输,多MAC帧的传输需要重新使能DMA通道。

描述符的具体结构如图1-3所示:

                                图1-3

OWN位控制描述符是由DMA控制还是由HOST端控制,后面31位是描述符状态信息,DES1为控制描述符并标明两个buffer大小,DES2和DES3描述两个buffer所在地址。

二. 千兆以太网卡驱动程序设计

GMAC驱动程序需要完成的内容有:PHY芯片初始化,GMAC初始化,GMAC读/写数据,GMAC数据流控制和各种模式设置。

GMAC初始化流程图如图2-1所示:

                  

                               图2-1

GMAC初始化过程首先检查PHY芯片工作是否正常并配置PHY芯片模式,创建发送和接收描述符,初始化DMA,然后配置MAC工作模式,使能DMA后进入工作状态。

初始化完成后,数据等待发送或接收,DMA根据描述符状态自动完成数据发送或接收的任务。buffer中的帧结构不包含preamble , PAD byte和FCS段,只包含源地址,目的地址和类型/长度域。如果MAC禁止CRC校验和PAD插入,那么buffer就必须包含完整的帧结构,其中必须包含CRC校验位。DMA一次搬运最多两帧数据,所以初始化后如果需要完成多帧数据搬运需要重新使能DMA。

GMAC发送和接收过程如图2-2所示:

              

                                图2-2

初始化后,第一次帧传输不需要等待中断,DMA自动完成发送接收任务,当有多次帧传输时,DMA在完成一次发送接收任务后会给CPU发送中断,CPU响应中断处理下一次读写任务。如果读写过程中发生帧错误等导致操作未完成,则会产生相应异常中断直到CPU清除中断位标志,此时GMAC停止工作。

驱动程序设计完成寄存器到功能函数的转换,给上层操作系统提供应用接口,Linux嵌入式操作系统有一套标准的接口规范,根据该规范设计驱动需要预先定义两种重要的结构体:

描述符程序结构体设计:


typedef struct DmaDescStruct
{
  __u32 status; //DMA状态
  __u32 length; //buffer1和buffer2长度
  __u32 buffer1; //buffer1地址
  __u32 buffer2; //buffer2地址
//下面数据仅为驱动使用
  __u32 extstatus; //接收描述符的扩展位状态
  __u32 reserved1; //保留部分
  __u32 timestamplow; //时间戳
  __u32 timestamphigh;
  __u32 data1; //buffer1虚拟地址(驱动备用)
  __u32 data2; //buffer2虚拟地址(驱动备用)
}DmaDesc;


GMAC控制器设备程序结构体设计:
typedef struct GMACDeviceStruct
{
  __u32 MacBase; //MAC基地址
  __u32 DmaBase; //DMA基地址
  __u32 PhyBase; //PHY基地址
  __u32 Version;


  DmaDesc *TxDesc; //发送描述符链开始地址
  DmaDesc *RxDesc; //接收描述符链开始地址

  __u32 BusyTxDesc; //当前DMA所拥有发送描述符链数量
  __u32 BusyRxDesc; //当前DMA所拥有接搜描述符链数量


  __u32 RxDescCount; //当前描述符链中接收描述符数量
  __u32 TxDescCount; //当前描述符链中发送描述符数量


  __u32 TxBusy; //指明当前发送描述符是否由DMA控制,即OWN位是否为1
  __u32 TxNext; //指明下一个描述符链是否有效
  __u32 RxBusy;
  __u32 RxNext;


  DmaDesc * TxBusyDesc; //与TxBusy对应的当前描述符地址
  DmaDesc * TxNextDesc; //与TxNext对应的下一个描述符链地址
  DmaDesc * RxBusyDesc;
  DmaDesc * RxNextDesc;


  __u32 ClockDivMdc; //时钟分频数
  __u32 LinkState;   //网卡链接状态
  __u32 DuplexMode;  //半双工,全双工等工作模式选择
  __u32 Speed;       //连接速度。10M/100M/1000M
  __u32 LoopBackMode; //LoopBack模式
}GMACdevice;

 

三. 测试实现

测试程序对GMAC进行了相应的黑盒测试和压力测试,黑盒测试用来测试GMAC千兆网卡的各个模块输入相应信号是否得到正确的输出信号,压力测试用来测试网卡的系统稳定性。

测试程序通过GMAC的LoopBack模式将数据写入内存并让GMAC发送,再从接收描述符指定的内存中读出,判断写入写出数据是否一致,完成数据读写测试。对于功能点测试,主要测试的GMAC功能有:PHY芯片自协商完成验证,GMAC LoopBack模式,哈希值和MAC帧过滤,CRC校验和,AV模式和时间戳支持模式。

一次读写测试完成后,测试程序改变GMAC模式和状态,再进行一次数据读写测试,同时加大数据量和功能点以完成压力测试,再次判断写入写出数据是否一致。不断循环进行直到测试程序测试结束,测试过程要完成判定覆盖和条件覆盖的100%代码覆盖率,需要不断改变输入信号和功能以满足测试意图,使用LoopBack模式的测试信号发送和接收结果如图所示: 

PHY和MAC使用GMII接口连接,全双工模式下发送的同时进行接收操作,实验结果发现在帧传输速度提升到1.3GMbps时,有明显的丢帧现象,MAC层的帧数据FIFO原数据被冲刷,丢帧现象明显。在使能中断的情况下,发生丢帧后会立刻进入异常中断,DMA停止工作等待CPU响应中断。

四. 结束语

该驱动程序已经在Linux嵌入式系统下调试通过,所有代码在Linux嵌入式系统下移植完成,驱动程序在MaPU定制指令SOC系统上调试通过,使用该驱动完成后续上层软件开发。验证平台基于ARM Cortex A8,测试仿真使用RealViewDebugger完成指令仿真,使用VCS进行时序精确仿真,测试程序代码覆盖率达到90%以上。

原地址:http://blog.sina.com.cn/s/blog_6372441a0101juug.html

原文地址:https://www.cnblogs.com/rayhe/p/9132611.html

时间: 2024-11-03 21:01:45

基于嵌入式Linux的千兆以太网卡驱动程序设计及测试的相关文章

基于嵌入式Linux下GCC编译器__sync_sub_and_fetch_4错误的解决心得

******************************************************************************************************************************************************* 作者:EasyWave                                                                                      

Linux 网卡驱动程序设计(1)

一.网卡驱动架构分析 1. Linux 网络子系统 #系统调用接口层 为应用程序提供访问网络子系统的统一方法. #协议无关层 提供通用的方法来使用传输层协议. #协议栈的实现 实现具体的网络协议 #设备无关层 协议与设备驱动之前通信的通用接口 #设备驱动程序 2. 重要数据结构 2.1 网卡描述结构 在Linux内核中,每个网卡都由一个<net_device>结构来描述,其中的一些重要成员有: #char name[IFNAMSIZ] 设备名,如:eth%d #unsigned long ba

基于GPL329xx linux平台电容屏gsl1680的驱动调试分析

因客户有用到了gsl1680 7寸电容屏,所以拿了一块过来,便在329xx的平台上面开始调试了. 大概浏览了一下所提供的资料,只有介绍模组的资料跟一份中文版的datasheet,datasheet只是说了个大概,没有提到读取触摸坐标的寄存器.不过还好有给一份在其他处理器平台的驱动,所以读取坐标的部分代码移植过来就可以了. gsl1680接口跟其他的电容屏一样,也是i2c接口的,貌似市面上的电容屏都是i2c接口,电容屏自带了微控制器MCU,用与处理采样,坐标转换等,还有一些抖动算法处理,完后将坐标

千兆/万兆单向传输网卡

单向传输网卡一种计算机网络的单向传输网关,属于计算机网络技术领域.它包括发送方以太网光纤卡.接收方以太网光纤卡以及连接它们的网络光纤线.发送方以太网光纤卡的模块只有发送端口.接收方以太网光纤卡的模块只有接收口.发送卡的发送口与接收卡的接收口采用单条光纤连接.它既实现了计算机内部网络与外部网络之间的物理隔离,又能够保证数据在内外网络之间实时.可靠.安全地单向传输.配合软件使用,可广泛应用于公安.政务系统.军队等要害部门以及其它需要保密的计算机网络中. 主要功能 跨网域数据迁移 应用于内外网分离的企

千兆双电口网卡

电口网卡也称为铜缆网卡,千兆电口网卡是千兆网卡中使用最为广泛的一个类别,大到公司企业常用到的服务器网卡:小到家用台式机网卡等都是现在热门的网卡型号,这里为大家介绍飞迈瑞克基于Intel芯片研发的千兆双电口网卡有哪些-- 千兆双电口网卡_Intel 82571芯片 飞迈瑞克FM-JL82571EB-T2是一款服务器专用千兆网卡,它具有2个10/100/1000M自适应的RJ45接口,可支持20/200/2000Mbs的传输带宽,同时支持PCI-E X4 标准插槽,保证了网卡高效.稳定的工作.另外网

一张国产网卡:同时使用万兆和千兆网络

通常情况下,当我们因业务发展而更新服务器网络设备时,总会遇到新老设备兼容性的问题而增加系统的不稳定性.例如:双口万兆光纤网卡,按需求一个业务口连接到万兆光纤交换机的网络上,另一个业务口连接到千兆光纤交换机的网络上,在实施试机调试的时候,连接万兆那边的很顺利,而连接到千兆的时候却怎么都链接不上,检查交换机没问题,检查网卡没问题,甚至把能检查的机器设备都检查了都没找到问题. 这就"恼火"了,究竟是什么问题呢? 这里面的主要问题是,在网络共享的计算机上使用了无法同时支持万兆和千兆的网卡上,有

linux下安装编译网卡驱动的方法

安装linux操作系统后发现没有网卡驱动,表现为 system → Administration → Network下Hardware列表为空. 以下为安装编译网卡驱动的过程,本人是菜鸟,以下是我从网上找的资料进行整理,并实际操作的过程,仅供借鉴.  一.检测linux系统内核版本和网卡类型,相关命令如下: uname -r                    查看linux内核版本 (uname -a 可显示所有信息)lsmod                        设备加载情况 l

转: 嵌入式linux下usb驱动开发方法--看完少走弯路【转】

转自:http://blog.csdn.net/jimmy_1986/article/details/5838297 嵌入式linux下的usb属于所有驱动中相当复杂的一个子系统,要想将她彻底征服,至少需要个把月的时间,不信?那是你没做过. 本人做过2年的嵌入式驱动开发,usb占了一大半的时间.期间走了不少弯路,下面将我的血的经验教训总结下,为要从事和正在从事的战友们做一点点贡献吧:) 首先,扫盲: 要做的是阅读usb Spec(英文的哦,其实很多文章.书籍和资料真有水平的还是原创的好,就像食品

嵌入式Linux内核tasklet机制(附实测代码)

Linux 中断编程分为中断顶半部,中断底半部 中断顶半部: 做紧急,耗时短的事情,同时还启动中断底半部.中断底半部: 做耗时的事件,这个事件在执行过程可以被中断.中断底半部实现方法: tasklet,工作队列,软中断等机制实现.实际上是把耗时事件推后执行,不在中断程序执行. 什么是tasklet? Tasklet 一词的原意是"小片任务"的意思,这里是指一小段可执行的代码,且通常以函数的形式出现.这个 tasklet 绑定的函数在一个时刻只能在一个 CPU 上运行 ,tasklet(