时间:2021年10月18日 分类:推荐论文 次数:
基于Linux平台高清摄像头USB驱动的研究
胡雄晖
摘要:本文通过在嵌入式系统中对USB摄像头驱动的改进,并对基于Relay技术的高清摄像头设备驱动作了分析和说明,有效提升摄像头整体性能。
关键词:Linux;USB驱动;Relay
1 Linux内核USB驱动框架
每一类设备都提供了通用接口,以便在需要时为内核提供服务。这种通用接口使得内核可以以相同的方式来对待不同的设备及驱动程序[1]。在应用程序看来,硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。
Linux内核提供了完整的USB驱动程序框架。USB总线采用树形结构,在一条总线上只能有唯一的主机设备。Linux内核从主机和设备两个角度观察USB总线结构。在linux系统中,USB主机驱动程序由3部分组成:USB主机控制器驱动(HCD)、USB核心驱动(USBD)和不同种类的USB设备驱动。
2 USB驱动程序主要数据结构
1) 主机控制器用于管理主机硬件与USB设备的数据传输【2】。在Linux系统下定义了如下用于开放主机控制器的数据结构。
Struct usb_operation sohci_device_operations={
sohci_alloc_dev,
sohci_free_dev,
sohci_get_current_frame_number,
sohci_submit_urb,
sohci_unlink_urb
};
其中:
sohci_alloc_dev用来分配USB设备资源。
sohci_free_dev用来收回USB设备资源。
sohci_get_current_frame_number用来获得当前帧号。
sohci_submit_urb用来提交URB请求快。
sohci_unlink_urb用来撤销URB请求块。
2) Linux系统中,USBD通过定义一组宏、数据结构和函数来抽象出所有硬件或者设备具有依赖关系的部分。USBD中主要有四个数据结构,分别是:
usb_device保存一个USB设备的信息。
usb_bus保存一个USB总线系统的信息。
usb_driver保存客户驱动信息,包括驱动名称,以及驱动提供给USB内核使用的函数指针等。
urb是进行USB通信的数据结构,USBD通过URB在USB设备类驱动和USBD、USBD和HCD间进行数据传输。
3) USB摄像头驱动程序需要做的第一件事情就是在USB子系统里注册,包括该驱动程序支持哪些设备,当被支持的设备从总线插入或拔出时,会有哪些动作等,所有这些信息通过usb_driver的形式传送到USBD中,具体实现如下:
static struct usb_driver cam_driver={
.name="cam_video",
.probe=cam_probe,
.disconnect:cam_disconnect,
.id_table:cam_ids,
};
cam_video是客户端驱动程序的字符串名称;cam_probe则指向USB驱动程序的探测函数指针;cam_ids列表包含了一系列该驱动程序可以支持的所有不同类型的USB设备,如没有设置该列表,则该驱动程序中的探测回调函数不会被调用[3]。
3 基于relay的Linux系统USB视频驱动
3.1 relay技术基本原理
Relay是一种从Linux内核到用户空间的高效数据传输技术。通过用户定义的relay通道,内核空间的程序能够高效、可靠、便捷地将数据传输到用户空间。Relay特别适用于内核空间有大量数据需要传输到用户空间的情形,它提供一种机制使得内核空间的程序能够通过用户定义的relay通道将大量数据高效的传输到用户空间。
一个relay通道由一组和CPU一一对应的内核缓冲区组成。这些缓冲区又被称为relay缓冲区,其中的每一个在用户空间都用一个常规文件来表示,这被叫做relay文件。Relay并不关心数据的格式和内容,这些完全依赖于使用relay的用户程序。Relay的目的是提供一个足够简单的接口,从而使得基本操作尽可能的高效[4]。
Relay将数据的读和写分离,使得突发性大量数据写入的时候,不需要受限于用户空间相对较慢的读取速度,从而大大提高了效率。Relay作为写入和读取的桥梁,也就是将内核用户写入的数据缓存并转发给用户空间的程序。Relay提供了两大类主要API包括面向用户空间和面向内核空间,面向用户空间的API:
open()允许用户打开一个已经存在的通道缓冲区。
mmap()使通道缓冲区被映射到位于用户空间的调用者的地址空间。
read()读取通道缓冲区的内容。
endfile()将数据从通道缓冲区传输到一个输出文件描述符。
poll()支持 POLLIN/POLLRDNORM/POLLERR信号。
close()将通道缓冲区的引用数减1。
面向内核空间的API为:
relay_open()创建一个relay通道,包括创建每个CPU对应的relay缓冲区。
relay_close()关闭一个relay通道,包括释放所有的relay缓冲区,在此之前会调用relay_switch()来处理这些relay缓冲区以保证已读取但是未满的数据不会丢失。
relay_write()将数据写入到当前CPU对应的relay缓冲区内。
relay_reserve()在relay通道中保留一块连续的区域来留给未来的写入操作。
3.2 Relay技术可靠性分析
整个摄像头图像采集系统由前端高清视频采集和后台处理过程组成。前端高清视频采集的可靠性主要由摄像头设备中的图像处理器性能决定的,目前市场绝大多数高清摄像头都可以满足系统要求。我们通过创建数据缓存多通道和增加缓存大小的方法来提高系统的可靠性,从而减少丢帧现象,从一定程度上提成了高清摄像头的工作的可靠性。
4 总结
本文在ARM体系结构平台下对USB摄像头设备驱动的基本原理进行了说明,并介绍了一种新型的驱动改进方法,通过提高内核空间和用户空间的数据传输速度,从而提高整个摄像头设备的数据采集速度,使得改进方案可行高效。
参考文献
【1】 冯伟,王博编著【M】.北京:中国电力出版社,2008.
【2】 商斌.Linux设备驱动开发入门与编程实践【M】.北京:电子工业出版社,2009.
【3】 畅卫功.嵌入式Linux中USB摄像头驱动的研究【J】.嵌入式软件应用,2008.
【4】 季春志,褚伟.Linux平台下高分辨率摄像头设备USB驱动的研究与改进【J】.合肥工业大学学报,2009.