百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

基于FIMC接口的CMOS摄像头驱动分析与设计

haoteby 2025-02-16 20:56 6 浏览

摘 要: 目前的嵌入式系统中,USB摄像头使用比较普遍,但其应用会受到传输速度的限制。本文采用一款高速CMOS摄像头,其驱动利用S3C6410内置的FIMC接口技术,采用DMA和ping-pong缓冲池机制,结合内存共享策略,有效提高了传输速率并充分利用了有限的内存资源。深入分析了该驱动的原理和实现细节,并提出了改进设计,最终应用在嵌入式图像采集系统中,能够为应用程序提供高清、高速图像。

0 引言

嵌入式系统具有体积小、功耗低和成本低等天然性的优势,因而得到广泛应用,甚至在许多场合得以取代传统工控机,比如视频监控系统和安防系统。目前嵌入式系统中最常用、嵌入式Linux内核支持最广泛的是USB摄像头。然而受到嵌入式处理器性能的限制,USB摄像头接口的传输速率限制为12 Mb/s,对于常用的640×480分辨率的YUV图像,其最高帧率为3.75帧/s,无法满足实时性要求。因此,基于CMOS图像传感器的高速摄像头正在被推广应用。CMOS高速摄像头可以为嵌入式系统实时地提供高分辨率图像[1],很适合进行识别、跟踪等实时图像处理作业。采集640×480的VGA图像,CMOS摄像头最高帧率可以达到30帧/s。基于OV系列的CMOS摄像头应用很多,比如监控[2]和人数检测[3]都使用了OmniVision公司的OV9650摄像头。参考文献[4]介绍了基于S3C6410和OV9650的V4L2图像采集系统的设计,参考文献[5]和[6]介绍了基于S3C2440中相机接口(Camera Interface,CAMIF)的OV9650摄像头驱动设计。

本文涉及的S3C6410[7]的完全交互式移动相机(Fully Integrated Mobile Camera,FIMC)接口是由S3C2440的CAMIF发展而来,但是目前关于FIMC驱动的原理分析和设计实现的文献仍然很少。本文对OV9650及FIMC接口驱动的原理和实现细节作了深入分析,并对原有驱动进行了改进,使之适用于视线检测系统。

本文首先分析摄像头驱动所依赖的硬件接口,然后重点分析其驱动软件设计原理和实现细节,并给出改进设计,最后对下一步的改进工作提出展望。

1 摄像头驱动系统的硬件接口

本文所涉及的驱动系统基于OK6410嵌入式开发板,采用S3C6410作为中央处理器。S3C6410内置的FIMC接口为开发板与CMOS摄像头的连接提供了可靠便利的接口。该驱动系统的硬件结构如图1所示。

如图1,摄像头为130万像素、20引脚的OV9650,通过FIMC接口接入S3C6410。OV9650与FIMC对应管脚连接如图2所示。其中,CAMYDATA7~CAMYDATA0负责图像数据传输,CAMRSTN为复位信号,CAMSYNC为同步信号。OV9650的配置接口为SCCB接口。由于S3C6410没有专用的SCCB接口,因此使用GPB6、GPB5分别模拟SIO_D、SIO_C,即数据和时钟信号。SCCB协议与I2C协议的区别仅在于设备地址不同,因此,驱动中直接用I2C代替。

2 摄像头驱动系统软件

2.1 Linux驱动模型

在Linux操作系统中,设备驱动为应用程序提供访问接口,屏蔽了底层硬件细节。从Linux2.6内核开始,设备被驱动和内核映射为文件,应用程序可以像访问普通文件一样访问这些挂载在/dev目录下的设备,访问接口被定义在驱动中file_operations结构体对象内。每一个接口函数其实都是一个系统调用,其具体实现由驱动程序完成。Linux内核中驱动模型包括总线(Bus)、设备(Device)和驱动(Driver)三个要素,即设备和驱动作为对象挂载在相同的总线上,由总线对设备和驱动进行一一匹配。

Linux驱动模型将所有外设分为字符设备、块设备和网络设备三种。摄像头属于字符设备,其驱动遵循着字符设备驱动的框架,包括设备号、设备注册和最重要的文件操作函数的实现。特别地,针对摄像头设备,V4L2[8]接口为驱动程序提供了一套完备的文件操作标准接口和缓冲池管理策略,目前大多数的摄像头驱动都遵循V4L2接口标准。

2.2 V4L2驱动

V4L2是Video For Linux 2的简称,是Linux内核中关于视频设备的虚拟驱动,它不涉及硬件,仅仅为应用程序提供一套完备的操作接口,这些接口的具体实现都由遵守V4L2协议的驱动程序来完成,比如常用的ioctl接口。V4L2的存在极大地方便了应用程序的编写,使得同一套应用程序可以应用于多种摄像头。V4L2层次示意图如图3。

基于V4L2的基本图像采集流程如下:

(1)打开视频设备文件(一般为dev/video0),初始化采集格式等参数;

(2)在内核空间申请若干视频采集的帧缓冲区;

(3)地址映射,使得用户空间的应用程序对帧缓冲区有读写权限;

(4)帧缓冲区在视频采集输入队列排队,并启动视频采集;

(5)从缓冲队列取出帧缓冲区,获得数据进行处理;

(6)处理完,将帧缓冲区重新放入视频采集输入队列,循环往复采集连续视频数据。

V4L2为图像采集程序维持一个环形缓冲队列,如图4。该缓冲区队列为ping-pong操作模式,应用程序需要使用的图像数据会通过ioctl接口使对应的缓冲区出队,缓冲队列的其余缓冲区继续接收图像数据,并在一个循环之后覆盖掉原有的缓冲区数据,以保证缓冲区队列中图像数据的实时性。

2.3 关键模块驱动的设计与实现

OV9650通过FIMC接口与S3C6410连接,FIMC为输入图像进行格式转换、剪裁等预处理,最后传输到内核中开辟的图像缓冲区,供应用程序读取。摄像头驱动分为两个部分:OV9650驱动和FIMC驱动。

2.3.1 OV9650驱动

OV9650驱动的主要作用是挂载驱动和配置寄存器,其中.h文件定义了寄存器配置数据,并由.c文件调用。由于FIMC接口的存在,应用程序不需要直接操作OV9650摄像头,因此OV9650驱动不需要为应用程序提供访问接口,不需要定义file_operations结构体。

从Mach-smdk6410.c文件中可以知道,内核在启动时,将OV9650作为一个I2C设备挂载到内核树的I2C总线上。之后内核找到OV9650驱动,执行其入口函数——ov965x_init,将OV9650.c文件中定义的i2c_driver驱动对象也添加到内核树中,最后由总线根据其name将设备和驱动进行匹配。在匹配工作完成之后,内核会调用其探测函数ov965x_probe,将OV9650的配置数据传递给FIMC驱动中的一个全局参数s3c_fimc,用于配置FIMC寄存器,然后,初始化OV9650寄存器。

2.3.2 FIMC驱动

FIMC是s3c6410芯片为摄像头设备提供的一个接口,用来对所采集的图像进行裁剪、放缩等预处理。FIMC为输出图像提供两个DMA通道:preivew通道和codec通道,并为每个通道分配四个ping-pong缓冲区,以提高图像传输速度和内存使用效率。如图5所示。

FIMC接收OV9650图像数据,并向上传递。因此,FIMC驱动最重要的作用就是向应用层提供标准的操作接口,供应用程序使用。

FIMC驱动主要包括三个部分:(1)platform驱动注册;(2)file_operations接口定义;(3)V4L2接口实现。

2.3.2.1 platform驱动注册

platform是Linux 2.6内核所引进的一种新型驱动管理和注册机制。目前Linux内核中大部分的设备驱动都采用platform架构。在platform架构中,设备用platform_device表示,驱动用platform_driver表示。Linux platform driver机制与传统的device driver机制(通过drivce_register函数进行注册)相比,一个十分明显的优势在于platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序使用这些资源时通过platform device提供的标准接口进行申请并使用,提高了驱动和资源管理的独立性,并且拥有较好的可移植性和安全性(这些标准接口是安全的)。

FIMC驱动入口函数是s3c_fimc_core.c中的s3c_fimc_register,该函数将platform_driver类型的s3c_fimc_driver挂载到platform虚拟总线。由mach-smdk6410.c文件可知,内核启动时将所有platform_device(包括s3c_device_fimc0)挂载到platform总线。platform总线的match函数将device和driver匹配之后,会自动调用s3c_fimc_driver中指定的probe函数探测设备、申请内存资源、申请中断等,并将最终形成的platform_device类型数据保存到内核中,供后续使用。最后,调用video_register_device函数将对应的video_device注册到内核。

video_device结构体包括fops、ioctl_ops、release、name、vf_type几个成员变量,其中,最重要的是file_operations类型的fops和v4l2_ioctl_ops类型的ioctl_ops,分别实现文件操作接口和V4L2接口。

2.3.2.2 file_operations接口

FIMC驱动遵循V4L2接口标准,其file_operations接口定义如下:

static const struct v4l2_file_operations s3c_fimc_fops=

{

.owner=THIS_MODULE,

.open=s3c_fimc_open,

.release=s3c_fimc_release,

.unlocked_ioctl=video_ioctl2,

.read=s3c_fimc_read,

.write=s3c_fimc_write,

.mmap=s3c_fimc_mmap,

.poll=s3c_fimc_poll,

};

当应用程序通过系统调用open打开摄像头设备时,内核会最终找到s3c_fimc_open函数来打开摄像头。

应用程序通过read获取图像数据,该函数通过copy_to_user将内核空间所申请缓冲区中图像数据拷贝到用户空间中开辟的图像数据区。该函数没有充分利用FIMC接口提供的ping-pong缓冲区,按字进行拷贝(memcpy),十分耗时。

mmap函数将内核空间中申请到的图像缓冲区映射到应用程序所在的用户空间,这样,应用程序申请到的buffer将指向内核空间的图像缓冲区,应用程序可以(不拷贝)直接对图像进行操作。该函数配合V4L2标准中的环形缓冲区队列,节省了应用程序读取图像数据所消耗的时间。

2.3.2.3 V4L2接口

V4L2接口功能强大,为应用程序提供了完备的操作接口,包括设置格式、帧率、白平衡、曝光模式、申请缓冲区、取数据、剪裁图像等。此处仅列举几个重要接口。

const struct v4l2_ioctl_ops s3c_fimc_v4l2_ops=

{

.vidioc_s_fmt_vid_cap=

s3c_fimc_v4l2_s_fmt_vid_cap,

.vidioc_s_ctrl=s3c_fimc_v4l2_s_ctrl,

.vidioc_streamon=s3c_fimc_v4l2_streamon,

.vidioc_streamoff=s3c_fimc_v4l2_streamoff,

.vidioc_reqbufs=s3c_fimc_v4l2_reqbufs,

.vidioc_querybuf=s3c_fimc_v4l2_querybuf,

.vidioc_qbuf=s3c_fimc_v4l2_qbuf,

.vidioc_dqbuf=s3c_fimc_v4l2_dqbuf,

.vidioc_s_parm=s3c_fimc_v4l2_s_parm,

};

应用程序通过ioctl接口使用这些函数,比如ioctl(fd,VIDIOC_S_FMT,&fmt)用来设置图像格式,此时V4L2会将VIDIOC_S_FMT命令映射为
s3c_fimc_v4l2_s_fmt_vid_cap函数,并将fmt指定的格式告知FIMC接口,FIMC会将OV9650传递过来的原始图像数据经过类型转换传递回应用程序。

s3c_fimc_v4l2_reqbufs用于申请图像缓冲区,该函数为应用程序在内核空间开辟ping-pong缓冲区。s3c_fimc_v4l2_qbuf函数将缓冲区组成环形缓冲队列,当应用程序需要调用图像数据时,使用s3c_fimc_v4l2_dqbuf使指定的缓冲区出队,缓冲区在出队期间,不会被新来的图像数据覆盖,新到的图像数据会被传送到环形队列中指定缓冲区的下一个缓冲区。由于FIMC控制器为P通道和C通道分别开辟了4个缓冲区,在内核初始化时已经申请到,因此FIMC驱动中并不需要再重新申请。

2.4 驱动错误分析与改进设计

在驱动主体框架正确的情况下,开发板(OK6410A)自带的驱动并不能直接使用。同一套V4L2图像采集程序可以应用在USB摄像头上,应用在OV9650上却无法获得图像,并且先后报出两个错误:

(1)tx or ty is lower than zero and this is a invalid target size

(2)VIDIOC_QUERYBUF error

上述错误出现之后,LCD屏幕没有图像,紧接着串口会显示display 0,表示程序无法读出图像数据,导致程序终止。下面分别对两个错误进行分析并改进。

2.4.1 错误1的分析与改进

由于ov9650驱动仅仅将ov9650设备注册进入系统,并没有其他处理,因此ov965x.h和ov965x.c两个文件不用修改和调试。

FIMC采用DMA通道向内核缓冲区传送数据,需要专门的函数打开DMA输出通道。通过函数跟踪得知,原有
s3c_fimc_v4l2_s_fmt_vid_cap函数并没有打开输出DMA通道,因此CMOS摄像头的数据并没有传送到内核开辟的缓冲区中,导致V4L2也无法获取这些图像数据。而且由于没有打开输出DMA通道,out_frame参数也没有设置,导致其对应的尺寸参数也为0,所以报出第一个错误。


s3c_fimc_v4l2_s_fmt_vid_cap中通过调用s3c_fimc_ set_output_frame函数,打开输出DMA通道,解决了该问题。

2.4.2 错误2的分析与改进

该错误由s3c_fimc_v4l2_querybuf函数报出,报错条件是:

if(b->type!=V4L2_BUF_TYPE_VIDEO_OVERLAY&&b

->type!=V4L2_BUF_TYPE_VIDEO_CAPTURE)

该函数用于配置所申请图像缓冲区的长度、偏移量等属性,从而使所申请的环形队列缓冲区生效。由于本系统中摄像头仅用于图像捕获,因此在该函数开头可以将b->type进行强制设定,即:b->type=V4L2_BUF_ TYPE_VIDEO_CAPTURE,从而解决图像缓冲区申请的问题,该错误不再出现。

至此,修正后的FIMC驱动程序可以正常工作,图像数据得以传输到内核中为FIMC驱动开辟的图像缓冲区,应用程序可以通过read系统调用或者ioctl的VIDIOC_DQBUF命令获取图像数据。

图像捕获效果如图6所示。

3 结论

本文深入分析了CMOS摄像头驱动的原理和实现细节。FIMC驱动向内核申请四个ping-pong缓冲区,通过DMA方式传入图像数据,提高了图像数据传输速率。内存共享策略使得应用程序在访问图像缓冲区时免去了内存拷贝的步骤,大大缩减了图像获取的时间。但是目前的FIMC驱动在缓冲区出队和入队时的保护机制仍不够完善,需要在今后的工作当中对这一部分不断进行优化。

参考文献

[1] OminiVision Technologies Inc. OV9650 color CMOS SXGA (1.3MegaPixel)camerachipTM implementation guide[EB/OL].(2004-12-07)[2015-01-31]. http://www.ovt.com.

[2] 胡哲光.基于S3C2440与OV9650的嵌入式监控设计[J].轻工机械,2012,30(2):50-53.

[3] 官志平.基于ARM9的Linux系统移植以及在电梯轿厢内人数检测的应用[D].厦门:厦门大学,2014.

[4] Lu Yinli, Yu Hongli, Zhang Pengpeng. The implementation of embedded image acquisition based on V4L2[C]. Proceedings of the 2011 International Conference on Electronics, Communications and Control (ICECC), 2011:549-552.

[5] Zhang Min, Sun Jinguang, Wang Shi. Research and implementation of the CMOS camera device driver based on S3C2440[C]. Proceedings of the 2010 International Conference on Intelligent Computation Technology and Automation (ICICTA),2010:1039-1042.

[6] Kuang Shunming, He Xiaojian. Included in your digital subscription design and application of CMOS device driver based on S3C2440[C]. Proceedings of the 2011 10th International Conference on Electronic Measurement & Instruments (ICEMI),2011:342-343.

[7] Samsung. S3C6410x RISC microprocessor user′s manual (revision 1.2)[EB/OL].(2009-02-13)[2015-01-31]. http://www.samsung.com.

[8] DIRKS B. Video for Linux two API specification (revision 3.9)[EB/OL].(2012-12-03)[2015-01-31]. http://www.linuxtv.org/downloads/v4l-dvb-apis/v4l2spec.html.

相关推荐

Python爬虫进阶教程(二):线程、协程

简介线程线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合和堆栈共同组成。线程的引入减小了程序并发执行时的开销,提高了操作系统的并发性能...

A320-V2500发动机系统FADEC介绍(2)

目的全权数字发动机控制(FADEC)系统在所有飞行和运行阶段提供全范围发动机控制。...

三国志战棋版:玩家“二叔”用这套群DOT在比武中拿下31胜5负

声明:本文首发于今日头条,而后发布于“鼎叔闯三棋”的微信公众号、抖音、哔哩哔哩和小红书平台,如果在其他平台就是抄袭。...

真正的独一无二:Dot One 推出 DNA 定制系列 139英镑起

相信很多人在挑选衣物时有着这样的困扰,综合了性价比、面料等因素后好不容易找到了心仪的款式,还要担心是否会撞衫,不管是擦肩而过的陌生人还是身边的熟人,都令人尴尬。小部分人为此热衷于购买少量的古着或者限量...

崩铁:周年庆福利再升级,老角色加强时间确定,3.xdot体系反转

#埃安UT大一圈高级很多#...

Dotgo推出RBMHub,扩大了CPaaS提供商的覆盖范围和功能

据telecompaper网7月15日报道,用于商业消息传递的RichCommunicationServices(RCS)解决方案的领先提供商Dotgo宣布推出RBMHub。RBMHub的推出扩大了C...

深度解析:快照取消Dot职业的将何去何从

写在前面曾几何时,术士的出现便被冠以dot大师的名头,从远古时期的献祭腐蚀虹吸不如暗牧一个痛,到TBC上满dot=荣誉击杀+1,到wlk接近全暴击的冰晶腐蚀,再到CTM就算了吧MOP的各种变态吸x放...

星穹铁道:抽卡芙卡之前,你必须了解什么是dot!

卡妈终于上线了,可还是有很多人不明白什么是dot伤害,抽了卡妈直接玩起了直伤流,把一个持续伤害的引爆器玩成了打手,卡妈打dot伤害是远高于直伤的,有了卡妈的玩家一直了解dot,不然这卡妈就真被玩成四不...

游戏界的闪耀星辰陨落:悼念知名游戏博主″dotα牛娃″

无尽哀思!在数字时代浪潮中,游戏不仅是消遣娱乐的代名词,更是连接心灵的桥梁,构筑了无数人的青春回忆。在这片浩瀚无垠的游戏宇宙中,有这样一位博主,他以独特的风采、深邃的洞察力和无尽的热情,成为了玩家心中...

直击2017新加坡同性恋聚会Pink Dot,自由爱!

今年的“粉红点”又来啦~这个支持LGBT群体(男女同志、双性恋、跨性别等)群体的活动,从2009年起,已经在新加坡举办8年了!”这个非营利的同性恋权益活动,主要是希望大家了解到,不管一个人的性倾向或...

python-dotenv,一款超级实用处理环境变量python库

python-dotenv,一款超级实用处理环境变量python库python-dotenv概述:...

亚马逊语音助手毫无征兆发笑 诡异至极吓坏用户

来源:新华网美国电商亚马逊7日承诺,将更改名下“亚历克萨”语音系统设置,令它不会莫名发笑,免得吓坏用户。“亚历克萨”是亚马逊开发的语音助手软件,可服从用户语音指令完成对话、播放音乐等任务。依照原来设计...

2022最火英文网名男女生

精选好听英文昵称带翻译1.moveon(离开)2.Monster(怪物)3.Solo吉他手4.Finish.(散场)...

智能家具 RecycleDot 的出现给传统家具厂商带来新的挑战

从可穿戴手环、手表到智能衣服,智能硬件逐步渗透到每一个领域。最近有一对父子MikeSandru和JohnSandru在自家的车库中设计了一款智能家具RecycleDot,给日渐萧条的家具行...

欧洲通信卫星公司 OneWeb 敦促印度DoT尽早批准提供卫星宽带服务

据telecomtalk2月17日报道,欧洲通信卫星公司EutelsatOneWeb近日敦促印度电信部(DoT)尽快批准其在印度部署双地球站网关的计划,以便连接其近地轨道(LEO)全球卫星星座,并...