1、滨州学院本科毕业设计(论文) Linux下网络驱动程序设计与开发摘 要作为Unix操作系统的一个衍生系统,Linux普及与发展的非常迅速,Linux操作系统被许多企业和个人所使用, Linux操作系统可安装在各种计算机硬件设备中,从手机、平板电脑、路由器和视频游戏控制台,到台式计算机、大型机和超级计算机,这就使Linux下设备驱动程序的开发变得愈来重要,但是Linux操作系统的设备种类繁多,缺少一种通用的驱动程序适用于Linux操作系统的各种设备之中,针对Linux网络设备,需要设计出相应的网络驱动程序。本论文通过对Linux 网络设备驱动程序的工作原理和结构组成的研究,探讨Linux环境下网
2、络驱动程序的开发过程,首先详细的对Linux设备驱动程序进行分析介绍,其次介绍了ARM驱动程序开发的硬件环境和软件环境,阐述了该驱动程序在开发时的需求分析。第三对Linux环境下网络驱动程序的设计与实现作了理论上的探讨。 对于驱动程序而言,核心问题之一就是如何完成调试,本论文在对网络驱动程序的调试过程中, 使用了一种独特的printk方法,是调试过程变得简单,避免了对驱动程序的重复操作 。关键词:Linux; 网络驱动程序;TCP/IP协议Development and design of linux network card drivers AbstractLinux technology
3、is a hotspot among computer technology nowadays, and it developes at high speed not only in our country but also in the whole world, and it has applied widely in embedded system, server, network system, security area and so on. So it makes that grasping the development technology under the Linux env
4、ironment is more and more noticeable in computer industry.One of the many advantages of free operating systems, as typified by Linux, is that their internals are open for all to view. The Linux kernel remains large and complex body of code. User activities are performed by means of a set of standard
5、ized calls that are independent of the specific driver; mapping those calls to device-specific operations that act on real hardware is then the role of the device driver.Allocating IP addresses and subnet masks differentiating network and host, through construction of TCP/IP network in Linux. Config
6、uring hosts IP arguments dynamically to well solve the problem of manual configuration, through Key words:linux; network card drivers;The TCP/IP protocol II目 录第一章 绪论11.1课题的目的和意义11.1.1课题的研究目的11.1.2课题的研究意义11.2课题的国内外研究现状11.3 本文主要内容2第二章 LINUX设备驱动程序42.1 Linux设备驱动程序概述42.1.1 Linux设备驱动程序分类4第三章 LINUX下网络驱动程序6
7、3.1 Linux下网络驱动程序设计的数据结构和方法63.1.1网络驱动程序设计用到的数据结构63.1.2驱动网络驱动程序的基本方法93.2套接字缓冲区介绍113.3驱动模块的加载和卸载143.4编写网络驱动程序的一些基本概念153.4.1发送和接收153.4.2中断153.4.3时钟15第四章 系统分析174.1 S3C2410 ARM 开发板介绍174.2需求分析以及MII接口17第五章 LINUX下网络驱动程序具体实现205.1 Linux网络驱动程序体系结构205.1.1加载模块及初始化设备225.1.2初始化设备成员和函数245.1.3注册、打开、关闭设备285.1.4接受和发送数据
8、305.1.5设置参数和统计数据325.1.6统计网卡数据信息335.1.7 网络驱动程序调试33结论34参考文献35谢辞36附录 网络驱动程序代码36ii42滨州学院本科毕业设计(论文)第一章 绪论1.1课题的目的和意义随着人们对开放源代码软件热情的日益增高,Linux作为一个功能强大而稳定的开源操作系统,越来越受到计算机专家与爱好者的关注。在嵌入式领域中,通过对Linux进行小型化裁剪后,使其能够固化在容量只有几十兆字节的存储器芯片或单片机中,成为应用于特定场合的嵌入式Linux系统。Linux强大的网络支持功能实现了对包括TCP/IP在内的多种协议的支持,可以为嵌入式系统应用联网的需求提
9、供相应的解决方法。因此,在嵌入式系统开发调试时,Linux下网络驱动设计成为不可缺少的步骤。1.1.1课题的研究目的Linux操作系统的设备种类繁多,缺少一种通用的驱动程序适用于Linux操作系统的各种设备之中,由于Linux是开放的源代码,能够方便的给用户提供分析和设计网络驱动程序的机会,本课题针对Linux 网络设备驱动程序的结构组成和工作原理进行分析,主要对Linux下网络驱动程序的开发技术进行探究,着重对网络驱动的开发流程及具体实现细节进行讨论,最后进行必要的调试,设计出基于ARM的LINUX网络驱动程序。1.1.2课题的研究意义Linux系统的设备主要由字符设备,块设备和网络设备构成
10、,Linux设备驱动程序的增加,相应的Linux的内核源代码就会增加,Linux 网络设备驱动程序在Linux 操作系统内核中占有重要地位,掌握了Linux网络设备驱动程序的原理与设计技术,对于我们从事基于Linux平台的网络产品开发具有十分重要的意义。1.2课题的国内外研究现状Linux以其特有的高效、安全、可动态加载及源代码开放等特点,实现了快速的发展,Linux下网络驱动程序作为Linux操作系统网络应用的一个重要组成部分,其强大的网络处理能力、高稳定性和较强的安全性得到了普遍的认同,但不可回避的是Linux上的应用程序相对来说还十分有限,对各种硬件的支持远不如Windows系统,没有一
11、种能够通用的驱动程序适用于Linux各种硬件,在国内外的Linux网络驱动的研究中,人们发现网络设备作为三大设备之一,有着其非常特殊的地方,它与字符设备及块设备有很大的区别:1、在 Linux 的文件系统中,网络接口并不存在,在核心里,用device数据结构表示。在文件系统中,每一个字符设备或块设备都有一个对应的特殊设备文件来表示该设备,如/dev/hda1、/dev/sda1、/dev/tty1 等。在网络设备进行数据包的发送和接收时,可以径直通过接口访问,不需要进行文件的操作;而对字符设备和块设备的访问都需通过文件操作界面。 2、在系统初始化时,网络接口实时生成,对于核心支持的但不存在的物
12、理网络设备,将不可能有与之相对应的 device 结构。而对于字符设备和块设备,即使该物理设备不存在,在/dev 下也必定有相应的特殊文件与之相对应。且在系统初始化时,核心将会对所有内核支持的字符设备和块设备进行登记,初始化该设备的文件操作界面(struct file_operations) ,而不管该设备在物理上是否存在。1.3 本文主要内容论文首先对Linux下设备驱动程序设计的基本知识进行介绍,其中包括对Linux的发展历程、内核、特性的概述,Linux设备的分类及编写驱动程序的一些基本概念等,以及模块的加载和卸载。其次介绍了ARM驱动程序开发的硬件环境和软件环境。阐述了该驱动程序在开发
13、时的需求分析。第三对Linux环境下网卡驱动程序的设计与实现作了理论上的探讨,重点从网卡驱动模块的加载、网络设备的初始化、设备打开与关闭、数据的发送与接收、信息统计、网卡驱动模块的卸载等方面按步骤的进行了详细的讨论。通过组建在Linux操作系统下的TCP/IP网络,来分配IP地址以及区分网络号和主机号的子网掩码,通过配置DHCP服务器,实现动态地为主机配置IP参数,解决手工配置存在的问题。最后介绍了在驱动程序开发设计过程中所遇到的问题和困难以及是如何去克服这些困难的,并提出了今后的努力方向。38第二章 Linux设备驱动程序2.1 Linux设备驱动程序概述在 Linux内核里,驱动程序起着特
14、殊的作用。驱动程序可以让某个固定的硬件回应另一个定义好的编程接口,这些接口没有显示设备工作的具体过程。用户的活动通过一套规范的调用来实施,但是这些调用不隶属于特定的驱动程序。设备驱动程序的任务就是将这些调用映射到与作用到实际硬件设备有关的操作上。 这个编程接口能够允许驱动程序独立于内核其他部分而建立,需要的情形下能够在系统运行的时侯,“插入”内核。这种特点造成Linux驱动程序的编写非常容易,所以内核驱动程序的数目增长非常快,截至到现在已经有许多的驱动程序能够在Linux下被应用。2.1.1 Linux设备驱动程序分类在Linux的内核源代码中,Linux设备驱动程序占有比较大的比例,源代码的
15、长度的增加,增加的是驱动程序。随着Linux内核的升级,驱动程序的结构比较稳定。在Linux系统中,设备可以分为字符设备(char device),块设备(block device)和网络设备(net work device)三种。字符设备:字符设备是指存取时没有缓存的设备,块设备的读写都有缓存来支 持,并且块设备必须能够随机存取(random access),字符设备则没有这个要求。典型的字符设备包括鼠标,键盘,串行口等。块设备主要包括硬盘软盘设备,CD-ROM等。一个文件系统要安装进入操作系统必须在块设备上。块设备:块设备通过位于/dev目录下的文件系统节点来存取。块设备上可以包纳文件系统
16、。Linux能够允许应用程序如字符设备一样地读写块设备。网络接口:任何网络事件都是通过一个网络接口形成的,一个网络接口就是一个能够和其他主机交换数据的设备。通常,接口都是硬件设备,但也可能是纯软件设备,比如回环(loopback)接口。网络接口由内核中的网络子系统驱动,负责数据包的接收和发送,但它不需要了每项事务是如何映射到实际传送的数据包的。许多网络连接是面向流的,但网络设备却围绕数据包的传输和接收而设计。网络驱动程序不需要知道各个连接的相关信息,它只要处理数据包即可。第三章 Linux下网络驱动程序3.1 Linux下网络驱动程序设计的数据结构和方法全部Linux网络驱动程序使用通用的接口
17、。设计Linux下网络驱动程序时,我们使用的是面向对象的方法。一个设备就是一个对象(device 结构),在它内部,有自己的数据和方法。在调用每一个设备的方法时,第一个参数就是这个设备对象本身。这种方法就能够存取本身的数据。3.1.1网络驱动程序设计用到的数据结构位于网络驱动层核心位置的net_device1结构是我们理解网卡设备的最好切入点。(1) 全局信息net_device结构的第一部分是由以下成员构成:char nameIFNAMSIZ;设备称谓。如果由驱动程序设置名称,这样就包含%d格式串, register_netdev 用一个数字代替它使之成为一个唯一的名字,我们在分配时,编号从
18、0开始。unsigned long state;设备状态。设备状态包含一些数量的标志。在正常情况下,驱动程序不直接参与到操作这些标志的行动,而是由内核提供一组工具函数对这些标志进行特定操作。struct net_device *next;这是个指针,指向全局列表中下一个设备。驱动程序不参与修改这个成员。int (*init)(struct net_device *dev);初始化函数。如果对这个指针进行设置,register_netdev 调用这个函数用来完成对net_device结构的初始化。很多当今的网络驱动程序已经不再运用这个函数,它们的初始化工作是在注册接口前完成的。(2).硬件信息以
19、下的成员含有相对简单设备的低层硬件信息。它们延续了早期 Linux的 网络特点,它们仍然被现在许多驱动程序使用。unsigned long rmem_end;unsigned long rmem_start;unsigned long mem_end;unsigned long mem_start;设备的内存信息.。设备使用了共享内存,这些共享内存的开始地址和结束地址由这些成员保存。如果设备使用不同的接收和发送内存,发送内存使用mem成员,接收内存使用rmem成员。在驱动之外,rmem成员不被引用。根据要求,设置end成员的时候,我们要保证end - start等于可用的板卡内存量。unsig
20、ned long base_addr;网络接口的I/O基地址。我们驱动设备探测时给这个成员赋值。 Ifconfig命令能够来显示或修改当前值。在系统启动时、或者在模块加载时,base_addr在内核命令行中显式赋值。和内存成员一样的是,内核不使用它们。unsigned char irq;被赋予的中断号。当列出接口时,ifconfig命令打印出dev-irq的值。通常情况,这个值在启动或者加载时设置,然后用ifconfig命令修改。unsigned char if_port;在多端口设备中,指定使用哪个端口。例如,如果这个设备支持同轴电缆(IF_PORT_10BASE2)的同时,也支持双绞线(I
21、F_PORT_100BSAET)以太网连接,就可以使用该变量。完整的已知端口类型设置定义在。unsigned char dma;为设备分配的DMA通道。这个成员仅仅对一些外设总线有用,比如 ISA。 它仅仅用于显示信息(ifconfig命令)。ether_setup函数正确设置有关接口的许多信息,或者任何其他给定硬件类型适合的设置函数。以太网卡可以通过这个通用的函数,从而设置大部分这些成员,flags和dev_addr成员例外,它们是特定设备的, 所以在初始化时显示赋值。在一些非以太网接口中,我们也可以应用像ether_setup的辅助函数。deviers/net/net_init.c 输出了
22、包括下列的类似函数:void ltalk_setup(struct net_device *dev);设置一个 LocalTalk 设备的函数。void fc_setup(struct net_device *dev);初始化光通道设备。void fddi_setup(struct net_device *dev);配置一个光纤分布数据接口(FDDI)网络接口。void hippi_setup(struct net_device *dev);对高性能并行接口(HIPPI)的高速互连驱动的成员进行初始化。void tr_setup(struct net_device *dev);对令牌环网络接口
23、的设置进行处理。我们把大部分设备都归于这些类别中的一类。假如设备是一个比较新的类,就需要对下面的成员进行手工设置:unsigned short hard_header_len;硬件头部长度,就是在数据包中,位于IP头、其他协议信息之前的octet数目。对于以太网接口hard_header_len的值是14(ETH_HLEN)。unsigned mtu;最大传输单元(MTU)5。在网络层中,对于数据包的传输,使用该成员变量来驱动。 unsigned long tx_queue_len;设备发送队列中可以排队的最大帧数ether_setup把这个值设置为100,特殊的是我们可以更改它。例如,设置p
24、lip为10来避免系统内存浪费。unsigned short type;接口的硬件类型.。用ARP来决定type成员由接口支持什么样的硬件地址。对以太网接口正确的值是ARPHRD_ETHER,该值是ether_setup设置。能够识别的类型在中定义。unsigned char addr_len;unsigned char broadcastMAX_ADDR_LEN;unsigned char dev_addrMAX_ADDR_LEN;硬件(MAC)地址长度和设备硬件地址。ether_setup会对上述值进行正确地设置。此外,设备地址从接口板卡中的读出必须以特定于设备的方式,然后驱动程序把它拷贝
25、到dev_addr中。unsigned short flags;int features;这个flags 成员是一个位掩码。内核管理一些标志,接口在初始化期间设置其他的标志,这可以用以声明接口的能力及其他特性。在中定义有效的标志。3.1.2驱动网络驱动程序的基本方法在网络设备中,有许多函数能够对它进行操作。下面我们介绍一下能够对网络接口进行的操作。网络接口的设备方法可归为基本的和可选的两个类型。基本方法与可选的方法的区别在于:可选的方法可以实现更高级的性能,这些功能并不是我们严格要求的。下面介绍基本方法:int (*open)(struct net_device *dev);打开接口。在ifc
26、onfig激活接口时,打开接口。open方法应该注册设备需要的所有系统资源(I/O口、IRQ、DMA等等),打开硬件,并且对设备执行其他所要的设置。 int (*stop)(struct net_device *dev);停止接口。它被关闭的时候接口终止。int (*hard_start_xmit) (struct sk_buff *skb, struct net_device *dev);该方法对数据包的传输初始化。在套接字缓存区(sk_buff)结构中,有一个完整的数据包(协议头和所有)int (*hard_header) (struct sk_buff *skb, struct net_
27、device *dev, unsigned short type, void *daddr, void *saddr, unsigned len);该方法依据先前取到的源和目的硬件地址,从而建立硬件头,并且在 hard_start_xmit前被调用。该函数的作用是:将作为参数传入的信息组织成一个合适的硬件头,该硬件头特定于设备。eth_header是以太网类型接口的默认函数, ether_setup把该成员赋值,变成eth_header。int (*rebuild_header)(struct sk_buff *skb);在ARP4解析完成之后、在报文发送之前,该函数用来重新建立硬件头。在以太
28、网设备运用的缺省的函数中,通过使用ARP协议,充实数据包没有的硬件地址信息。void (*tx_timeout)(struct net_device *dev);在一定的时间段内,若数据包传输没有成功,则假定中断或接口被锁住,这时,网络代码将调用该方法,它负责解决问题并重新开始数据包的传输。struct net_device_stats *(*get_stats)(struct net_device *dev);任何时候当一个应用程序需要获取接口的统计信息,则调用这个方法。例如,当ifconfig或者netstat -i运行时将利用到该方法。int (*set_config)(struct n
29、et_device *dev, struct ifmap *map);在改变接口配置时,这个方法是配置驱动的入口点。设备的 I/O 地址和中断号可以通过运行set_config来改变。在探测不到接口时,系统管理员可使用该函数。除开上面提及到的基本方法以外,还有很多的可选方法。通过这些可选的方法,实现禁止中断、轮询模式操作接口、执行接口特有的ioctl命令、改变硬件地址、改变接口的MTU、以及hh-cache的查询更新等功能。3.2套接字缓冲区介绍套接字缓冲区这个结构处于 Linux 内核网络子系统的核心,Linux内核中网络数据包的传输和接收都是通过套接字缓冲区实现的。在中, 能看到该结构和函
30、数原型。(1). 重要成员变量这里描述的成员都是驱动程序需要访问的。struct net_device *dev;接收或发送该缓冲区的设备。union /* */ h;union /* */ nh;union /*/ mac;指向报文中包含的各级的头的指针。union中的每个成员都是一个不同数据结构类型的指针。h中含有传输层头部指针(例如struct tcphdr *th);nh包含网络层头部(例如struct iphdr *iph);以及mac包含链路层头部指针(例如struct ethkr * ethernet)。网络驱动程序要负责设置传入数据包的mac指针,这个任务正常是由 eth_ty
31、pe_trans 处理,但是非以太网驱动不得直接设置skb-mac.raw。unsigned char *head;unsigned char *data;unsigned char *tail;unsigned char *end;指向数据包中数据的指针。head 指向分配内存的开头,data是有效字节的开始(并且常常稍微比head大一些),tail是有效字节的结尾,end指向tail能够到达的最大地址。通过它们可以计算出可用的缓存空间(skb-end - skb-head)和当前使用的空间(skb-tail - skb-data)。unsigned int len;unsigned int
32、 data_len;len是报文中全部数据的长度,data_len是报文存储于单个片中的数据片段的长度,如果使用sctter/gather I/O,data_len 成员的值为0。unsigned char ip_summed;对报文的校验策略。该成员由驱动程序对传入数据包进行设置。unsigned char pkt_type;在发送过程使用的数据包类型。驱动程序负责将其设置为PACKET_HOST (数据包是给我的),PACKET_OTHERHOST,PACKET_BROADCAST,或者PACKET_MULTICAST。以太网驱动不显式修改 pkt_type,因为eth_type_tran
33、s会完成这个工作。shinfo(struct sk_buff *skb);unsigned int shinfo(skb)-nr_frags;skb_frag_t shinfo(skb)-frags;处于对性能方面的考虑,skb中的一些信息分散存储在内中与其紧邻的其他结构中。(2) 作用于缓冲区的函数使用sk_buff11结构的网络驱动程序通过一些正式的接口函数来操作该结构。下面是最常用的几个函数。struct sk_buff *alloc_skb(unsigned int len, int priority);struct sk_buff *dev_alloc_skb(unsigned in
34、t len);分配一个缓存区。alloc_skb函数分配一个缓存并且将skb-data和skb-tail 都初始化成skb-head。dev_alloc_skb函数以GFP_ATOMIC的优先级调用 alloc_skb函数,并且在skb-head和skb-data之间保留了一些空间,网络层使用这一数据空间进行优化工作,驱动程序不应该访问它。void kfree_skb(struct sk_buff *skb);void dev_kfree_skb(struct sk_buff *skb);void dev_kfree_skb_irq(struct sk_buff *skb);void dev_
35、kfree_skb_any(struct sk_buff *skb);释放一个缓冲区。kfree_skb调用由内核在内部使用。一个驱动应当使用一种dev_kfree_skb形式的函数。在非中断上下文中使用dev_kfree_skb,在中断上下文中使用dev_kfree_skb_irq,dev_kfree_skb_any在上面两种情况下均可以使用。unsigned char *skb_put(struct sk_buff *skb, int len);unsigned char *_skb_put(struct sk_buff *skb, int len);更新sk_buff构中的tail和le
36、n成员;可用这些函数在缓冲区尾部添加数据。unsigned char *skb_push(struct sk_buff *skb, int len);unsigned char *_skb_push(struct sk_buff *skb, int len);递减skb-data和递增skb-len的函数。除了数据是添加到报文的开始而不是结尾以外,它们的功能与skb_put相似。在传输数据包之前,可使用该函数添加硬件头。int skb_tailroom(struct sk_buff *skb);该函数返回缓冲区中可用空间的大小。如果驱动程序释放了多于它能持有的数据到缓存中,则系统会出现pani
37、c来标识出这个错误。int skb_headroom(struct sk_buff *skb);;返回data前面的可用空间数量,也即是有多少字节能够保存在该缓冲区中。void skb_reserve(struct sk_buff *skb, int len);这个函数递增data和tail。这个函数可用来在填充数据前保留报文头部空间(headroom)。大部分以太网接口在数据包之前保留2个字节,这样IP头可在14字节的以太网头之后,在16字节边界上对齐。unsigned char *skb_pull(struct sk_buff *skb, int len);从报文的头部删除数据。它递减sk
38、b-len和递增skb-data;这是从传入的数据包的头部剥离硬件头所使用的方法。int skb_is_nonlinear(struct sk_buff *skb);如果这个skb分离为多个片为发散/汇聚 I/O,则该函数返回一个真值。int skb_headlen(struct sk_buff *skb);返回skb的第一个片的长度(该部分指向skb-data)。void *kmap_skb_frag(skb_frag_t *frag);void kunmap_skb_frag(void *vaddr);如果要在内核中直接访问非线性skb中的数据片段,这些函数负责映射和解除映射。由于使用了原
39、子性的kmap,因此不能一次映射多个片段。3.3驱动模块的加载和卸载对驱动模块构造好之后,我们需要把驱动模块装入内核,在必要的时候我们也需要将其卸载。 Linux驱动程序的加载有两种方式:一种是动态加载,使用insmod或者rmmod加载或卸载设备驱动程;另外一种是静态加载。Linux中独有的技术是模块设计,模块设计能够很方便的扩展Linux的内核功能,我们在设计Linux网络设备驱动程序时,应用模块方式也很简单易行,而且可以固定模式。在嵌入式设备中,硬件的功能一般是特定、专一的,在将驱动程序编进内核时,我们通常选择静态编译来获得更高的效率。基于这两种方式的特点,我们在调试过程中,采用模块加载
40、的方法,这样做是为了调试方便,可以使编译内核更加简单,在调试成功以后,我们就把其编译进内核,这样运行效率会更高。模块加载设计步骤如图3-1:Insmod命令Init module()初始化Register_retdev()注册Init指针初始化函数Rmmod命令关闭网卡设备数据包发送和接收打开网卡设备图3.1 模块加载步骤图在加载命令insmod时,通过模块我们可以使网络设备驱动程序插入进内核,入口函数init_module()可以调用register_netdev0函数,网络设备就是在Linux系统中注册。注册成功后,就可以调用init函数指针所指向的初始化函数,初始化设备,把设备中的net
41、_device数据结构进行处理,在链表的末尾插入。在结束初始化后,就能够打开设备,发送和接收数据包。进行模块卸载时,先关闭设备,再通过执行模块卸载命令rmmod来调用驱动cleanup_moduIe()函数卸载该模块。Rmmod工具完成模块从内核中的模块移除任务。如果内核认为模块仍然在使用状态(例如,某个程序正打开由该模块导出的设备文件),或者内核被配置为禁止移除该模块,则无法移除该模块3.4编写网络驱动程序的一些基本概念所有操作系统的驱动程序具有通用的概念。同时操作系统给予驱动程序的支持也一样。对于网络设备驱动程序的若干基本要求,我们通过下面的文字简单介绍一下。 3.4.1发送和接收发送和接
42、收是网络设备最基本的功能。网卡的本职工作就是收发。因此在驱动程序里,需要通知系统发送函数的位置,在有数据要发送时,系统会调用发送程序。有的驱动程序因为是直接操纵硬件的,因此驱动程序能最先得到这个数据,驱动程序的任务是把原始数据进行必须的处理后,然后传入到系统里。操作系统需要提供两个不同的机制,首先是发现驱动程序的发送函数,然后驱动程序接收数据后,把它传给系统。3.4.2中断在现代计算机结构中,中断有着很特殊的作用。操作系统一定得提供驱动程序响应中断的能力。通常情况就是把一个中断处理程序注册到系统里。硬件中断发生后,操作系统使用驱动程序,通过驱动程序处理程序。Linux支持对中断的共享,就是对一
43、个中断,许多个设备共享。3.4.3时钟时钟在实现驱动程序时侯,会应用到很多地方。比如超时处理,缺乏中断机制的硬件轮询。操作系统可以为驱动程序提供定时机制。通常回调注册的时钟函数是在预定时间过了之后。在网络驱动程序中,假如硬件缺乏中断性能,定时器可以提供轮询(poll)方式,从而存取硬件。第四章 系统分析4.1 S3C2410 ARM 开发板介绍CPU:S3C2410 ARM的CPU采用SAMSUNG S3C2410 ARM920t ,集成有串口,SD卡控制器,USB Host和USB device控制器,LCD控制器,Nand Flash控制器等。存储器由以下部分构成:64M SDRAM,64
44、M Nand Flash,32M Intel StrataFlash 32M(默认不焊接),SD卡,一个VGA(直接连接普通PC显示器), CS8900以太网控制器,IDE接口,一个USB 主机接口,一个USB设备接口(可以切换成第二主机,需要更改驱动),一个总线扩展接口(包含16位数据,12位地址,两个片选,可以通过CPLD控制)。其他关联设备:2个串口输出,一个MIC输入接口,一个LINE音频输入接口,一个耳机输出接口,2个CPU可控LED,AD转换输入接口,SPI和IIC接口,JTAG调试接口,CPLD编程接口,扩展GPRS和CDMA专用接口(包含3.3V电平的串口,SPI口,IO引脚,
45、电源等)。4.2需求分析以及MII接口随着2.4内核代码不断的提高级别,我们看到随着升级,内核代码的编写也趋于混乱,就现在来看,在清晰度上,2.6比2.4更加有优势,也分类定义了资源,具有很好的可读性,修改起来也很简单;2.6的代码大量使用C的struct,从而具有C+的面向对象风格;2.6支持标准的高级电源管理;在同一个目标板上,2.6的内核相比2.4的内核,具有更高的效能。 三星的sdmk开发板使用这种内核,相比较而言,2.4的内核的驱动程序比较全,大部分国内的2410应用的是2.4的内核,。目前在s3c2410开发板上,linux2.6的内核能够很稳定的运行,通过完成驱动程序,很快就可以
46、实现移植。MII(Media Independent Interface介质无关接口)13,或称为媒体独立接口,它是IEEE-802.3定义的以太网行业标准。它包括一个数据接口,以及一个MAC和PHY之间的管理接口。数据接口包括分别用于发送器和接收器的两条独立信道。每条信道都有自己的数据、时钟和控制信号。MII数据接口总共需要16个信号。管理接口是个双信号接口:一个是时钟信号,另一个是数据信号。通过管理接口,上层能监视和控制PHY。MII(Management interface)只有两条信号线。MII标准接口用于连接Fast Ethernet MAC-block与PHY。在不对MAC硬件重新
47、设计或替换的情况下,任何类型的PHY设备都可以正常工作。在其他速率下工作的与 MII等效的接口有:AUI(10M以太网)、GMII(Gigabit以太网)和XAUI(10-Gigabit以太网)。在IEEE802.3中规定的MII总线是一种用于将不同类型的PHY与相同网络控制器(MAC)相连接的通用总线。网络控制器可以用同样的硬件接口与任何PHY进行连接。以太网媒体接口有:MII,RMII,SMII,GMII,所有的这些接口都从MII而来,MII是(Medium Independent Interface)的意思,是指不用考虑媒体是铜轴、光纤、电缆等,因为这些媒体处理的相关工作都有PHY或者叫做MAC的芯片完成。MII支持10兆和100兆的操作,一个接口由14根线组成,它的支持还是比较灵活的,但是有一个缺点是因为它一个端口用的信号线太多,如果一个8端口的交换机要用到112根线,16端口就要用到224根线,到32端口的话就要用到448根线,一般按照这个接口做交换机,是不太现实的,所以现代的交换机的制作都会用到其它的一些从MII简化出来的标准,比如RMII、SMII、MI