韩金利
(山西机电职业技术学院数控工程系,山西 长治 046000)
目前,随着计算机技术、网络技术的快速发展,很多嵌入式设备也有网络互联的需求,嵌入式设备的网络化必将是未来发展的趋势[1]。所以对于多数嵌入式系统开发者而言,使嵌入式设备实现网络互连,是不可回避的关键性技术。
本文就是介绍基于linux 系统的网卡底层驱动编写,研究linux 系统下DM9000EP 网卡驱动的框架结构、存储器控制器的配置等技术。其中核心处理器采用三星公司开发的ARM9 芯片——S3C2440AL。Linux 系统采用2.6.22.6 版本的内核。
存储器控制器集成于S3C2440AL 中,S3C2440AL 的存储器控制器提供访问外部存储器所需要的存储器控制信号[2],微处理器S3C2440AL 通过存储器控制器使外设与CPU 之间交换数据,它决定了数据发送的地址宽度,数据宽度,读写时序等。该控制器负责传输网络数据所必需的控制信号,数据端口,地址端口。存储器控制器与网卡连接方框图如图1 所示。
图1 存储器控制器与网卡连接方框图
该控制器包括总线宽度和等待控制寄存器(BWSCON)、BANK 控制寄存器(BANKCONn)和刷新控制寄存器(REFRESH)。其中BANKCON 有8 个可编程寄存器,用于配置网卡的读写时序,BWSCON 用于设置网卡的数据宽度和等待状态。
本文中采用S3C2440AL 与DM9000EP 以太网控制器相连接,实现网卡的数据传送功能。其中S3C2440A L 是高性能嵌入式微处理器,主频可达400 MHz,具有外围接口丰富、体积小、功耗低等特点[3];DM9000EP 芯片完全集成了以太网MAC 控制器的基本功能,它具有处理速度快,成本低廉、设计简单等优点。
这里选用DM9000EP 为以太网MAC 控制器,它提供了两种接口,一种通用处理接口,另一种是介质无关的接口。其中包含4 个重要的控制信号IOR、IOW、INT 和CS,分别用于读、写、中断和片选的控制信号。S3C2440AL 与DM9000EP 硬件连接示意图如图2 所示。
图2 S3C2440A 与DM9000EP 连接图
1.2.1 接口配置
针对以太网控制器,S3C2440AL 的存储控制器能够产生相应的控制信号,如:nOE(读)、nWE(写)、nGCS4(片选)、EINT7(中断)等。如果要对DM9000 进行读写操作,必须对DM9000 正确寻址。根据实际设计电路,SA9 和SA8 接高电平,SA7- SA4 为低电平,DM9000EP 默认I/0 基地址为300H,而当CPU 发出地址在0x2000_0000—0x2800_0000 范围内时,DM9000 片选打开[4]。并且S3C2440AL 中7 号中断与以太网卡的中断引脚相连接,故EINT7 为中断触发信号。
其接口配置关键代码如下:
1.2.2 网卡读写时序配置
由于存储器控制器本身可以支持很多外设,而不同的外设芯片读写时序有所差异,所以当硬件开发人员选定以太网控制器时,就需要对存储器控制器的相关寄存器进行配置,在S3C2440 中,通过对BWSCON 和BANKCON4 进行配置,以实现处理器与控制器之间数据传输的匹配。本文中使用的是DM9000EP 以太网控制器。
存储器控制器硬件参数配置关键代码如下所示:
在Linux 系统中,网络设备一般被抽象为一个统一接口。本文中主要对网卡驱动程序进行设计,重点涉及到两个结构体,网络设备接口net_device 和套接字缓冲区sk_buff。net_device 结构体负责表示网络设备在内核中的运行状态,sk_buff 负责为Linux 网络层提供缓冲区的相关处理以及流量控制等任务。
在网卡驱动设计中,驱动程序需要对硬件进行配置,具体配置过程这里不赘述,这里主要叙述驱动如何实现数据包的发送与接收。
在net_device 中,比较重要的函数有open()和hard_start_xmit(),前者主要完成网卡中相关寄存器的初始化工作,后者负责将来自协议层的数据发送出去,本文中在dmfe_probe1(struct net_device * dev)函数中将net_device 与驱动中的open 函数、hard_start_xmit()函数建立关联。
数据包发送过程就是将上层数据包发送到网卡发送缓冲区,再设置发送控制器将发送缓冲区数据发送出去的过程。当用户发送数据帧时,DM9000EP 被激活,net_device 结构体中open()函数被调用,它负责向内核注册中断,复位并初始化dm9000,检查连接状态和媒介速度,并调用netif_start_queue(struct net_device* dev)使能传输[5]。然后通过调用net_device 结构体中的hard_start_xmit ()函数把存放在sk_buff 中的数据发送到网络物理设备中。hard_start_xmit ()函数处理流程是:首先对速度模式进行判断,根据速度模式确定不同的数据包数量,执行相应操作,这里主要是为了避免网络拥塞。然后包计数,关中断,将skb 数据长度发送到网卡相应的寄存器中,传输数据到TX SRAM,然后根据I/O传输模式,程序将数据发送到I/O 端口,设置发送控制寄存器TCR,数据被发送出去。最后释放sk_buff,打开中断。
其关键代码如下:
网卡数据包的接收可以采用轮询和中断两种处理模式,文章中DM9000 网络驱动程序采用中断方式,dmfe_interrupt()中断处理流程是:判断读取中断状态寄存器,通过检查硬件设备上的中断状态寄存器来判断是发送中断还是接受中断,若为发送中断就调用dmfe_tx_done(0);若为接受中断就调用dmfe_packet_receive(dev),该函数通过dev_alloc_skb()申请一块sk_buff 的缓冲区;并构造skb,然后通过netif_rx(skb)函数将skb 提交到上层。值得注意的是中断函数必须事先在open()函数中注册。其关键代码使用request_irq()函数将中断号与中断函数建立关联,并设置触发方式。具体代码这里不赘述。
这里采用挂载NFS 文件系统是否成功,来判断网卡驱动程序是否编写正确,建立NFS 文件系统的步骤如下:
1)实验环境为虚拟机,主机,arm 开发板三者通过路由器互联,虚拟机上安装ubuntu 9.10 编译环境。
2)通过CuteFTP 软件将驱动程序拖到Linux 系统内核drivers/net 目录中,修改此目录下的makefile 文件,编译内核生成镜像文件,烧写内核。
3)设置IP 地址。通过命令行方式,在虚拟机上设置某个目录允许被NFS 挂载。具体命令行如下:
通过以上三步网络文件系统挂载成功,说明网卡驱动运行正常。
文中介绍了关于DM9000 以太网控制器的配置过程,深刻详述了存储器控制器与网卡芯片之间的关系,网卡驱动程序与系统内核之间的关系,并在实验中得到验证,对以后的教学工作与科研工作有很大的借鉴意义。与此同时,有关网卡驱动的分析还有很多不足之处,以后会更加努力。
[1]徐功伟,戴学丰,刘树东,等.嵌入式以太网控制器设计[J].通信技术,2009,42(5):183-184,187.
[2]S3C2440A 32-Bit CMOS Microcontroller User's Manual,Revision 1,2004.
[3]蔡理金,王逢东,王丽洁,等.S3C2440A 嵌入式手持终端电源管理系统设计[J].单片机与嵌入式系统应用,2009(9):28-31.
[4]李剑雄,张策,杨军.基于ARM 和DM9000 的网卡接口设计与实现[J].微计算机信息,2008,52(14):123-124,138.
[5]韩超,王可人.基于DM9000 的嵌入式系统的网络接口设计与实现[J].工业控制计算机,2007,20(4):17-18.