今年上半年我对市场常见的vimicro 摄像头移植了Linux下的驱动至在研的一款嵌入式开发板,开发环境为:
OS:Linux2.6.9
Compile:cross 3.3.2
CPU:Intel PXA270
Camera Type :Vimicro ZC301P +HV7131R
使用的驱动源码基于*软件spca5xx。基于源码作了些小改动。记录一下。
Linux下的USB驱动架构
Linux下完整的USB驱动程序必须包括3个模块:USB core,USB 主控制器驱动,USB设备驱动。三者的关系如下:
Linux下USB摄像头驱动开发
其中:
Linux Core封装了支持USB主控制器和USB设备驱动的API,通过一系列的数据结构、宏、函数来抽象化设备硬件并掩蔽硬件具体细节,使得Linux系统对USB设备的访问采用如同一般文件访问类似的接口函数,如此实现了硬件无关。“设备即是文件”。
USB HC(Host Controller)全面负责主机端对USB的信息传输分工,对下注册功能和相关数据结构;对上提供了设备驱动与USB Core数据传输的桥梁。USB上的实时流数据传输通常通过URB(USB Request Block)的数据结构实现,每一次数据传输中,设备驱动建立URB,提交给USB HC,USB HC负责完成此次与设备端的URB交互。
USB驱动程序的结构
struct usb_driver spca5xx_driver
struct video_device spca50x_template
struct file_operations spca5xx_fops
模块初始化与卸载
spca5xx_init()模块初始化;spca5xx_disconnect()模块卸载;spca5xx_probe() 物理设备查找、匹配、配置,并向内核注册video设备。
系统调用接口
spca5xx_open()完成设备的打开和初始化,并初始化解码器模块,spca5xx_close()完成设备的关闭;
spca5xx_read()完成数据的读取,其主要的工作就是将数据由内核空间传送到进程用户空间;
spca5xx_mmap()实现将设备内存映射到用户进程的地址空间的功能;
spca5xx_ioctl()实现文件信息的获取功能。
数据传输
spca50x_reg_write
摄像头数据传输过程
USB总线上信息传输类型可分成控制、中断、等时、成块四种:其中控制型主要用于设备的“配置”与控制;中断型主要用于主机对USB设备的周期性查询;实时性使用与实时的音视频信号传输;成块型用于信息量大,没有很强的时间要求,但要求可靠传递的应用。对摄像头而言,通常采用的是实时传输。USB设备端提供若干通信端口(port),主机与端口间建立起逻辑上的通信管道,进行数据传输。在摄像头的设备初始化阶段,主机与0号端口通信,驱动程序检测摄像头型号和所有端口信息;进入数据传输阶段,主机与探测到的实时输入端口建立通信管道,实时回传摄像头拍摄到的图像数据。
USB主机控制器把每秒总线时间分成1024个固定大小的frame,每个frame占据1ms的时间带宽并以此为时间单位递增,同时对应一个等时交互队列。主机负责把USB总线上回传的等时图像数据流量分配给各frame,USB主机控制器每一秒钟扫描一遍所有frame,依次读入各frame携带的等时数据包至内核缓冲区中。应用程序通过内存映射,在用户空间直接读取内核缓冲区内容,存入Linux显存帧缓冲(framebuffer)中,从而在显示屏中出现图像数据。
笔者的实验摄像头为Vimicro ZC301P,sensor是HV7131R,驱动程序中每秒钟进行2次URB传输,每个URB携带16个1023字节的数据包,这样每秒钟所能得到的图像数据大小为32Kbyte。对RGB565、大小320×240、16位颜色深度的图像格式,在PXA270处理器的嵌入式开发板上测试,帧速达到每秒17帧,完全满足嵌入式网络实时视频会议的需要。
Linux下USB摄像头驱动开发
提高摄像头工作质量的几种方法
双URB
双帧缓冲
V4L协议改进