b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

嵌入式Linux网络驱动程序的开发和实现原理

电脑杂谈  发布时间:2020-03-20 02:05:49  来源:网络整理

嵌入式linux驱动程序设计从入门到精通_嵌入式 linux驱动_嵌入式linux驱动程序设计从入门到精通 pdf

0简介

随着对开源软件的热情不断提高,Linux作为一种功能强大且稳定的开源操作系统,越来越受到成千上万的计算机专家和发烧友的青睐. 在嵌入式领域,Linux经过小型化和切割后,可以在容量仅为几十兆字节的存储芯片或单片机中固化,并成为适用于特定场合的嵌入式Linux系统. Linux强大的网络支持功能支持包括TCP / IP在内的多种协议,可以满足面向21世纪的嵌入式系统应用程序的需求. 因此,在开发和调试嵌入式系统时,网络接口已成为必不可少的模块.

1嵌入式Linux网络驱动程序简介

作为Linux网络子系统的一部分,Linux网络驱动程序位于TCP / IP网络体系结构的网络接口层中. 它主要实现上层协议栈与网络设备之间的数据交换. Linux的网络系统主要基于BSD Unix套接字机制. 与字符设备和块设备不同,网络设备没有相应地映射到文件系统中的设备节点.

通常,Linux驱动程序有两种加载方式: 一种是静态编译到内核中,然后在内核启动时自动加载;另一个则写为内核模块,并使用insmod命令将该模块动态加载到正在运行的内核中. 如果不需要它,可以使用rmmod命令卸载该模块. Linux 2.6内核引入了kbuild机制,该机制将外部内核模块的编译与内核源代码树的编译统一起来,从而大大简化了特定参数和宏的设置. 通过这种方式,将书面的驱动程序模块添加到内核源代码树中. 您只需要修改相应目录中的Kconfig文件,将新驱动程序添加到内核配置菜单中,然后您需要修改相应子目录中与模块编译相关的Kbuild Makefile,以使新驱动程序在内核源代码树. 在嵌入式系统驱动程序的开发中,驱动程序通常被编写为内核模块,以方便开发和调试. 调试后,可以将驱动程序模块编译到内核中,然后重新编译支持特定物理设备的Linux内核.

2嵌入式Linux网络驱动程序的体系结构和实现原理

2.1 Linux网络设备驱动程序体系结构

如图1所示,Linux网络驱动程序的体系结构可以分为4个级别. Linux内核源代码提供了网络设备接口和更高级别的代码,因此移植特定网络硬件驱动程序的主要工作是完成设备驱动程序功能层的相应代码,并根据特定的定义网络设备接口结构net_device基础层的硬件特性. 键入结构变量,并实现相应的操作功能和中断处理程序.

Linux中的所有网络设备都抽象为一个统一的接口,即网络设备接口. 内核中网络设备的结构由struct net_device类型结构变量表示. 这包括回送设备和回送设备. 包括硬件网络设备接口. 内核通过设备链接列表(以dev_base作为头指针)来管理所有网络设备.

2.2 net_device数据结构

struct net_device结构是整个网络驱动程序结构的核心. 它为网络协议接口层定义了许多标准方法来调用设备. 该结构在2.6内核源树文件中定义. 下面仅列出主要成员.

2.2.1全局信息和基础硬件信息

name: 网络设备名称,默认为以太网;

* next: 指向全局链接列表中下一个设备的指针,该指针在驱动程序中未修改;

mem_,rmem_: 发送和接收缓冲区的开始和结束位置;

嵌入式linux驱动程序设计从入门到精通 pdf_嵌入式linux驱动程序设计从入门到精通_嵌入式 linux驱动

base_addr,irq: I / O基地址,网络设备的中断号,ifconfig命令可以显示和修改;

hard_header_len: 硬件头的长度,以太网中位数为14;

mtu: 最大传输单位,以太网中位数为1500B;

dev_addr [MAX_ADDR_LEN]: 硬件(MAC)地址长度和设备硬件地址,以太网地址长度为48bit,ether_setup会正确设置它;

2.2.2主要操作方法

int(* init)(结构net_device * dev);设备初始化和在系统中注册的功能,仅调用一次;

int(*打开)(struct net_device * dev);当使用ifconfig激活网络设备,注册在激活硬件时使用的系统资源(I / O端口,IRQ,DMA等)并增加使用计数时,将调用设备开放接口功能;

int(*停止)(struct net_device * dev);执行open方法的逆运算;

* hard_start_xmit;初始化报文传输功能;

* hard_header;此函数(在hard_start_xmit之前调用)基于先前检索的源和目标硬件地址构建硬件标头. eth_header是以太网类型接口的默认功能;

2.3网络驱动程序的编写和实现原理

Linux网络系统各层之间的数据传输是通过套接字缓冲区sk_buff完成的. sk_buff数据结构是每一层协议数据处理的对象. sk_buff是用于在驱动程序和网络之间交换数据的介质. 当驱动程序将数据发送到网络时,它必须从中获取数据源和数据长度. 从网络接收到数据之后,驱动程序还必须在将数据移交给sk_buff之前将其保存. 由上层协议处理.

对于以太网驱动程序的实际开发,可以参考内核源代码树中的相应模板程序,着重了解网络驱动程序的实现原理和程序的结构框架,然后为为实现相应的操作功能而开发的特定硬件. 下面,作者使用Linux2.6.18内核在深圳FS2410开发板(SAMSUNG S3C2410处理器)上移植并编写嵌入式CS8900A网卡驱动程序,并说明该网络驱动程序的实现原理.

2.3.1网络设备初始化

网络设备的初始化由net_device结构中的init函数实现. 内核加载网络驱动程序模块后,将调用初始化过程. 在示例中的初始化函数_init cs8900_probe中完成的主要工作:

a. 呼叫ether_setup();

嵌入式linux驱动程序设计从入门到精通 pdf_嵌入式 linux驱动_嵌入式linux驱动程序设计从入门到精通

b. 将其他大多数成员填充到net_device结构变量dev;

c. 调用check_mem_region()来检测I / O地址空间,然后调用request_mem_region()来申请以dev-> base_addr;

开始的16个连续的I / O地址空间. d. 通过cs8900_read()检测网卡CS8900A,并读取ID信息;

e. 将CS8900A的INTRQ0设置为中断信号输出引脚;

f. 将MAC地址写入CS8900A的IA寄存器;

g通过register_netdev()将CS8900A注册到Linux全局网络设备列表中;

2.3.2打开(或关闭)网络设备

系统响应ifconfig命令时,将打开(关闭)网络接口. ifconfig命令首先调用ioctl(SIOCSIFADDR)为接口分配地址. 对SIOCSIFADDR的响应由内核完成,与设备无关. 接下来,ifconfig命令将调用ioctl(SIOCSIFFLAGS)来将dev->标志的IFF_UP位置1以打开设备. 该调用将导致调用设备的open方法. (当ifconfig调用ioctl(SIOCSIFFLAGS)清除dev->标志的IFF_UP位时,将调用设备的stop方法)

在示例中,使用cs8900_start()函数打开网络设备,主要任务已完成:

a. 通过set_irq_type()向内核注册网络设备的中断处理程序.

b. 通过cs8900_set()设置CS8900A网卡中的每个控制寄存器和配置寄存器;

c. 通过内核中的netif_start_queue()函数打开网络接口的数据传输队列;

2.3.3发送网络数据包

发送和接收数据包是网络驱动程序中实现的两个最重要的任务. 激活网络设备后,将调用net_device结构中的open方法. 它负责打开设备并在net_device结构中调用hard_header函数指针以建立硬件帧头信息. 最后,函数dev_queue_xmit()用于调用net_device结构中的hard_start_xmit方法,以将sk_buff中存储的数据发送到网络物理设备. 如果传输成功,则在hard_start_xmit中释放sk_buff并返回0;否则,返回0. 如果硬件设备繁忙且无法进行临时处理,则返回1. 网络硬件发送数据包后将产生中断. 将dev-> tbusy设置为0,以通知系统可以再次发送.

在示例中,hard_start_xmit方法是网络设备数据发送功能cs8900_send_start(). 该函数将数据发送到以太网,并由网络协议接口层函数dev_queue_xmit()调用. 在cs8900_send_start()中完成的主要工作:

a. 发送数据前关闭中断,并暂停网络设备的数据传输队列;

嵌入式 linux驱动_嵌入式linux驱动程序设计从入门到精通_嵌入式linux驱动程序设计从入门到精通 pdf

b. 将传输数据命令控制字写入CS8900A寄存器TxCMD,并将要发送的数据帧的长度写入寄存器TxLength;

c. 反复通过cs8900_read()读取CS8900A总线状态寄存器BusST信息,直到准备好从主机接收数据为止.

d. 调用cs8900_frame_write()将要发送的数据发送到CS8900A的sk_buff,然后硬件设备会将数据帧发送到以太网;

e. 记录数据帧的发送时间,使能中断,释放sk_buff缓存,函数返回0;

2.3.4接收和中断网络数据包

网络设备异步接收传入的数据包,并主动“请求”将由硬件获得的数据包推送到内核中. 网络设备通过中断接收数据包. 对于网络接口,当接收到新的数据包,传输完成或报告错误消息以及连接状态时,将触发中断. 通常,中断处理程序通过检查硬件状态寄存器来确定是哪种情况.

当设备接收数据时,将产生一个中断,并且硬件会通知驱动程序数据包已到达. 在中断处理程序中,驱动程序申请一个sk_buff(通常定义为skb)缓冲区,然后从硬件读取数据并将其放在请求的缓冲区中. 然后,它将在sk_buff中填充一些信息: 包括接收数据的设备结构. 主体指针填充在skb-> dev中;接收到的数据帧的类型以skb->协议填充;指针skb-> mac.raw指向硬件数据,并且丢弃硬件指针(skb_pull);设置skb-> pkt_type表示链路层数据类型. 最后嵌入式 linux驱动,调用协议接口层函数netif_rx()将接收到的数据包传输到网络上层协议进行处理. 在此,netif_rx()仅负责将数据放入工作队列并返回. 真正的处理是在中断返回之后进行,这可以减少中断处理时间. 几乎每个中断处理程序都采用下半部机制编写,以确保高效地处理中断.

示例中的数据接收函数cs8900_receive()由网络驱动的中断处理函数调用,该函数主要完成以下任务:

a. 通过从I / O端口读取RxStatus和RxLength的值来确定状态信息和接收到的数据帧的长度;

b. 确定接收到的数据帧状态是否正常,如果异常,记录相关的错误信息,然后函数返回;

c. 通常情况下,请在内存中申请sk_buff高速缓存,然后将数据从CS8900A的片上存储器传输到sk_buff高速缓存; d. 从数据帧中获取协议头,并将其分配给skb->协议;

e. 通过调用netif_rx()函数将接收到的数据发送到上层协议栈进行处理;

f. 记录接收数据的时间并更新统计信息;

3将设备驱动程序模块编译到内核中

在设计了模块化网络驱动程序之后,我们可以编译此内核模块并编译此自定义内核模块作为Linux系统源代码的一部分,以构建一个新系统. 以下内容是在Linux 2.6.18内核上编译的,可以在2.6.x内核中使用. 如前所述,由于Linux2.6内核引入了kbuild的新机制,因此可以很容易地编译新的内核模块或将您自己编写的内核模块集成到内核源代码中.

在Linux2.6内核中,必须在/ usr / src下正确配置和构建内核模块,即,所需版本的内核源代码在/ usr / src /中解压缩,并且位于内核源代码的主目录. (在/usr/src/linux-2.6.18.3中),使用make menuconfig或make gconfig命令配置内核,然后使用make all完全编译内核.

嵌入式linux驱动程序设计从入门到精通_嵌入式linux驱动程序设计从入门到精通 pdf_嵌入式 linux驱动

下面以作者开发的CS8900A网卡驱动程序为例,介绍如何将网络设备驱动程序模块编译到内核中.

a. 在系统源代码树的drivers目录中创建一个新目录Cs8900;

b. 将准备好的文件cs8900.c和cs8900.h复制到drivers / Cs8900目录;

c. 在驱动程序/ Cs8900目录中写入一个Makefile:

#Makefile CS8900A网络驱动程序

obj- $(CONFIG_DRIVER_CS8900A)+ = cs8900.o

d. 在drivers / Cs8900目录中,编写一个Kconfig文件:

#Just for CS8900A网络接口

菜单“ CS8900A网络接口支持”

配置DRIVER_CS8900A

三态“ CS8900A支持”

--------帮助--------

这是CS8900A的网络驱动程序模块.

endmenu

e. 在驱动程序目录的Kconfig文件中的endmenu语句之前嵌入式 linux驱动,添加一行:

来源“驱动程序/ Cs8900 / Kconfig”

在内核源代码树的主目录中,可以通过make menuconfig或make gconfig命令在“设备驱动程序”选项下找到CS8900A网络接口支持选项,并找到CS8900A支持的选择菜单. 它具有三种状态: 未选中(不编译),选择(M)作为模块进行编译,选择(*)作为新系统的一部分进行编译.

重新编译内核,以获取支持CS8900A网卡的内核. 然后将内核下载到FS2410的开发板上. 通过配置网络参数,可以测试网卡驱动程序的行为.

4结论

在这个信息爆炸的时代,人们对​​网络的需求越来越强. 越来越多的嵌入式设备需要具有以太网访问权限. 因此,网络驱动程序的开发对于许多嵌入式产品的开发很重要. 在专门开发嵌入式Linux网络驱动程序时,可以参考内核中已经支持的网络驱动程序源代码. 在了解Linux网络驱动程序实现原理的基础上,根据模块相对固定的开发模式,结合特定物理设备的硬件手册,移植并编写所需的模块化网络驱动程序.


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/ruanjian/article-145476-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      每日福利
      热点图片
      拼命载入中...