完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
作者:国防科技大学电子科学与工程学院 王崇红 习勇 魏急波
Linux驱动程序的基本原理 Linux下开发设备驱动程序的原理较之Windows系统来说结构层次简单明了。Linux操作系统中定义了三种设备,即字符设备、块设备和网络设备。字符设备是指存取时没有缓存的设备。块设备的读写都有缓存来支持,并且块设备必须能够随机存取,字符设备则没有这个要求,USB设备主要通过快速串行通信来读写数据,一般把它作为字符设备处理。 挂在Linux系统上的每个设备都被描述为设备驱动程序文件,一些与设备有关的设备参数文件被保存在/dev目录下。用户自己提供或编写设备驱动时,也需要在/dev目录下有一个设备文件。设备驱动程序可以分为三个主要组成部分:一是自动配置和初始化子程序 二是服务于I/O请求的子程序 三是中断服务子程序。 |
|
相关推荐
3个回答
|
|
用户对设备的访问主要有如下函数:
open,打开设备,典型的用法如下:open(/dev/xxx, flag); flag指定打开的参数,例如读写属性等;open函数返回一个整数fd句柄,如果fd小于0,表示打开错误。 read, write读写函数,用法如下:read(int fd, char *buf, char length,..)。 ioctrl设备控制函数,用户各类设备的特殊控制。 驱动程序的设计就是实现上述四个函数与外加一个设备初始化函数。这些函数在设备驱动程序中可以是dev_init(),dev_open(),dev_read(), dev_write(),dev_ioctrl()等。声明一个称之为file operation的结构体将用户级的open等函数与设备dev_open()等函数联系起来。例如 static struct file_operations dev-xxx_fops = { NULL, /* lseek */ dev_read, /* read */ dev_write, /* write */ NULL, /* readdir */ NULL, /* select */ NULL, /* ioctl */ NULL, /* mmap */ dev_open, dev_close, NULL /* fsync */ }; 为了将用户驱动程序与内核结合起来,首先向内核注册,请求内核分配主设备号与次设备号;二是注册中断,以便外部设备向CPU发出中断后能够处理设备中断函数。这些操作的一半在dev_init()函数内完成。dev_init()函数除了注册设备与注册中断外,还要完成设备特有寄存器初始化等操作。驱动程序与内核结合起来后,为了让应用程序能够访问该设备,还需要做一些额外的工作。前面提到,应用程序对设备的访问是通过访问文件的形式实现的,所以要建立一个文件节点与该设备相关联,使用命令 : mknod /dev/xxx option major minor 可以实现上述的关联。该命令的含义是建立一个/dev/xxx的文件节点,并且把特定主设备号与次设备号的设备与该节点关联。Option选项指定设备的类型,字符型还是块设备。有了关联后,应用程序要访问该设备,只要调用open (“dev/xxx”,...)函数即可。 |
|
|
|
MPC850 USB
MPC850是Motorola公司生产的32位嵌入式通信处理器,具有强大的通信和网络协议处理能力,特别适用于嵌入式通信和网络系统,它提供的功能与MPC860相似,在MPC860系统功能基础上增加了对USB的支持。 MPC850 USB不提供任何OHCI和UHCI接口,但它有作为主机控制器必须的功能。MPC850 USB没有与根集线器连接,当不止一个USB设备时需接一个外部集线器。在MPC850中主控制器类似于功能单元(function),它不遵循OHCI和UHCI标准。USB控制器由一个发送模块、一个接收模块、两个协议状态机构组成。一个协议机构执行功能状态表,另一个执行主机状态表。USB控制器可完成一个USB功能端点,一个USB主机和两种检测的任务。主控制器的特点如下: USB驱动程序由主控制驱动程序、USB子系统、USB设备驱动程序。 在Linux系统中存在一个连接USB设备驱动程序和主控制器驱动程序的子系统USBcore,它通过定义一些数据结构、宏和功能函数来抽象所有的硬件设备。USBcore提供了为硬件处理的所有下层接口,包含所有USB设备驱动和主机控制的通用程序,可称为UpperAPI和LowerAPI。USB子系统提供与设备驱动程序的接口,读取并解析USB设备描述符,配置描述符,为USB设备分配唯一的地址,使用默认的配置来配置设备,支持基本的USB命令请求,连接设备与相应的驱动程序,转发设备驱动程序的数据包。 虽然前面讲了驱动程序有两种加载模式,但是,如果 USBcore或主控制器驱动程序是内核模式,USB设备驱动程序就以模块方式加载。用u***_register和u***_deregister向USBcore子系统注册和注销驱动程序。所有USB驱动程序都有一个向子系统注册的结构。 struct u***_driver{ const char *name; /*模块名字*/ void *(*probe, struct u***_device*, unsigned int); /*probe 功能入口点*/ void (*disconnect, struct u***_device*, void*); /*disconnect功能入口点*/ struct list_head driver_list; /*子系统内部初始化*/ struct file_operations fops; /对驱动函数文件列表*/ int minor; } 在高速USB中时序安排是以1帧为基本要素的,每1ms为1帧,在每帧要产生并发送SOF包之外,还需要一个微码通道。同步传输和中断传输占90%的有效带宽,控制传输占10%,剩下的为块传输,如下表所示: SOF Isochronous Interrupt Control Bulk 控制传输完成了设备的配置,设备的轮流检测是由中断传输完成,大量的数据传输由块传输和同步传输完成。 MPC850是不支持这样的时序调度的,我们用1ms的时序器产生一个中断并在软件中运行这个调度。每个SOF时序里我们都加入一个SOF包到tx列表中,并监视发送包的列表,包是依据优先权来加入的。在每帧开始时,检查未处理事务,将符合优先级的队列元素放到当前帧中。驱动程序跟踪处理事务的设备,并不再向它发送事务。程序中用一个队列结构来完成这一调度的。如: 下面是分派队列元素到发送帧的结构。 struct m8xxhci_qe * take_from_current_frame(int qtype) { struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr; unsigned long flags; struct list_head *list; struct m8xxhci_qe *qe = NULL; ┋ if (!list_empty(list)) { ┋ qe->on_frame_list = 0; ┋ } spin_unlock_irqrestore(&framelist_lock, flags); return qe; } MPC850 USB主控制器的有些任务是硬件不支持的,必须由软件来实现。例如,发生错误及错误恢复后的重传、每秒产生和传输SOF、CRC5的产生等。这些功能是通过相应的结构体来完成,主控制器驱动向USBcore数据结构注册它的功能函数,它完成接口硬件的初始化、状态控制、传输差错控制、发送SOF帧、数据处理。 结构的每一个成员的名字都对应着一个系统调用,剩下的主要是子函数及结构体的编写,而编写子函数就很容易了。 |
|
|
|
结语
嵌入式Linux以及USB设备的应用越来越广泛。本文分析了MPC850 USB控制器的特点,描述了在嵌入式Linux操作系统下设备驱动程序的实现,对于使用PowerPC 系列CPU的开发人员具有一定的借鉴作用. |
|
|
|
只有小组成员才能发言,加入小组>>
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 17:36 , Processed in 0.818246 second(s), Total 81, Slave 63 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号