第36卷
VoL36
第9期
No.9
计 算 机 工 程
Computer Engineering
2010年 5月
M ay 2010
·开发研究与设计技术· 文章编号:1000—_3428(2o10)o9—__0282—03 文献标识码:A 中圈分类号:TP301.6
嵌入式 Linux下 USB摄像头驱动实现
宋丽华,高 珂
(北方工业大学信息工程学院,北京 100144)
摘 要:在嵌入式系统中开发USB摄像头驱动需要充分利用USB总线带宽并保证内存与摄像头之间数据的高速稳定交换。为满足该要求,
参考开源项目GsPcA/sPcA5xx,采纳 Linux内核建议并遵循 Video4Linux
标准
excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载
,提出双 URB分配策略和 MMAP内存映射机制以最大限
度地提高视频采集速度。在 S3C2440AL_ARM开发平台上设计并实现 USB摄像头的嵌入式 Linux设备驱动,对该驱动程序进行功能验证
和性能
分析
定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析
。
关健词:嵌入式 Linux;USB摄像头;双 URB策略;MMAP映射机制
Implementation of USB Camera Driv e
Under Embedded Linux
SONG Lbhua,GAO Ke
(College ofInformation Engineering,North China University ofTechnology,Beijing 100144)
[Abstract]In the design and development of USB camera drive based on embedded system,it should make full use of USB bus bandwidth and
ensure a high and stable data transfer speed between memo~ and peripherals.In order to meet the real-time video capturing requirements,reference
is made to open-source projects GSPCA/SPCA5xx,recommendation of Linux kernel is adopted,and using double—URB strategy and MMAP
m~ pmg mechanism to maximize the video capturing speed,eventually realizes this USB camera drive in line with Video4Linux on the
$3C2440AL
—
ARM development platform and provides a functional verification and perform ance analysis.
[Key words]embedded Linux;USB camera;double—URB strategy;MMAP mapping mechanism
1 概述
随着 CMOS和 CCD图像传感器技术的迅速发展,USB
摄像头由于性价比高、接口统一和支持多种高质量图像输出,
因此应用十分广泛,如可视电话、视频会议、视频传感器和
手持设备。在此类嵌入式设备中,基于 ARM结构的高性能、
低功耗、低成本的处理器已成为嵌入式解决方案的 RISC标
准。但嵌入式系统中支持 USB摄像头的驱动很少,因此,研
究和开发USB摄像头驱动具有较高的实用价值和现实意义。
USB摄像头由传感器芯片和图像处理芯片组成。传感器
芯片负责图像采集,图像处理芯片负责压缩及与主机的通信。
本文使用的摄像头传感器芯片为HYUNDAI公司的HV7131C
CMOS芯片,图像处理芯片为 Vimicro公司的 ZC0301系列
芯片。开发平台为 EMBEDSKY 公司的 SKY2440开发板
(Samsung$3C2440AL ARM9芯片,主频 400 MHz),操作系
统为Linux 2.6.13,交叉编译环境为gcc一3.4.1一glibc一2.33。
2 USB驱动程序系统架构
2.1 USB驱动层结构
Linux内核主要支持2种类型的USB驱动程序:主机侧
(host)驱动和设备侧(gadget)驱动 。主机侧驱动负责控制
插入其中的 USB设备,而设备侧驱动控制该设备如何与主机
通信 】。
USB驱动层如图 1所示,在主机侧中,最底层是 USB
主控制器驱动,中间层为 USB核心层,最上层为 USB设备
驱动层。通常,内核本身带有前面 2层驱动程序,而开发者
只需完成 USB设备驱动层的开发工作。
一 282一
JL
蚪I 设备功能层
1广
JL
USBGa~ethi' l USB核心层
申 l usB设备 l USB总线接口 l控制器驱动l —__j 一
l usB主控制器 ==== >lusB设备控制器l
图1 USB驱动层鳍糟
2.2 主机侧与设备侧
设备侧非常复杂,生产商按照USB协议进行实现,Linux
内核提供的USB核心处理了大部分的复杂性。主机侧驱动开
发关心的是设备侧的构成,包括配置、接El和端点,以及 USB
主机侧驱动如何绑定到 USB设备接口上。按照协议【jj,USB
是一种 “单主方式”的实现,主机轮询各种不同的外围设备,
基金项目:国家 “十一五”科技支撑计划基金资助重点项 目(2009
BAI71B02);北京市属高等学校人才强教计划基金资助项目(PHR
201007121);北方工业大学重点研究基金资助项 目(NCUT2009
0106)
作者简介:宋丽华(1979一),女,博士 ,主研方向:嵌入式系统,
网络通信协议 ;高 珂,硕士研究生
收稿日期:2009-12—04 E-mail:slh2g@126.com
一 个 USB设备不能主动发送数据。
2.3 驱动模块结构
每个 USB设备 由一个 USB模块驱动,但设备本身可能
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
现为一个字符设备,如 USB摄像头。因此,对于一个 USB
摄像头来说,它首先是 “USB”的,其次是 “视频类”的。
USB 模块与 Linux 内核 用于支持视频设备的附加层
Video4Linux一起工作。Video4Linux驱动程序组划分出了一
个通用模块,它导出的符号可供与具体硬件相关的驱动程序
使用L4。J。
3 关键模块的设计与实现
3.1 重要的数据结构
所有 USB驱动程序都必须创建的结构体是 struct usb
—
driver。创建一个有效的usb—driver只要初始化以下 5个字段:
static struct usb
—
driver spca5xx
— driver={
.owner=THIS
—
MODULE,
.name=”gspca”.
.id
—
table=device
—
table,
.probe=spca5xx~probe,
.disconnect。二spca5xx
— disconnect};
其中,id
— table是指向struct usb— device— id表的指针,该表包
含了驱动程序可以支持的所有不同类型的 USB设备。probe
是指向驱动程序中探测函数的指针,当 USB设备在总线上
加电启动后,USB将检测与之匹配的驱动程序,如果找到,
调用 spca5xx_probeO函数,该函数主要完成初始化工作,包
括:配置设备信息以及连接摄像头操作函数;初始化 zc301
桥芯片和解码器信息;创建设备驱动文件系统等。
感光芯片和桥芯片的寄存器设置与具体硬件相关,初始
化细节可参阅相关硬件的datasheet。disconnect是指向断开函
数的指针,当USB设备从系统中移除或者驱动程序卸载时,
将调用 spca5xx
— disconnect()函数,主要完成内存释放和资源
回收工作。struct usb— spca50x是本驱动中非常重要的结构体,
几乎所有的函数调用都会用到它。
struct usb
— spca50x{
struct video
—
device vdev;
struct usb
—
device dev;
struct tasklet
—
struct spea5xx
_
tasklet;
struct dec
—
data maindecode;
unsigned char iface;
int alt;
int epadr;
int customid;
struct spca50x
— frame frame[2];
struct spca50x
—
sbuf[2];
⋯ };
usb
—
spca50x是 USB摄像头驱动的 “上下文”结构,包
含了 “当前”摄像头的硬件配置信息,包括:桥芯片和感光
芯片信息,来自设备侧的 “配置”、“接口”、“端点”信息,
主要编解码信息,与摄像头相关的操作函数及帧缓冲信息。
硬件设备在 Linux系统中是作为文件而存在的,struct
file
— operations结构体实现了 “设备文件”与在 “设备文件上
的操作”的连接。
static struct file
— operations spca5xx fops={
.owner THIS
—
MODULE,
.open spca5xx
— open,
.release=spca5xx
—
close,
.read spca5xx
—
read,
.mmap spca5xx
— mm ap,
.ioctl=spca5xx
—
ioctl,
.1lseek=no
— tlseek,};
在上述结构体中,spca5xx
—
open()函数是对设备文件执行
的第一个操作,所有客户端程序对设备的访问都将从它开始。
该函数主要完成初始化 usb—spca50x中的各个缓冲区工作、
寻找匹配的iso端点、开始同步传输等工作。spca5xx—close()
用于释放 file结构,注意并非每次关闭设备时都会被调用,
只要 file结构被共享 ,spca5xx— close()就会等到所有的副本都
关闭之后才会得到调用 J。spca5xx
_
read0用于从设备中读取
数据。spca5xx
—
mmapO用于请求将设备内存映射到进程地址
空间,此函数是 MMAP 内存映射机制的主要实现函数。
spca5xx
— ioctl0用于执行设备相关的特定命令。
3.2 双 USB请求块及MMAP映射
Linux内核通过 URBUSB请求块(USB Request Block,
URB)与所有的USB设备通信。该请求块使用 struct urb结构
体表示。根据 USB协议 ,URB的传输有 4种:控制,中断,
等时和批量。对于 USB摄像头,USB传输方式必须为等时传
输l,J。驱动程序对 URB的分配和提交策略及核态空间和用户
空间转换开销是影响 USB摄像头传输性能的 2个关键因
素 j。本文采用的双URB策略和MMAP内存映射机制可以
最大限度地提高视频采集速度。
3.2.1 双 URB策略
驱动程序可以为单个端点分配多个 URB,也可以一个
URB被多个端点重用。关于 URB的分配策略,Linux内核是
这么建议的:当URB被驱动提交后,通常都在排队。对于音
频或视频之类数据流设备,为了能以固定的速率传输,驱动
程序在安排传输的URB时,至少应该是双缓冲的,并且在回
调函数中应明确地重新提交该URB。主要代码如下:
int gspca
_
init
_
transfert(struct usb
—
spca50x spca50x)
{⋯
for(n=0;n<2;n++){
urb=usb
—
alloc
— urb(FRAMES—PER DESC,GFP—KERNEL));
spca50x一>sbuRn].data usb—buffer_ alloc(spca50x->dev,psize
FRAMES
—
PER
_
DESC,
GFP KERNEL,&urb一>transfer
— dma);
urb一>pipe= usb
—
rcVisocpipe(spca50x->dev,ep一>desc.bEndpoint
Address);
urb一>transfer
—
flags:URB
—
ISO
—
ASAP l URB—NO—TRANSFER—
DMA
—
M AP;
urb->interval ep一>desc.blnterval;
urb一>transfer buffer spca50x->sbuf[n].data;
urb->complete:spca50x
—
isoc
—
irq;
⋯ )
for(n=0;n<2;n++)
usb submit
—
urb(spca50x->sbuf[n].urb,GFP
—
KERNEL);
}
首先调用 usb
—
alloc
_
urb0分配 2个 URB,由于等时 URB
没有初始化函数,因此此处必须显示初始化。调用宏 usb
—
rcvisopipe0设置接收 URB的设备端点地址;URB
—
ISO
—
ASAP
IURB—NO—TRANSFER—DMA—MAP用于指定 URB传输方式
为iso等时传输,并采用DMA方式以提高传输速度;transfer
buffer指定 DMA关联数据的缓冲区地址;最后调用 usb
submit
—
urb分别提交这 2个 URB。
spca50x
—
isoc
—
irq为指向该 URB生命周期结束后的回调
函数地址,它主要完成一帧数据获取和解码工作,并完成重
一 283—
新提交该 URB的任务。主要代码如下:
void spca50x
— isoc irq(struct urb ,struct pt regs )
{if(spca50x->curframe>=0、
/ 解码 将数据传输到缓冲区中 /
len=spca50x
—
m ove
— data(spca50x,urb);
else if(waitqueue actiVe(&spca50x->wq))
wake
— up interrupt|ble(&spca50x->wq);
urb一>dev: spca50x一>dev;
urb->status=0:
usb
—
submit
—
urb(urb,GFP
— ATOMIC);
⋯ }
3 2.2 MMAP内存映射机制
在 Linux系统中,文件操作通常是由 mad,write系统调
用完成。这些系统调用在驱动中的解决方法是用 copy— to—
user(),copy_from—user()等函数在核态、用户态空间互相拷
贝,如图 2所示。但对大量的图像数据来说,这种频繁互拷
会增加系统开销,特别对资源相对较少的嵌入式系统来说更
加明显。
内核空问 用户空间
(不可替换) (可替换)
图 2 read系统调用
MMAP内存映射可以提供给用户直接访问设备内存的
能力,以减少系统开销。主要代码如下:
ssize
—
t spca5xx
— mmap(struct file ,struct vm—area struct )
{._·
down
— interruptible(&spca50x一>lock);
page。。kvirt
—
to
— pa(pos);
if (remap_pfn range(vma, start, page >> PAGE
~
SHIFT,
PAGE SIZE,PAGE
~ SHARED)){
up(&spca50x一>lock);
return—EAGAIN;
}}
在 spca5xx—mmap()~数中,首先将驱动中帧缓存地址转
换成页,然后调用remap_page—range()函数将其逐页映射到用
户空间中,如图3所示。
一 284一
图3 MMAP映射机制
4 测试与性能分析
4.1 功能测试
嵌入式驱动测试平台见图4,由ARM9 CPU、64 MB Flash
存储器、3.5英寸TFTLCD屏幕以及2个主机端USB接口组
成 ,可以支持低速和全速的 USB设备。
图4 USB摄像头驱动测试平台
驱动程序可以快速正确地完成 CMOS传感器探测、桥芯
片设置和初始化。运行客户端软件后,顺利出图,视频显示
平滑流畅,可连续工作数十个小时,稳定可靠。
4.2 性能分析
搭建好 ARM—GCC交叉编译环境 后,分别测试不同时
间间隔下摄像头的帧速情况,测试参数和结果见表 1。测试
平台为 400 MHzARM9处理器。由于嵌入式系统限制,因此
在 320x240分辨率下视频采集平均帧速大于 1 1 f/s,能够满足
大多数嵌入式系统的需求。
表 1 帧速测试数据
5 结束语
本文介绍了 USB 驱动的层次结构以及主机侧和设备侧
的关系,阐述了开发符合Video4Linux标准的USB摄像头驱
动的方法。根据嵌入式系统的视频实时性要求 ,采用了双
URB分配策略和MMAP内存映射机制,最大限度地提高了
视频采集速度,实际测试表明其具有良好的性能和可靠性。
这对其他平台的相关驱动开发工作也具有一定的指导意义。
参考文献
[1]魏永明,耿 岳,钟
书
关于书的成语关于读书的排比句社区图书漂流公约怎么写关于读书的小报汉书pdf
毅.Linux设备驱动程序[M].3版.北京:
中国电力出版社,2005.
[2]宋宝华 Linux设备驱动开发详解【M].北京:人民邮电出版社,
2008.
[3]Compaq,Intel,Microsoft,NEC.Revision l_1 Universal Serial Bus
Specification[Z].1998.
[4]SchimekM H,Dirks B,VerkuilH,et a1.Videofor Linux TwoAPI
Specification Reversion O.24[EB/OL].(2009-09—03).http://v412
spec.bytesex.org/v412spec/v412.pdf.
[5]Cox A.Video4Linux Programming[EB/OL].(2003-1 1-29).http://
kernelbook.sourceforge.net/videobook.htm1.
[6]Fliegl D.Programming Guide for Linux USB Device Drivers[Z].
(2000—03一O1).http:f sb.CS.tum.eduMownload/usbdoc.
[7】杨 伟,刘 强,顾 新.Linux下USB设备驱动研究与开发[J1_
计算机工程,2006,32(1 9):283—285.
[8]刘 飞,张曦煌.基于嵌入式平台的 USB摄像头驱动程序的实
现『J].计算机工程与设计,2008,29(8):1994—1996.
[9]Yaghmour K,Masters J,Ben—Yossef G et a1.Building Embedded
Linux Systems[M].2nd ed.[S.1.]:O’Reilly Media,Inc.,2008.
编辑 张正兴