基于Android系统的Camera模块设计和实现

基于Android系统的Camera模块设计和实现

ID:36790769

大小:2.21 MB

页数:62页

时间:2019-05-15

上传者:U-145848
基于Android系统的Camera模块设计和实现_第1页
基于Android系统的Camera模块设计和实现_第2页
基于Android系统的Camera模块设计和实现_第3页
基于Android系统的Camera模块设计和实现_第4页
基于Android系统的Camera模块设计和实现_第5页
资源描述:

《基于Android系统的Camera模块设计和实现》由会员上传分享,免费在线阅读,更多相关内容在学术论文-天天文库

学位论文创新性声明秉承学校严谨的学风和优良的科学道德,本人声明所呈交的论文是我个人在导师指导下进行的研究工作及取得的研究成果。尽我所知,除了文中特别加以标注和致谢中所罗列的内容以外,论文中不包含其他人已经发表或撰写过的研究成果;也不包含为获得西安电子科技大学或其它教育机构的学位或证书而使用过的材料。与我一同工作的同志对本研究所做的任何贡献均已在论文中做了明确的说明并表示了谢意。申请学位论文与资料若有不实之处,本人承担一切的法律责任。本人签名:关手论文使用授权的说明本人完全了解西安电子科技大学有关保留和使用学位论文的规定,即:研究生在校攻读学位期间论文工作的知识产权单位属西安电子科技大学。学校有权保留送交论文的复印件,允许查阅和借阅论文;学校可以公布论文的全部或部分内容,可以允许采用影印、缩印或其它复制手段保存论文。同时本人保证,毕业后结合学位论文研究课题再撰写的文章一律署名单位为西安电子科技大学。(保密的论文在解密后遵守此规定)本人签名:导师签名:日期鲨!!:塞二!! 摘要随着移动互联网的快速发展,人们对智能手机的需求越来越多。而在各个智能手机操作系统中,Android系统凭借Goo百e的技术支持和其开源特性而得到了各个公司的支持。C锄e豫设备作为智能手机必备的组件,也成为人们关注的重要部分。关于C锄em,Am(1roid系统在上层应用提供了较完善的接口,但在趾l(1roidHAL层、驱动层的C锄em控制器驱动和C锄efaS锄sor驱动上却没有统一的标准。针对这些问题,本文以某一款开发板上Android系统的C锄era模块开发和移植为背景,对触id系统的开发环境和移植进行简介,对A麒koid系统下C锄era模块的HAL层、Camera控制器驱动以及C锄e豫S黜or驱动进行深入的分析和研究,总结并概况了眦id系统下C锄era模块的工作原理和工作流程。并在该开发板上基于v4L2标准和普通字符设备模式两种方法实现了Am‘hDid系统下的C锄em模块的HAL层和Ij玎uX驱动层。关键词:AndmmC锄era应用层HAL层控制器驱动Sensor驱动 AbstractWim恤rapiddevelopm饥t0fIIlobile谳锄et,morepeoplestartt0llseSmartph0姗.In枷0fmese0p倒tiIlgSy阳nsfor锄artph.粥,龇droids姆眦,wlmgoo幽supports趾dits0pellsourcecharac硎stic,岫b唧鲫pportedbyVanollS鲫唧砸鹤.C锄戗a唧1ipment勰孤髓sential唧n髓tofsmartphone,h觞beC0mea11impo衄tpartofpeople'satt训0n.AboutcaIll%锄droidsyst鼬provldesb濑inte嘲c髓fofc锄eraapplicatioIlsillupperlay既ButiIl砌加idHALla黟锄d11nuxdmer1碱惭eisn0s伽融矾丘弧eworkforc锄eramodule·舢aresult'恤spap%dcvelop吨趾dporting锄趾droidc锄锨moduleina撕elopIIlentb0棚舔妣back鲫眦d,in们duc铭曲devclo呻ent髓、俩姗饥t0faIldroidsyst锄趾d龇舢恤gofaIldroid,de印ly锄alyz镐龇dresearchesmeHALl鹕c锄eraC0n仃011盯“verandc锄ems锄0rdriv%跚姗ariz骼tlleworking砸n咖le锄dwomngtIowofcal麟amodulein孤‘lroidsySt锄,锄drealizestheHALl彬孤dlmuxdnverl啊0fmec锄eramoduleinade、,elopm饥tbo矾b弱ed0nV4L2s伽1d矾舭dreguLar(.haI.acterde啊cemodel.Keyw。rd:androidcameraappHcati。nHALlayercameracontmu盯dI如ercamerasensord订Ver 目录第一章绪论⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.11.1选题背景及研究意义⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.11.2国内外研究现状⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.11.3主要研究内容⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.21.4论文结构安排⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯..’⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.3第二章相关技术概述⋯⋯⋯⋯⋯⋯⋯⋯⋯:⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯..52.1ANDI的D平台框架⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯52.2L煦Ⅸ内核相关概念简介⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯一72.2.1I.jnlⅨ用户空间和内核空间⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯72.2.2Linll)【系统调用⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.82.2.3I,inux设备驱动⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯8第三章舢岫ROID的开发环境搭建⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.1l3.1ANDRoD移植概述⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯113.2ANDRom开发环境的搭建⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯123.2.1开发所需软件资源⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯123.2.2开发所需硬件资源⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯一15第四章ANDROID下的CAMERA模块分析和设计⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯174.1C—蝴RA应用层、运行时环境、库介绍⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.174.2CJ蝴RAHAL层分析和设计⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯l74.3LNux驱动层分析和设计⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.194.3.1C锄efa控制器驱动⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.194.3.2C锄eraSellsor驱动⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯。204.4整体框架⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯..23第五章舢奶ROID下的CAMERA模块实现⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯255.1基于V4L2标准的CA^伍RA模块实现⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯255.1.1HAL层实现⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯255.1.2Linux驱动层实现⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯275.2CAⅦzRA模块的普通字符设备方式实现⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯385.2.1HAL层实现⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.385.2.2Li姗x驱动层实现⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯39第六章C舢ⅥERA模块的测试⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.416.1C怂伍RA模块的测试环境⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯..4l6.2C—岫RA模块的功能测试⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.426.2.1C锄era硬件测试⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯..42 6.2.2“nuX驱动测试⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯436.2.3HAL层测试⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯。446.3CAMERA拍摄效果测试⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯45第七章结束语⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯一49致谢⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯..51参考文献⋯⋯⋯⋯⋯⋯二⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯.53 第一章绪论1.1选题背景及研究意义随着科技的发展和无线移动互联网的普及,手机的功能越来越强大,人们对手机的需求也不仅仅是基本的打电话或玩简单的小游戏了,人们更多的是希望手机能像电脑一样方便,所以智能手机渐渐成为人们选择的目标。而Goo百e的Android系统凭借其通用、开源、免费的特点迅速的在短时间内占有了大量的市场,成为时下手机终端产品时下的热门。而作为触id智能手机的必备功能之一的拍照功能更是常成为用户选择龇id产品的重要依据,其质量、稳定性、拍摄效果往往可以左右人们的选择。№id是基于Linll】【内核的软件平台和操作系统,是Goo舀e在2007年11月5日公布的手机系统平台,早期由Goo百e开发,后由开放手机联盟(Op饥Halldset砧1i锄ce)开发。它采用了软件堆层(SonwarcStack,又名以软件叠层)的架构,主要分为三部分。低层以LinuX内核工作为基础,只提供基本功能;其他的应用软件则由各公司自行开发,以JaVa作为编写程序的一部分。龇id下的C锄era模块同样分为三部分,应用层,HAL层,I,inux驱动层。应用层由Goo西e提供参考代码,有较完善的接口,HAL层需要与驱动层相配合,HAL层通常由芯片厂商提供参考代码,由于没有统一的标准,不同的芯片公司会有不同的代码结构。驱动层会涉及C锄era控制器驱动和C锄eraSeIlsor驱动,Camera控制器驱动会由芯片厂商提供参考代码,C锄emSenSor驱动是手机设计公司根据C撇era控制器驱动提供的接口来对具体的c猢外设进行初始化和配置以协调CalIlera控制器和C锄emScIlsor使他们能够正常工作。但在C锄efaHAL层到驱动层没有固定的代码编写标准,这就为代码的编写提供了各种的框架结构,不利于手机的研发。针对这些问题,本文以实现某一块开发板上的Androidc锄era模块开发为背景,研究C锄era的在HAL和驱动层的工作过程和原理,帮助开发者更好的理解和尽快的解决AndroidC锄era相关的问题,提升触id手机研发进度。1.2国内外研究现状首款Android手机是由Google和HTC(宏达电)联合推出的HTCGl,它以Android为操作系统,包含移动电话工作所需的全部软件。随后,黼id平台的研发队伍阵容强大,包括Goo西e、HTC(宏达电)、T-Mobile、高通、摩托罗拉、 2基于Android系统的C锄em模块设计和实现三星、LG以及中国移动在内的34家企业都有基于该平台开发手机的新型业务。在中国,台湾的联发科也在2010的北京国际通信展上展出了他们的4、5款Android手机,而台湾的mstar、上海的展讯通讯等公司也正在积极研发基于Android平台的手机。关于№id下的C锄era模块,在Lin_ux下,存在一个V4L(ⅥdeoForIjnl】x)标准,它由~觚Cox在bttv驱动接口基础上改进而来,在2006/2007年发展为现在的V4也标准。它为视频设备在Ijnbx内核和用户层应用程序提供了一系列接口函数。由于触id是以“nuX为内核,所以Android下的C锄era模块可以按照V4L2标准来写HAL层和内核驱动,但其中的HAL层必须与And∞id的一些标准接口相配合。但并不是所有的芯片设计公司都会使用这种标准,由于芯片设计不同和方便移植,一些芯片公司往往会按照自己的结构来设计C锄era模块,由于C锄era设备属于字符设备,所以这些芯片公司通常会在Linu)【下以普通字符设备驱动的方式来设计C锄efa的驱动,在HAL层会根据驱动提供的调用接口来设计HAL层。C锄era模块还包括C锄eraSeIlsor,它通常由Sensor公司提供,如CIIIlIliⅥsion、美光、格微科、比亚迪等。这些公司设计CamemSensor的硬件设备,提供相关的硬件文档给手机设计公司,通常这些S饥sor的特性都具有很多的相似性,需要根据相应的文档配合手机芯片来完成C锄era模块。1.3主要研究内容本文以三星6410芯片为平台、OV(0IIllniⅥsion)系列的C锄eraSensor,辅助对比高通7227芯片,分析Android下的C锄era模块框架和各部分特征。主要完成的工作有:1.研究国内外关于Am(1roid的发展现状,介绍“nuX开发环境下Amdroid系统移植的相关知识;2.分析和总结了触id下C锄eraHAL层相关的结构;3.分析某芯片公司的C锄e豫控制器驱动,总结其相关工作逻辑;4.研究c锄eraSeIlsor的工作原理;5.按照所总结方法设计了胁id的C锄era模块并在某个三星6410芯片的开发板上实现其功能。由于Camera模块涉及Camcra应用层、HAL层、芯片上的C锄e豫控制器驱动、C锄eraSensor驱动、C锄em硬件设备的连接,这些部分存在紧密的联系,某一层的问题往往会影响到整个模块的正常工作,所以在实现C撇模块的过程中,对问题的排查,对代码的调试也是模块实现的重要组成部分。 第一章绪论31.4论文结构安排论文共分为六章,各章主要内容如下:第一章:绪论。提出项目背景及研究意义、国内外研究现状、论文的主要研究内容和组织结构。●第二章:相关技术概述。列举并详细描述研究过程中涉及到的关键理论和技术,其中包括Android平台框架介绍、Ijn:u)【内核相关概念介绍。第三章:Android的开发环境搭建及移植概述。介绍Amdroid手机开发所需要的软硬件环境。首先介绍开发所需配置的主机环境,如何获取开发所需源码。接下来根据源码编译需求进一步对主机环境进行配置,分别编译源码的不同部分。之后介绍源码所需要运行在的硬件环境。第四章:触id下的C锄cra模块分析。通过分析把C锄era模块分为C锄em应用层、m地层、Linux驱动层三个部分,指出C锄e豫模块功能实现主要在HAL层、I.inux驱动层,驱动层又分为C锄e豫控制器驱动和C锄eraSensor驱动。接着分析HAL层和LinuX驱动层的工作流程,以及所涉及设备的工作原理。第五章:Amdroid下的Camera模块实现。通过And而d提供的接口函数实现五C锄era模块的HAL层,在驱动层分别使用V4L2标准和普通字符驱动模式实现C锄em的Lmx驱动。第六章:调试和测试。首先介绍C锄era模块从硬件到AmdroidHAL层的功能调试方法。再介绍C锄e豫成像效果相关的知识,通过配合必要的检测设备修改驱动程序完成C锄era成像效果的调试。最后通过在不同的环境下测试C锄em的功能和成像效果。第七章:总结。对雅出oid终端产品前景展望,对论文内容进行概括总结。 4基于Android系统的C锄era模块设计和实现 第二章相关技术概述52.1Android平台框架批id平台是一组面向移动设备的软件包,它包含了一个操作系统、中间件和关键应用程序。开发人员可以使用舢ldI.oidSDK(软件开发工具包)为这个平台创造应用程序。应用程序使用Java语言编写并在Dalvil【之内运行。Dalvik是一款量身定制的虚拟机,它专为嵌入式应用设计,运行在LinuX内核上层,其框架分为Applicatio邶,ApplicationF删[Ileworks,Libr碰嚣,AndroidRuIltime,HardwareAbs仃actionL彬,LinuxK锄el,如图2.1所示。AndroidAnat0脚lyApplica右Onsh哪edialerIMBrowerC锄emApplicationF黜lewofksActiV埘WilldowsMContentl沁souI.ceNotificationM雒ager孤agerProvidersMaIla|萨rMaIlagerLibr撕esAndl.oidlhmtimeSu确配eMediaSQL沁WebKitCo豫Librari髓M鞠a髫玎F戊强me、^,o勰LibcDalvikVirmalMachineHardwareAb8tractionLayerGraphicsIAu击。lIc锄era.|鼬t砌fIG鹧㈠⋯|LinuxKemelDisplayD订VefC锄e糟diverUSBDriv盯KeypadDnV凹图2.1Android平台框架1.Applications(应用)Android将预装一组核心应用程序,包括锄ail客户端、短信服务、日历日程、地图服务、浏览器、联系人和其他应用程序。所有应用程序都是Java编程语言编写的。 6基于Android系统的C锄em模块设计和实现2.ApplicationFrameworl!【S(应用框架)应用程序就是依赖应用框架层次API开发的。应用架构设计的初衷是:简化组件复用机制;任何应用都能发布自己的功能,这些功能又可以被任何其他应用使用(当然要受来自框架的强制安全规范的约束)。和复用机制相同,框架允许组件的更换。所有应用都是一组服务和系统,一般包含:·一套丰富且可扩展的视图组件,含有lists,鲥ds,textbox懿,buttons,甚至嵌入的网络浏览器;9·ContentProViders(内容提供器)使一个应用可以访问另外一个应用的数据(如联系人),或者使一个应用内部可以共享自身数据;·ResourceMallager(资源管理器),提供对非编码资源——例如本地化字符串、图形和布局文件——的访问通道;●NotificationM趴agcr(通告管理器),使应用在状态栏显示自定义的警报通知;·Activi够M肌ag研(行动管理器)负责管理应用的生命周期,提供通用导航回退支持。3.LibⅢes(库)Android包含一套C/C++库,Android系统的各式组件都在使用。这些功能通过Android应用框架暴露给开发人员。下面列举一些核心库:·SystcIIlClib捌y一衍生于BSD的标准C系统库(1ibc)实现(注:BSD:B酞eleySoflwareDistribution,伯克利软件套件,是UI血的衍生系统,1970年代由伯克利加州大学开创),尤其支持嵌入式的基于Lin:u)【的设备;·MediaLibrari髓一媒体库基于PacketVideo’s0IpellCORE;媒体库支持很多流行音频和视频格式、静态图形文件(包括MPEG4,H.264,MP3,AAC,AM凡JPG,锄dPNG)的播放和录制;·Surf.aceM纽ag髓一管理范围:对子系统显示功能的访问,跨应用的无缝组合2D和2D图形层:·Libwebcore一是流行的浏览器引擎,可以支持Android浏览器和嵌入应用的WEB视图组件;·SGL一底层的2D图形引擎;●3Dlibr撕es.基于0IpcllGLES1.OAPI的实现;该类库使用硬件3D加速器(如果硬件支持的话)或者内置的、高度优化的3D软件加速机制;·FrecType-支持位图和矢量字体;.·SQLite.能干、轻量级的关系型数据库引擎,面向所有应用。4.AndroidR1mtime(Android运行时) 第二章相关技术概述7Amdroid的核心类库提供Java类库所提供的绝大部分功能。每个AJ汕Did应用都运行在自己的进程上,享有Dalvil(虚拟机为它分配的专有实例。为了支持多个虚拟机在同一个设备上高效运行,Dalvik被改写过。Dalvik虚拟机执行的是Dalvik格式的可执行文件(.dcX)——该格式经过优化,以降低内存耗用到最低。Java编译器将Java源文件转为d嬲s文件,cl嬲s文件又被内置’的dx工具转化为deX格式文件,这种文件在Dalvil【虚拟机上注册并运行。在一‘些底层功能——比如线程和低内存管理方面,Dalvil【虚拟机是依赖Linll)【内核的。5.H盯‘1wareAbs仃actionL,ay盯(硬件抽象层)触id的HAL(硬件抽象层)是Goo西e因应厂商“希望不公开源码’’的要求下,所推出的新观念,HAL的目的是为了把Android舶mework与Lin.u)【kenlel完整“隔开”。让Android不至过度依赖I.inllxk锄el,让Android劬me、阳rk的开发能在不考虑驱动程序的前提下进行发展。6.“ml】【K锄el(Liml】【内核)Am(bid依赖Ijn:u)【2.6版,提供核心系统服务:安全、内存管理、进程管理、网络组、驱动模型。内核部分还相当于一个介于硬件层和系统中其他软件组之间的一个抽象层次。2.2LilluX内核相关概念简介因为C锄era模块的驱动是LinuX下的驱动,其HAL层代码也需要与Linux内核进行交互,所以有必要介绍一些I,inux内核概念帮助理解。2.2.1“nllx用户空间和内核空间Linux为了保证程序的独立操作,保护资源不受非法访问,让操作系统运行在两种不同的级别。例如应用程序运行在用户空间,驱动程序运行在内核空间,这个任务是由CPU完成的。所有的现代处理器都具备这个功能,在较低的级别中将禁止某些操作。程序代码只能通过有限数目的“门"来从一个级别切换到另一个级别。当前所有处理器都至少具有两个级别,而其他一些处理器,比如x86系列,则有更多的级别。当处理器存在多个级别时,“nuX使用最高级别和最低级别。在LiIlll】【中,内核运行在最高级别(也称作超级用户态),在这个级别中可以进行所有的操作。而应用程序运行在最低级别(即所谓的用户态),在这个级别中,处理器控制着对硬件的直接访问以及对内存的非授权访问。’每当应用程序执行系统调用或者被硬件中断挂起时,LiIlll)【将执行模式从用 基于Android系统的C锄e豫模块设计和实现户空间切换到内核空间。2.2.2Linux系统调用所谓系统调用,就是内核提供的、功能十分强大的一系列的函数。这些系统调用是在内核中实现的,再通过一定的方式把系统调用给用户,一般都通过门(gate)陷入(trap)实现。系统调用是用户程序和内核交互的接口【l】。系统调用在“nuX系统中发挥着巨大的作用,如果没有系统调用,那么应用程序就失去了内核的支持。系统调用是用户接口在内核中的实现,如果没有系统调用,用户就不能利用内核。不同CPU处理系统调用的方法也不一样。比如x86系列处理器通过中断Ox80,从用户态切换到内核态,通过处理器寄存器传递参数,执行系统调用。血m系列的处理器通过改变状态寄存器CPSR来从用户态切换到内核态,执行系统调用。一般系统调用的过程如下:1.执行用户程序;2.根据西ibc中的函数实现,取得系统调用号并执行int$oX80产生中断(锄处理器通过改变状态寄存器);3.进行地址空间的转换和堆栈的切换,执行SAVEALL(进行内核模式);4.进行中断处理,根据系统调用表调用内核函数;5.执行内核函数;6.执行RESTOREALL并返回用户模式。2.2.3LinuX设备驱动驱动是一个允许高级计算机软件与硬件交互的程序,这种程序建立了一个硬件与硬件,或硬件与软件沟通的界面,经由主板上的总线或其它沟通子系统与硬件形成连接的机制,这样的机制使得硬件设备上的数据交换成为可能【2】。Linux设备驱动在Li肌x内核里扮演着特殊的角色。它们是截然不同的“黑盒子",使硬件的特殊的一部分响应定义好的内部编程接口。它们完全隐藏了设备工作的细节。用户的活动通过一套标准化的调用来进行,这些调用与特别的驱动是独立的;设备驱动的角色就是将这些调用映射到作用于实际硬件的和设备相关的操作上。这个编程接口是这样,驱动可以与内核的其他部分分开建立,并在需要的时候在运行时“插入”【2j。Lin_u】【将设备驱动分为三类:字符设备驱动、块设备驱动和网络设备驱动。字符设备指那些必须以串行顺序依次进行访问的设备,如触摸屏、鼠标、C锄em 第二章相关技术概述9等。块设备可以以任意顺序进行访问,以块为单位进行操作,如硬盘、n锄d等‘31。字符设备和块设备驱动设计有很大差异,但对于用户层而言,他们都是用文件操作接口opell()、Close()、readO、、耐t“)等函数进行访问。而网络设备驱动是面向数据包的发送和接收设计的,它并不对应于文件系统的节点。Linll)【驱动与上层应用、应用的关系如图2.2所示。I用户应用程序可c语言库函数ILinux系统调用接口LiIlll)【文件系统I字符设备块设备驱网络设备驱动动驱动I硬件设备图2.2I.jn职应用层与底层硬件的交互过程图2.2描述了I,inlⅨ下应用层与底层硬件通信的过程,应用程序通过c库函数或Lin_Il】【系统调用操作设备节点,通过“nux的文件系统找到对应的驱动操作,通过驱动与硬件设备交互。 lO基于Android系统的C锄em模块设计和实现 第三章Am“d的开发环境搭建第三章Android的开发环境搭建3.1Android移植概述Amdroid可以运行在Gbo酉e提供的模拟器上,也可以运行在具体与硬件相关的开发板上。运行在模拟器上的触id不涉及I.inllx内核部分,主要是为了方便上层开发,对需要各个外设参与的应用程序,Goo西e提供了一系列的模拟代码,使之可以像真实的设备一样,为用户的应用程序提供参考。本文的A麒hidC锄era模块的开发,需要在一块基于加m芯片的开发板上运行。需要软件硬件两个方面的支持。本章介绍AndroidC锄era模块开发在软件硬件方面的需求。‘首先需要一台基于x86的PC机作为开发使用的机器,并需要在这台机器上安装必要的操作系统,在对其进行配置。使其能够编译加ldroid,并能够把编译成的文件下载到开发板上。而本文所述Android移植是在真实的设备上,根据不同的芯片、不同的外设,·提供能够使这些硬件正常工作的代码。将Android移植到某个开发板上,通常需要移植三个部分:B00tload%I,in:u】【Kenlel和mldroid文件系统。1.Boonoader移植B00tloader是在LinuX内核运行之前运行的一段程序,它通常对CPU、内存、flaSh、串口等进行初始化,移植需要根据开发板相关的硬件特性配置相关设配。Bootloader还担负着下载代码到开发板上的任务,通过相关的选项让B00tloadcr运行时停在某个位置,通过选择相应Linux内核和Android文件系统,之后把它们烧写到开发板的n姐d上,以便下次运行时调用。本文主要是对Android下Camera模块的研究和开发,所以对Bootloader移植不做详细分析,默认Bootloader不存在任何问题。2.LinuX内核移植Linux内核移植需要根据不同的芯片外设。通过makem咖C0n堍命令配置对应的通用硬件,再根据芯片和产品不同的硬件特性编写相应的驱动程序,通过修改Mal【e6le和K(幻n丘g把它们编入内核,最后通过Bootloadef提供的方法把内核文件烧写到开发板上。3.加1droid文件系统移植A时roid文件系统需要根据不同的用途,根据不同的芯片公司的设备提供与 12基于Android系统的C锄em模块设计和实现设备通行的用户层代码,使用户可以方便的使用开发板的硬件资源。由于Android内核是基于Linux的,基于Li肌x内核的操作系统是较好的。现在成熟的Lin_u)【发行版有ubuIltu,Fedora,Debi距等。本章以IJl)瑚加10.04为操作系统配置开发环境。3.2Android开发环境的搭建本文的知l(1roidCamera模块的开发,需要在一块基于知m芯片的开发板上运行。需要软件硬件两个方面的支持。本章介绍AmdroidC锄era模块开发在软件硬件方面的需求。’首先需要一台基于x86的Pc机作为开发使用的机器,并需要在这台机器上安装必要的操作系统,在对其进行配置。使其能够编译№id,并能够把编译成的文件下载到开发板上。由于Android内核是基于№的,基于“nux内核的操作系统是较好的。现在成熟的L胁畎发行版有Ubuntll,Fedom,Debi锄等。本章以Ub硼加10.04为操作系统配置开发环境。3.2.1开发所需软件资源本文所述的C锄era模块开发是在Android2.1源码基础上的开发,在实现C锄era模块的过程中会用到Android提供的一些接口和芯片公司提供的BSP(BoardSupportPackagc)上的一些函数。1.获取Android源代码在获取源代码之前,首先简单介绍下西t。Git是用于LinuX内核开发的版本控制工具。它用了分布式版本库的方式,不必服务器端软件支持,使源代码的发布和交流极其方便。因为And∞id是由k锄e1,dalVik、biollic、p把built、build等多个Git项目组成,为了更方便的管理这些项目的源码,goo酉e为这些项目编写一个P灿on脚本r印o,它把西t进行封装以同时管理这些源码。在Ublll】加下获取Amdroid最新源码需要以下几步。1)安装酉t和训‘Cucl是一个利用URL语法在命令行下的文件传输工具,会安装R印。的时候用到。通过sudo印t—getillstallgnc0∞cud安装。2)下载r如。脚本下载之前,新建一个目录,比如椰,把它添加到环境变量里,在I舨mtI】下 第三章An“d的开发环境搭建13修改~/.b嬲hrC文件最后添加cXportP舢=$P御:忡,这样执行r印。命令时会调用~/repo下的r印。脚本。接着通过cudl脚:肌‰droid.百t.kenlel.0r酊印o>~卸。下载r印。脚本。并且给Depo脚本执行权限,通过∞dochmoda+x一/r印。命令执行。3)初始化版本库这步是通过r印。命令下载最新的A。ndroid源码。新建目录√Android,在该目录下执行rep0iIlit命令。r印o“t-u西t:肌吣ldroid.垂t.k锄d.org/plat向m蜘aIlifeSt.酏最后会看到rep0iIlitializedin~/Android这样的提示,就说明本地的版本库已经初始化完毕,并且包含了当前最新的源码。如果想拿某个分之上的源码,需要用-b参数指定bmCh名字例如:repoi11it—u西t://Android.百t.kemel.o玛佃la£如n】¨maIlif-eSt.百t_bcupcake另一种情况是,如果只需要某一个工程的代码,比如kemeWrivcr,就不需要r印。了,直接用西t即可。班clone西t://Android.西t.ke朋d.o礓/k锄e犰lriVer.百t。这也需要不少的时间,因为它会把整个I,in慨№lel的代码复制下来。4)同步版本库’使用r印oshsync命令,可以把服务器上的整个№id源码下载到开发机上。同样,也可以用类似r印osyncprojectlproject2的命令行来同步Android源码中的某几个子项目。全部同步完后~/Android下将是最新的Android源码。2.环境配置及编译№id编译分为IjnuX内核的编译,触id文件系统的编译。不同的部分需要的环境配置也不同。1)LinuX内核编译本文所述内容是在普通x86的PC机上开发,对Ijn:ll】【内核编译进行编译。但需要在基于锄的芯片上运行所以要建立一个交叉开发环境方便开发。交叉编译是指,在某个主机平台上用交叉编译器编译出可在其他平台上运行的代码的过程。要进行交叉编译,需要在主机平台上安装对应的交叉编译工具链,然后用这个交叉编译工具链编译源代码,最终生成可在目标平台上运行的代码。进行交叉编译需要一个交叉编译工具链,芯片公司往往会提供这些工具链。工具链中通常包括aml.I,inux一甄锄.LinuX.gcc等工具,把它们所在的目录添加到Ub硼加的环境变量中。例如它们位于~/1】s川oc州am似.4.1/biIl下,就在~/.bd玳最后添加eXponPATH=$P棚:~/1l跚们oc训a珊/4.4.1/bin。编译内核之前有必要简单介绍以下一些内核目录。 14基于Android系统的C撇em模块设计和实现·砌目录包含了核心源代码所支持的硬件体系结构相关的核心代码。如对于X86平台就是i386,对于锄平台就是绷。◆include目录包括了核心的大多数include文件。另外对于每种支持的体系结构分别有一个子目录。·init目录包含核心启动代码。·lm目录包含了所有的内存管理代码。’·“Vers目录包含了系统中所有的设备驱动。它又进一步划分成几类设备驱动,每一种也有对应的子目录。比如本文需要开发的Camera控制器和C锄eraSenS0r驱动位于嘶v例,media/Video目录下。·ipc目录包含了核心的进程间通讯代码。‘·modules目录包含已建好可动态加载的模块。●色目录包含了I,inuX支持的文件系统代码。不同的文件系统有不同的子目录对应,如eXt3文件系统对应的就是eXt3子目录。·k锄el目录是Lill.呱主要核心代码。●net目录是核心的网络部分代码。里面的每个子目录对应予网络的一个方面。·lib目录包含了核心的库代码。。●s嘶pts目录包含用于配置核心的脚本文件。·DoC唧entation目录是一些文档,起参考作用。接下来就可以编译内核了,在具体的编译之前,还需要根据芯片的种类来配置内核。通过在内核的根目录下执行makemenuconfig命令来以菜单的方式来配置。也可以通过mal【eco曲舀makexcon丘g命令来配置。由于makecon丘g是以命令行形式来配置,较为繁琐。makexcon丘g是以窗口模式下配置,在Linll)(环境里一般也不用。“nux内核支持较多的CPU架构,提供了丰富的编译选项以适应不同的产品,这些都可以在编译前进行配置。其实配置都在源码里对应着相应的Makefile和Kcon69文件。它们支持把源代码直接或以模块的方式编如内核文件。通过makemenuC0曲g可以方便的把需要的源码编入内核,把不需要的源码舍去,以减小内核的大小,调高产品的运行效率。2.)Android文件系统的编译文件系统的编译需要开发环境提供-_些必须的软件包,在Ub硼tll下,需要nex,bison,印吼libsdl-dev,build—ess饥tial,libesdO—dev,libwxg此.6-dev,zip,训,val鲥nd,phython2.4或以上版本,jdkl.5。通过UbuIl_tll下的sud0apt_geti11stall命令进行安装。为了更好理解Android框架,简绍下Android下的一些目录。◆胁leworks目录包含了Android的应用程序核心框架代码,以java和C++ ·dalv搬目录包含了Am‘hoid自带的jaVa虚拟机。·development目录包含了程序开发所需要的模板和工具。·eXt锄al目录包含了第三方的一些软件和库。·h钺iware目录包含了部分厂家开源的硬件适配层HAL代码,C锄era模块HAL层的代码可以放在该目录下。。●邮b硼t目录包含了x86和枷架构下预编译的一些资源。●syst锄目录包含了底层文件系统库、应用及组件,以C语言编写。·paCkages目录主要存放java层应用程序代码。·veIldor目录包含了不同厂家的定制目录。·k眦el目录是A面roid底层所依赖的I.inux内核代码。◆prcbuilt目录包含了各种平台下编译所需的脚本和交叉编译工具。接下来就可以开始编译了,与内核一样触id文件系统也需要进行一些配置,Adl(1roid的配置是通过配置一些常量的值来使Android的make6le文件按照特定的需求来生产相应的文件。通常需要配置的常量有吖岷GETPRoDucT,TARGET.sⅡ订ULATIoR,TARGEl巳.BUILDTYPE,TARGElI—BUILDmL≮NT。它们是提供给眦id的makefile文件的,决定编出来的目标文件的某些功能。如:T根GETPRoDUCT是决定在毗r目录下的哪个产品是实际需要的。W瓜GETSIMuI.A1’oR是决定给触id模拟器使用的还是给开发板使用的等。3.2.2开发所需硬件资源首先在处理器方面,Android要求至少为缸m9200MhZ以上的处理器。在内存方面,至少需要32M的内存。存储器方面,因为要保存Bootloadcr,Linux内核,№id文件系统,所以至少需要128M以上的n舭d存储器。本文以某一款s锄gun酌410这个开发版为例介绍龇id下C锄era模块的实现需要哪些硬件条件。这个S锄蹦lgS3c6410开发板处理器为ARMll76JzF.S核,内存为256MDDR黜蝴,达到了缸ldorid运行的硬件要求。128MN趾dFlaSh足以存储BooUoader,。Lillux内核,Android文件系统。4.3寸真彩色1’I叮液晶屏可以让我们直观的感受到C锄era的拍摄效果。标准SD卡座可以让B00tloader、Linllx内核、 16基于Android系统的C咖em模块设计和实现Android文件系统文件通过SD卡烧写到naIld存储器上。串口用于代码的调试。CMOS摄像头接口(图3.1)是用来接外置的摄像头设备的。12esD磊i!竺堡8R堂嘲■■■■■■■■■■■■■■●●■■■●■●■’Il●■■■·一CA黼SDAGPK2R7210l(《3.3研(1。8聊如。嘲豫盟2468王O12耋4.1820幽R12eseLCA髓SeLeA磊乔RST秘CA嬲HREFeA酗PC耋.KVDDK>CAMDATA6VeA醚DATA4Irn垒塑壁垒坠兰◆1咐1锵CA隧oATAO—-卜v鼗£陀磊隧I(2.4孓2.8ⅥGK貉图3.1S觚瑚ngS3C“10芯片的C枷em模块接口图3.1是S锄sungS3C64lO芯片手册上C锄era模块的截图,它为C锄era设备提供的20个pin脚。其中CAMDATAO.7是与C锄era设备图像数据传输的接口。V1)DIO,Ⅵ)D18VVDDC伽订是通过PMIC给C锄era设备供电的接口。CAMSDA,CAMSCL是芯片上12C控制器提供给的12C接口。C舢ⅥCLK是芯片给C锄cra设备提供初始频率的pin脚。CAMRSTn是硬件复位piIl脚,通过操作该pin脚可以硬件复位C锄era设备。CAMVSYNC,CAMHREF,C触唧CLK分别是帧同步、行同步、像素时钟,是用来协调接受C锄e豫设备传来的数据。GND是地线。蚕l旧愕盖m噶∞一一一一一一一一一一一一一一一 第四章Android下的C锄em模块分析和设计17第四章And∞id下的C锄era模块分析和设计Android下的C锄era模块开发的主要工作是把在主机端开发Android关于C锄era的HAL层,Linu】【内核里的C锄era控制器和C锄emSell∞r驱动,把它们分别编入A涨lroid文件系统和【柚uX内核,通过Bootloader提供的烧写功能把它们存储到开发板的naIld存储器上使开发板能够在运行时正确的使用C锄era设备。根据第二章Android平台框架的介绍,A面roid分为jaVa应用层、应用框架层库、And埘d运行时、HAL层和Lmu】【驱动层。A“lroid下的模块大致都符合上述框架。龇id下的C锄era模块也一样。C锄em模块在jaVa应用层,应用框架层库,№id运行时环境,№id都提供了较完善的框架,在功能上Android在这些层都提供了完善的源码。但在HAL层和驱动层则需要根据具体的芯片和外设特征进行编码以使其正常工作。本章会对简单介绍c锄era应用层、运行时环境、库,对HAL层和驱动层作详细的分析和实现。4.1C锄era应用层、运行时环境、库介绍Am‘hoid发布版的Camera程序架构分成客户端和服务端两个部分,建立在Amdroid的进程间通讯Bmder的结构上。C锄era的应用层是用java语言编写的,是用户与设备的交互接口。其相关源代码位于packages/印ps/C锄盯a/sr洳/Android/C锄efa下,会被编译为C锄era.apk。运行时环境是C锄era应用层通过ⅢI的本地调用部分。它通过900酉e提供的java虚拟机dalVik使应用层的java代码可以与C++语言编写的代码进行交互。其相关源代码位于仔锄ework泊舔e/cor嘶州下,这部分会被编译为libAndroidHHItime.so。C锄era底层库位于m吼eworks/bas胡ibs/_耐下这部分被编译为libui.s0。它是Camem功能中实现Bindef机制的接口类,对上层C锄era.apk提供接口,具体功能由其子类实现,在C锄ejra模块中是libC锄eraseⅣiCe.so。4.2C锄emHAL层分析和设计libC锄er雒eⅣice.s0是C锄efa的服务端程序。它是与C锄eraHAL层交互的 18基于Android系统的C锄em模块设计和实现一个库。相关代码在№id源码觎哑eworks厂base/C锄e刚libCameraseⅣice下。源码本身提供了一个假的C锄era供Android模拟器使用的。根据该文件夹下的触id.mk文件来决定C锄e豫模块的实现与否。阅读该№id.mk可知USECAMERASTUB宏是决定是否使用假的C锄era,即是否以C锄eraH砌wareS劬.卵p,Fal(eC锄era.叩p为源文件编入libC锄er嬲e惭ce.s0库,本文要在真实的发板上实现e.撇efa模块,所以需要将USEcAMERAsTUB宏设为空,即在一开始编译时并没有定义宏USECAMERASTUB,这样就需要实现libC锄era库,即C锄era模块的HAL层,它是为实体开发板所必须实现的功能。需要根据/觑呱eworks/baSe/inc_lude/ui下的C锄e棚ardwareInterl沁e.h接口实现其相关功能,写出与c锄e豫驱动通信的代码。这部分在C锄era应用程序里的大致调用流程如图4.1所示。图4.1C锄efa模块HAL层流程图图4.1是根据山ldroid源代码C撇彪lH冰1wareIIlted沁e.h文件里的函数接口实现的HAL层调用过程。首先通过op%C锄emHardware()函数以得到一个C锄em实例,然后initDe最mltP觚吼eters()函数调用getP龇吼eters(),setParameters()初始化这个实例,之后需要初始化一个存放帧数据的堆。在Starqp谳,iew()函数中创建一个线程,该线程实现从C锄em与C锄em驱动交互获取一帧数据,并把数据存放在之前初始化的堆中。之后把堆中的数据复制到Surf.aceFlinger的Bu妇衙中,经 第四章Android下的C锄啪模块分析和设计19过S抵F1iI孵处理后送到LCD控制器的胁lebu脑中以显示在LCD屏幕上。4.3Li删x驱动层分析和设计驱动层分为C锄era控制器驱动和C锄eraSensor驱动,Camera控制器位于手机的芯片上是芯片的一部分,由芯片厂商提供。Came豫S吼s赏是手机外设的一种,它有各个C锄efaSeIlsor公司提供。C锄era控制器驱动控制需要在某些设置方面与CameraS肌sor相匹配,所以他们之间存在着密切的关系。在适当的时候,C锄em控制器驱动里会调用C锄emSellsor驱动以完成整个设备系统的协调工作。’4.3.1C锄era控制器驱动由于C锄en控制器由不同的芯片公司提供其具体的功能叶各不相同,在性能上也存在着差别,但他们都会具有一些C锄era控制器的基本功能。以三星641Q芯片为例,它的C锄era控制器支持的特性如下特性:◆nU-RBT601/6568.bitInode吼lpll,ort;●DZI(Di西talzoom埘capability;●Pro目煳Ablepolmtyofvideosyncsignals;●Maxh肌m.4096x4096pixelsC锄e豫inputsuppcInCodec/Pre、riew;●hIlagcnli盯0randrota.tion(oIllypreview)(X-flip,Vflip,900,1800and2700r0伽on);●Cod∞/Previewoutputilnagegme枷on;●C锄eraimagpc雄帆uefhmecon乜ol吼lpport;◆Sc趾linco凰etsu]pport;●YCbCr4:2:2im曩geint甜eavefomatsupport;●Imagee任.eCtsupport;●LCDcon们llerdnctpamsupp嘣(MSDMA砌y);●hlteIrlaceC锄erain}Iutsupport.C锄era控制器驱动的主要任务就是配置和协调C锄era控制器上的寄存器。对控制器的配置包括对以上这些C锄era控制器特性的参数配置也包括其他一些与C锄eraSellsor相协调的寄存器的配置。根据三星6410芯片的datasheet,初始化和配置C锄era控制器需要按照一定的流程来。首先需要配置控制器为rrU—RBT.60lYC!bCr8.bit模式,三星6410芯片支持ITU.RBT601YCbCr8/l6和ITU.RBT656YCbCr8-bit模式从外部C锄em 基于Android系统的C锄锄模块设计和实现S%sor获取数据,这需要根据C锄emSeIlsor的特点来配置。由三星6410芯片的datasheet可知,这既是把芯片上寄存器CISRCFMTOx78000000寄存器的31位设为1。然后设置寄存器CIGcTRLOx78000008寄存器31位设1,然后设O,以软件复位控制器。这之后再初始化其他寄存器。最后配置芯片TestPalt锄为普通的extenlalcameraprocessorinput(将Ox78000008寄存器27、28位设为1)。至此,C锄em控制器基本配置完成。’这是C锄era控制器大致需要的工作方式。在驱动里,还需要提供一系列接口以按照实际的需求改变寄存器的值以协调系统的运行,其具体实现会在模块实现里详细说明。4.3.2C锄efaS哪or驱动c锄era硬件(即可以在手机上看到的摄像头)是由C锄era模组和C锄eraSellsor组成的,是模组厂商组合镜头等外围器件和C锄eraSenS0r经过调焦等操作并提供相应的与手机主板相连的接口得到的。在C锄em驱动上,由于模组是对C锄eraSellSor的组合和封装,主要涉及硬件和电的特性,它也会关系到C锄em设备的成像效果但在功能上并没有影响,所以在驱动里除了与电相关的操作只需要关注C锄eraScnsor的驱动即可,但通常也把对模组里电的操作也放到C锄eraSensor的驱动里,因为它是C锄efa硬件工作的必备条件,可以算作驱动的一部分。C锄efa硬件与手机设备连接需要通过特定的接口,如图4.2所示。12CSDACAMDATA51ll12CSCLCAMDATA4212EINT20CAMDATA3313CAMRSTCAMDATA2414CAMCLKCAMDATAl515CAM—HREFCAMDATA0616CAM—VSYNCVDD33V717CAM.-PCLKVDDCAM818CAMDATA7VDDl8V919CAMDATA6GND1020图4.2Came豫硬件的20piIl接口图4.2是0IV9650Sellsor的C锄era接口。其中12CSDA,12CSCLpin脚是接在芯片的12C控制器上的。通过这两个piIl脚,12C控制器可以向C锄e豫S嘲0r 第四章Android下的C姗模块分析和设计21发送命令来修改SeIlsor里控制器的数据以配置sensor。芯片通过CAMCLK向C锄efa发送一个时钟给C锄era提供外部的频率;CAMDATA【O.7】是C锄em硬件与Camem控制器相连的piIl脚,C锄em硬件通过这几个pin脚把得到的数据传给系统;VDD33V,VDDCAM,VDDl8V等pin脚是C锄era的几路电;GND是地线【刀。CamemSellsor驱动的主要工作是对camemS6矗sor的初始化和配置,分为上电、硬件复位、给S∞sor提供时钟、P删不使能、软件复位、配置寄存器六个步骤。1.上电Camera通常有三路电,ScIls6r上两路电VDDC√蝴、VDD33V模组有一路电VDDl8V。不同的S锄or可能还需要不同的上电顺序。以OV2655为例其上电需要满足图4.3所述条件。VDD昭Iclal,面l如DA沁嘲PW溅图4.3oV2655上电时序j图4.3中VDD.IO,VDDA代表C锄e豫Sensor上的两路电,PwDN是C锄emSeIlsor的powerdownpin脚的电平,其中TO>一Oms,T2>=5ms,上电期间PwDNpin脚需要为高。2.硬件复位通过硬件复位使C锄era硬件初始化。操作是让resetpiIl脚高低高。硬件复位并不是每个C觚leraseIlsor都要做的,一些sellsor并不需要这一步,其上电后seIlS0r就会自动初始化。3.通过XCLKpin脚提供给Sensor一个时钟不同的SeIlsor需要的提供的时钟范围不同,具体需要参考Sensor的dat砷eet。OV2655需要的时钟范围是6.27Mhz。4.使PWDN不为使能状态这一步是为了使C跗leraSe娜or开始工作,OV系列的sellsorPwDN高电平为使能,所以需要把它拉低。但一些S饥sor可能正好相反,低电平使能,这就需要把piIl脚拉高。5.软件复位软件复位会初始化C锄emseIlS0r的所有寄存器,使其为默认值。通过OV2655 基于Android系统的C锄em模块设计和实现的dat砒eet,软件复位需要把Sensor的ox3012寄存器的3l位设为1,即是通过12c接口向S鼢sor的Ox3012寄存器写0)【80。6.配置C锄eraSeIlsor的寄存器。通过12C接口向SeIlsor的各个寄存器里写入适当的值以配置Sellsor。这样C锄eraSensor就可以采集外部影像了,并在数据线DⅣrAO.D√扎~7上有数据传送了。’CameraSeIlsor的寄存器不仅关系到c锄eraScIlsor能否正常工作,它还需要与C锄era控制器的配置相协调才能采集到正确的图像数据,并且还会关系到采集到的数据的质量。C锄eraS6Ilsor里存在一些需要与C锄era控制器相配合的寄存器。例如,SeIlsor端配置输出的格式为YCbCr格式,并以Y-Cb-Y.Cr的顺序,图像大小为640宰480,在控制器端就需要同样的设置,否则显示出来的图像会丢失一些色彩,从而失真。例如:OV2655sellsor端寄存器Ox300e配置为Ox34,设置输出的格式为YCbCr需要与三星6410的C锄em控制器CISRcFMr寄存器的31位相匹配;oX3400决定图像YCbCr的顺序,它需要与Camera控制器CISRCFMT寄存器的14.15位相匹配;o】【3024,0】【3025决定图像宽度需要与C锄era控制器CISRCFMT寄存器的16.28位相匹配;oX3026,o】【3027决定图像高度需要与C锄era控制器CISRCFMT寄存器的O.12位相匹配。ScIlsor的PcLK,HREF,vsYNc,极性配置也需要与C锄efa控制器的配置相对应,否则就采集不到图像。OV2655Sensor的0x3600的O.3位决定着Se璐or采集图像的三个时钟的极性,它需要与三星6410的C锄era控制器CIGCTRL寄存器的24.26位相匹配,这三个极性之间的关系如图4.4所示。一^=二二二二二二:=::二二二二二二二弃1l『II?lfIlI《:......JI.........................................................................................................................................................................一I..朋哺鄹崎图4.4C撇锨S钮sorV趴烈C,m迮EPCLK之间的关系图4.4显示了seIlsor的一种图像采集模式。当HREF极性为高时采集像素,VsYNC极性为低时采集HREF数据,最后传给系统的是采集到的一帧数据。如果HREF极性S肌sor和控制器不一致,控制器就可能在HREF为低的时候采集数据,这样就可能采集到错误的数据或采集不到数据;而当vSYNC极性Se邺or和 第四章Android下的C锄em模块分析和设计控制器不一致的话,控制器就可能在VSYNC为高的时候采集数据,它就不会采集到数据;而PcLK极性不一致的话,可以采集导数据,但图像就会失真。C锄emS∞sor寄存器还存在一些与Camera控制器在功能上重复的。比如裁剪功能,在C锄ems%S0r上存在对采集到的图像进行裁剪并在数据线上传送裁剪后的图像给C锄e豫控制器的寄存器,而c锄efa控制器上也存在相应的寄存器可以对C锄efaSenSor传来的数据进行裁剪:还有例如图像旋转功能,C锄e豫S饥sor可以对采集来的图像进行上下或左右的颠倒操作,在C锄era控制器端常常会有使图像旋转0-2700的寄存器。在开发时需要协调使用这些寄存器使他们能够配合好,以达到最优的效果。其中还有一些寄存器与图像效果相关,例如LightMode'ColorSanⅡ州。玛Bri西妇ess,C0ntrast’Exposure,sha啪ess,ColorMatrix,GaIIlIIl如Whitebl觚ce等,在C锄em的调试章节会对这些功能进行分析。4.4整体框架通过以上的分析,可以总结出Android下C锄era模块的整体框架图和工作流程图。通过这两个图可以从整体上把握住C锄era模块,为第五章C锄em模块的,:实现做好准备。Camem模块从HAL层到I.inllx驱动层框架如图4.5所示。HAL≤≥蛳⋯硎。张佻Ic锄era控制器么,,、∑。IJIJ‘厶3<7口j基警C锄eraS饥sor驱动。>^Daa【C一7】IlIlPWDNr∞etSDASCLMCLK上liCamem设备图4.5C绷模块HAL层到硬件之间的关系图4.5中m虬层通过操作设备节点与camera控制器进行交互,C锄efa控制 24基于Android系统的C锄em模块设计和实现器通过CamemSellsor驱动给硬件设备发命令使设备正常工作。设备正常工作后,会给C锄era控制器传送数据。HAL层会得到这些数据,进行处理后交给应用层。Amdroid上的C锄era预览从HAL层到驱动层的序列图如图4.6所示。图4.6C黼模块弛也层与驱动层的序列图图4.6中HAL层通过opell系统调用打开用户层的节点/dcv~edioO,再通过一系列ioctl操作获取C锄eraS%sor信息、为图像数据分配内存。在预览时通过调用C锄emSe娜or驱动来初始化和配置Se邶or,最后SeIlsor会把采集到的数据,放到之前分配到的内存中,供HAL层使用,最后实现预览。 第五章Android下的C锄em模块实现第五章Android下的C锄era模块实现由上节分析可知,对C锄era模块的实现主要是对加ldroid文件系统里HAL层,I,inuX内核里c锄efa琏剑驱动、c锄erase娜0r驱动的实现。本章会用两种方法实现Android下的C锄era模块。第一种方法是按照LinuX现有的V4L2标准实现,第二种是把C锄era控制器当作普通的字符设备去实现,最后会总结它们的异同和优缺点。5.1基于V4L2标准的C锄era模块实现5.1.1HAL层实现C锄efa模块在HAL层的主要工作就是完成Camera服务端所依赖的库libC锄era.so,这个库是上层库libCameraSeⅣice.s0的重要组成部分。实现时需要根据觑吼ework泊ase胁clud枷下CameraHardwareIntemce.h里的接口完成对应的函数。在G00西e提供的触id源码纳mework怕嬲e/C锄era/libC锄erauservice下提供了的c锄craHardwareStub.cpp,Fakec锄era.cpp,这两个文件是供模拟器使用的假的C锄era设备HAL层源码,用来供使用触id模拟器时上层开发使用。这里,可以通过参考它的代码结构来实现真正的运行在实际设备上的C锄era设备的HAL层。通常A州lroidHAL层代码放在/ll觚1war奶Ⅸ目录下,其中】【)【为厂商名,所以首先在/llardw触目录下新建libC撇e豫文件夹。在其中为相应的Camem设备创建相应的C或CPP文件,以实现具体对设备的操作。新建Android.mk文件,其目的是将libcamefa模块编入Android的文件系统,使An(1roid上层在调用时使用自定义的HAL层代码。Android.Illl【内容可参考如下代码。 26基于Andmid系统的C锄锨模块设计和实现其中1ibutils,libbind%1ibui,liblog等是该模块依赖的上层库,是Android框架里已提供的。libjpeg库是解码jpeg所需要的,这部分是Android下的另一个模块,在这里默认它是可以使用的。通过这样的make丘le配置就可以生成所需libC撇era.so库,通过它放在A麒lroid共享库里,就可以供libC锄er鹤eⅣice.so库调用了,这样就达到了完成C锄era模块HAL层的目的。为了完成c锄era模块,在HAL层的主要内容是完成针对不同C锄era设备在HAL层的具体操作的函数,以供Android源码里HAL层以上的接口调用。具体实现可以参考Goo哲e提供的伪C锄era源码。首先,需要在代码里创建一个继承触id源码提供的接口CamcraH绷lWareInte血ce的类,并添加其所需的私有成员函数和成员函数,如createIIlst觚ce()用于创建新的C锄era实例等。为了使C撇em的控制和预览的相互独立,还需要创建一个线程类PreⅥ翎汀hread供Camem预览时调用。具体到代码里,需要实现的就是C锄蹦lH鲫iwareInterface.h里所有的函数和其自身的私有成员函数。需要完成的函数有opeIlC锄emHardwareO函数,其主要功能是创建一个C锄era实例,通常在op吼C锄eraHard聊鹏()里需要调用crcateIIlst趾ce(),在crcateIllst孤ce()里通过singleton.promote()得到一个实例,并通过ge伊撇ctersO,setP娥吼ctIerS()等函数初始化这个实例。setP越嘲eters()函数里通常需要初始化图像的高度,宽度,缩略图的大小,设置预览格式等,最后还要分配一个可以存放帧数据的堆,之后就可以开始预览了。由于预览时常常会有其他操作如拍照等,所以在st耐PreviewO需要创建一个新的线程,使用该线程去调用特定c锄era里的pr鲥cw函数获得一帧数据的函数。以上是Android下在HAL层根据上层提供的接口完成的函数,其中在具体的获取一帧数据时,它需要根据具体的Camera控制器的特性来实现,在这里也存在一些标准。例如现在实现获取一帧预览部分ge印rcviewO函数时,它的流程如果符合V4L2标准,其通常的操作为打开设备,初始化设备(如:配置设备属性、设置为视频还是音频,设置图像亮度等),配置输入输出,开始预览,停止预览,关闭设备。其具体的操作是通过Lin_u)【的一系列系统调用如0peIl()、read()、iocll完成的。V4L2标准下,在HAL层首先通过opell系统调用打开C锄era的设备节点(如/dev~ide00)得到一个文件描述符。之后分别通过ioctl(fd,VIDIOC-QUERYCAP,...),ioctl(fd,VDIOC_cROPCAP⋯),ioCtl(fd,VIDIOC-SCRoP⋯.),ioCtl(fd,ⅥDIoCSINPUT,...)等函数来初始化设备、设置输入输出能力,最后通过ioctl(fd,VIDIoCSⅡ通AMON⋯.)来获取数据,这些ioctl系统调用在内核里的具体实现是由C锄era控制器驱动完成的。结束预览时通过close系统调用关闭设备。所以,在V4L2标准下其预览流程如图5.1所示。 图5.1WL2标准下的Can埘a预览流程图图5.1的流程是在V4L2标准中存在的规定流程,从打开设备到预览结束关闭设备都需要遵从这一标准,V4L2标准同时也为这流程提供了相应的接口以便具体实现时去完成相应的功能。5.1.2“nux驱动层实现在C锄era模块的驱动层实现之前,本文对Lin_u)【下的驱动进行简单介绍。LinuX驱动通常是以模块编译入内核里。在Linux内核的源码里,每个需要编译入内核的模块目录下都存在Make61e和Kconfig文件,它们会指示编译器把哪些模块编入Linux内核,可以通过修改这两个文件来把需要的驱动程序编入内核。例如在“ver目录下新建一个驱动程序teSt.c文件,并把它编入“nuX内核。只需把0bj.y+_test.o加入越ver目录下的Makefile文件最后一行即可,它表示直接把test.c编入内核。但这样做的话,在通过makem咖c0Ili龟配置内核时就不能看到与test.c相关的配置,这样不利于内核的管理,通常还需要配置文件所在目录下 28基于Android系统的C锄era模块设计和实现的Kconfig文件,如在Kconfig文件最后添加如下代码。在Make61e文件最后加入0bj-$(CoNFIGTEST)+=tcst.o,这表示通过配置TEST宏的值来决定是否把该文件编入内核,通过Kcon69的配置在配置菜单ddver子菜单下会显示fortest选项,默认是选中的,其帮助文件会描述"fork锄el缸vertest,’,通过这样的操作就可以把需要编入内核的文件添加进去。而在具体的代码里通过宏moduleiIlitO和moduleexitO来加载或卸载一个模块,在Linux启动过程中会调用所有的moduleiIlit宏。这样就可以通过这个宏把为各个设备编写的驱动程序编译到内核里。通常做法是在这个宏的参数里放入需要执行的函数,“nuX在启动时调用moduleiIlit宏时就会运行这个函数。在C锄era控制器和Se嬲or的驱动里,可以通过h姒提供的接口intplat南m-_d嘶ce上百st呱s仃IlctplatfonndeVice}pdev)和intplatfomdriv砑re西st呱stmctplatfo姗driver}drv)来关联设备和驱动。把设备和驱动相关的信息分别保存在s仃uctplat向mdevice,stnlctpla响m“ver结构体里。通常设备驱动会把开发板上的大量设备放在一个plat向nIldeVice结构体数组里,通过plat南mdevicere西ster函数把这些设备一次性注册到内核里,再分别在各个设备的驱动程序里调用platfoml“verre百ster通过设备名称来完成设备驱动的匹配。由于通过这两个函数的调用最后都会执行s仃I=哦platfo肌嘶v盯结构体里的probe函数,所以需要在probe函数里初始化设备并定义与用户空间操作相关的接口。Camera模块所需要实现的C锄era控制器驱动和C锄eraSellsor的驱动都可以通过这样的方式来编译入内核的。1.C锄era控制器驱动实现在Ijnux里提供了与V4L2相关的源码。相关的头文件在inclllde/modia目录下,有v412.common.h,v412.ioctl.h,v412.dcv.h等;相关函数的实现在嘶v酬IIl础a/Vide0下,有v412一deV.c,v412.ioctl.c,v412.common.c等文件。它们提供的一系列函数和接口可以用来方便的去设计V4L2标准下的驱动程序。在v412.dev.c里,提供intvide0re西sterdevice(s咖ctVide0deVice奉vfd,谳type,int叫函数来注册新的V4L2设备,其相关结构体s饥lctvide0device定义在v412.dev.h里,它的作用是注册新的V4L2设备,在用户层创建V4L2设备的设备节点以供用户层调用。C锄e豫控制器驱动就需要调用它在用户空间创建的节点以让应用程 第五章Android下的C锄啪模块实现序与Camera控制器进行交互。传入的参数s仃uctvidc0device包含了相应的C锄era控制器的信息和通过用户层设备节点对Camefa控制器进行操作的函数。Camefa控制器驱动的主要任务就是完成与与C锄era控制器操作相关的函数,以便用户层的调用。C锄era控制器驱动通常会放在“vefs/mcdia/video/Xx()【)【为芯片供应商)文件夹下:在该目录下新建一个C文件,通过修改或新建Mal(efile,K七on69文件来把该文件编入内核。在代码里通过新建结构体s饥lctplatfo姗ddverC锄硎fdrivef,s咖ctplatfomdeviCeC锄eraifdeVice来保存与Camefa控制器相关的信息。然后通过,platfo叫v町e百ster函数来关联设备私有信息和驱动所需的操作函数。通过moduleillit()宏来加载模块。新建Calne抛控制器结构体s扛ucts3cfimccon缸Dl用于保存C锄era控制器的编号、名字、时钟信息、中断号、strIlctvide0devicc等。在CaIIlcraifdriver的probe函数里需要初始化s3c6mccontrol,并通过调用vide0re百st盯device(s仃tlctvideojevice毒vfd,缸t),pe,洫呻函数来注册为V4L2设备,传入的第一个参数为s岫lcts3cfimccon仃ol里的s咖ct啊dc0device,它会保存这个C锄em控制器关于V4L2设备的特有信息和操作,第二个参数是宏Ⅵ?LTYPEG秕姬BER,在V.4L2,,提供的Linux代码里它表示视频设备,还有几个宏Ⅵ'Ln俾EⅦI,VFLn俾E黜蛐IO等分别表示电视信号设备,音频设备等,在这里Camem属于视频设备,所以用VFLn俾EG】认BBER。不同的设备在用户层默认创建的设备节点名称不同。第三个参数是结构体s廿ucts3cfimccon臼∞l里的C锄e豫控制器的编号,函数会根据这个编号决定Camem控制器设备的次设备号,从而在用户层创建不同的节点来区分不同的C锄era控制器。至此probe函数里的内容基本完成。接下来就是与V4L2设备的设备节点在内核中的相关操作的实现,具体由vide0de讥ce结构体里的smlctfileoperations结构体来实现。需要完成s饥Ictfil幽peratio璐结构体里函数。具体需要实现的函数有0pen()、release()、ioctl()、read()、mmap()、pollO等。其中ioctl函数指针需指向video_joctl2,它是v412一ioctl.c文件里的一个函数,会根据不同的ioctl命令分别调用vide0device结构体里的s饥磁v412ioCtl0ps宰ioctl.ops操作集。所以对V4L2设备的ioctl操作的实现就是对vide0de访Ce结构体下的s咖ctV412ioCtl0ps·ioctlops操作集函数的实现。以下对各个函数的具体实现进行分析,指出在具体的实现中需要用到的Lin_u)【接口函数以及其用法。1)0p∞函数在opeIl函数里的主要任务是初始化和配置C锄era控制器,通过“n_11)【提供 基于Andmid系统的C锄era模块设计和实现的readl(constvolatilevoid_jomem幸addr),writel(u32b,volatilevoid—jomem事addr)函数来对控制器寄存器进行读写。由于LinuX内核的寻址空间是3G_4G。所以Linll)【内核并不能访问所有的控制器寄存器地址,内核提供了ior锄ap函数来把控制器寄存器地址转化到内核可以访问的地址。其中re棚()函数的参数是一个寄存器地址,它是通过ior锄ap得到的可以在内核下操作的控制器寄存器的地址;、而tel()的第一个参数是要写入控制器寄存器的值,第二个参数也是通过ioreIIlap映射得到的可以在内核下操作的控制器寄存器的地址。由上节对C锄era控制器的初始化顺序可知需要做的有设置控制器模式、软件复位、初始化其他寄存器等部分。writel(S3C--cISRCFMTrrU60l-8BIT,S3qCIsRCFMT);//选择C锄era控制器模式为ITU.RBT.601YCbCr8-bit模式、柑tel(S3C._cIGCTRI,SWRSTIS3C_-CIGCTRL_皿Q-LEVEL,S3c_-CIGCTRL);另一些如裁剪、旋转功能的寄存器都可以用linux提供的、砸tel函数初始化它们的值。2)rele嬲e函数在release函数里需要在C锄era应用程序关闭时把一些与C锄em控制器相关的全局变量置为空、释放为C锄e豫控制器驱动中申请的内存以节约系统资源,可以使用Li姗x提供的k触函数。3)read函数rcad函数作用是读一帧数据,供C锄era应用层调用,在函数里需要调用w龇eventnen呻tible函数等待一帧数据完成,并通过C0pyt0jlser函数把数据送到用户空间。4)mmap函数nⅡn印函数通过内存映射把一段内存映射到用户空间,这样做的目的可以使用户空间的应用程序和内核空间的C锄era控制器驱动都可以操作同一段内存。所以在内核空间的一帧数据不需要通过copytouser函数用户空间就可以访问了,这提高了用户空间和内核空间之间的交互效率。主要通过Ijnl】】【提供的r锄ap_pmgc函数实现。5)ioctl函数ioctl函数是用户配置和控制c锄era控制器的主要接口,是C锄era控制器驱动的一个重要的部分,需要根据V4L2标准在Li伽x内核中提供的接口去实现。在V4L2标准下,C锄era预览时这些ioctl函数在C锄era控制器驱动里所需要完成的操作流程图如图5.2所示。. 第五章Android下的C锄em模块实现3l图5.2Ca蚴控制器驱动i硎调用流程图图5.2描述了V4L2标准下,Camera控制器完成预览所需要调用的ioctl函数的流程图,其中的各个功能都需要在C锄era控制器驱动里的ioctl函数里去实现。在linux下,V4L2标准里对这些ioctl函数进行封装,提供了标准的访de0ioctl2函数,其具体实现是在Ⅵdc0devicc结构体里的咖ctv412iocⅡ0ps木ioctlops里。它包含了V412标准里的所有iocu接口,下面是V4L2标准里提供的与C锄era相关的一些ioCtl的说明如表5.1所示:表5.1V4L2标准里提供的与c锄em相关的一些iocn命令及说明VⅢIOqCRoPCAP—hlfonnationabouttl圮vide0蝴ing锄dscalillgabiliti髓ⅧIoC踟,MFm—E蝴e眦ilnagefo蚰鹏VmIOC覃【NIIMFl啪SIzES~五:n:l:吼emte纳mesiz髓VDIocG:cRo只VDIoescRoP—Ge£0rsct啦ec啪耽t伽棚ngrectan酉eVⅡ)IOCGnU;己M—Getorsets妇汜锄ingpammete璐 32基于Android系统的C锄era模块设计和实现V4L2标准为C锄efa模块提供了一系列ioctl所需要宏的定义。在“nuX里,这些宏定义在inClude/LinllxMdeodcv2.h型121。但在内核并不需要实现所有这些ioCtl操作,因为Camera设备只是V4L2设备里的一种,只需根据C锄era控制器的特点和需求选择实现其中的一部分即可。例如为了实现一个预览功能,需要实现的函数有ⅥdioC_querycap,vidioC_cropc印,啊dioc:$啪p,Ⅵdioc蔓inp此vidioc:eImm筋t-Vid』ap,Ⅵdioc:s矗nt_yid』ap,vidioc|一reqbufs,vidio唧crybu£v412-s-pann.,vidioc_s骶amon,vidiotdqbufo下面对这些函数进行必要的介绍和分析。1)vidioc_queryc印通过该函数获取C舢控制器支持的操作,如预览、拍照等。相关信息存放在s仃uctv412c印ability结构体里。用户和内核通过传入传出这个结构体来交互信息。2)vidioc:cropcap和vidioc母啪p这两个函数用于获取C锄e豫控制器截取图片的配置,在6410芯片里是通过这两个ioctl配置C1wDOFsT寄存器的。通常使用默认的就可以了。3)Vidioc:sinput该函数用于获取V4L2设备的种类,供HAL判断是哪种V412设备。根据C锄era控制器的设备信息,提供给HAL层。4)Vidiocen吼蠡ntvidcap和vidiocs丘ntvidcap这两个函数用于获取设备输入和输出分别用什么格式,6410芯片的控制器以YcbCr方式接收数据,最后会以JPEG输出。5)vidiocLreqbu6通过这个ioCtl函数在内核里为一帧数据分配内存,并配置与DMA相关的参数。6)V412_S』aml该函数用于采集帧数据和设备初始化,在64lO控制器上帧数据通过控制器上的DMA传输,这个函数里要重新开始DMA以准备获取新的数据。具体通过操作C锄efa控制器上的寄存器MSCOCTRL来对DMA进行操作。 第五章An出0id下的C锄锨模块7)Vidioc-s骶锄on该函数用于开始采集数据时调用,函数里需要初始用C锄efase∞0r驱动里的c锄em初始化函数。通过DMA从外设接口采集数据。8)vidioc-dqbuf该函数用于处理帧数据转化为jpeg格式。具体函数由jpeg相关模块实现。2.C锄eraSe璐or驱动实现目前大多数的C锄eraSe粥or都是12C设备,与它内部的寄存器通信需要符合12C协议。如果C锄efa设备与芯片通信的12C接口接在芯片的12C控制器上就需要利用到LiImx12C的一些接口函数,这些接口函数对12C控制器的具体操作是在12C控制器驱动里实现的。但由于12C控制器上如果接较多的设备会影响通信效率(比如轨迹球、Gse硼or等设备也会接在12C控制器上)或芯片上没有12C控制器时可以利用芯片上的GPIO模拟12C协议与C锄emSensor设备通信,以代替12C控制器。本节第一部分会介绍如何利用I,i玎砥下的12C驱动接口(主要是读写两个操作)编写C锄eraS吼sor驱动。第二部分通过分析12C协议,编写使用GPIo模拟12C的代码(读写两个函数),并使用它使驱动程序与C锄emSensor设备进行通信,最后编写相应的C锄eraSe哪0r驱动程序。。,371)利用№提供的12C驱动接口编写C锄emse船or驱动同C锄efa控制器驱动一样,C锄emSeIlsor驱动模块也通过修改相应的Makc丘le和l;:config文件把需要的驱动代码的C文件编入内核。通过程序里的moduleini“)和n10dllleeXit()来加载或卸载这个模块。驱动在初始化和配置C锄emS%sor时需要操作12C控制器与C锄emSeIlsor进行通信,所以按照I,inux里使用12C控制器的规则可以新建一个s仃ucti2c“ver的变量来保存Camerasesnof的12c信息。目前内核支持两种编写i2c驱动的方式,分别为“Adapter方式"、“Probe方式"。它们都是通过i2cadd“v叫)函数向内核里注册这个12C设备来实现驱动的加载。不同的方法构建的i2cdriver结构体里的所需要的实现的成员函数也不同。如果采用Adapter方式,i2cddver结构体需要实现attachadapter,detachclient,commaIld函数,采用Probe方式需要实现probe,remoVe函数。关于Ad印ter方式里attaChad印ter函数的实现,此函数的主要作用是通过in_ti2cpfobe(s衄Icti2叫apter枣adapter'co邶ts们llcti2c:-clientaddress』ata·addresoata,int(木fouIldJroc)(灿Cti2cL砷apt盱宰,i蝇n))函数传入的第二个参数(C锄erasesnor的设备地址)探测该设备是否存在于12C控制器上,如果存在会调用第三个参数传入的函数。所以需要第二个参数传入正确的C锄e豫S锄0r设备地址,并且实现申请i2C一.aient,并且把申请到的i2cdient传给C锄eraseIlsor 基于Android系统的C锄e髓模块设计和实现的私有结构体,使它能够在需要与C锄erasensor设备通信时使用它的函数,把函数指针穿给i2cprobe()函数的第三个参数。关于Adapter方式里command函数的实现,这个函数主要是实现对C锄eraScllsor初始化或配置的选择。通过传入不同的参数来决定初始化所有C锄eraSellsor寄存器还是只对某些寄存器进行重新配置。Adapter方式的detachclient函数主要是把注销i2cdient,通过i2cde切rchclient()函数实现。Pfobe方式的probe()函数主要任务是初始化一个i2cclient,让驱动可以利用这个client与C锄eraS饥sor设备通信。Probe方式的r锄ove函数也是通过i2cdetachcli既t()注销申请到的i29_client。因为这两种方式都是通过i2cadd“ve“)函数来注册的,函数里面会检查姗cti2c赫ver变量的成员函数的实现情况来决定使用哪种方法。probe方式是一种新的方式,这种方式把C锄emSe珊or的具体初始化和配置函数和需要的12C通信函数分开。这里使用这种方式来实现C锄eraS吼sor所需要的通信接口,另外去实现CameraS%S0r的具体初始化和配置函数。新建i2c“v盯的变量并通过i2cadd蹦v呱)来注册设备,i2cadd嘶vero函数会初始化一个新的i2ccli朗t并传入probe函数里。这里需要实现的就是在probe函数里进一步把与C锄eraS饥sor相关的数据加入这个i2cdient并利用它操作12C控制器与CameraSensor通信。具体可以利用i2c仃a∞船函数传入i2ccli饥t的适配器和需要传送的信息来实现。C锄emSenS0r的驱动部分可以通过调用platfomldevicere西st%platfo肌姐vefre百Ster来注册CalI姗SeIlsor设备,在结构体plat南肌蹦v盯的pD0be函数旱提供C锄eraSellsor的初始化代码,但CameraSeIlS0r却没必要在用户层创建设备节点,因为它和C锄em控制器协同工作,只有在C锄era控制器需要时才会需要初始化CameraSenSor。而probe函数只会在L姗呱系统初始化时运行一次,供系统检测是否存在C锄era设备。所以需要为CameraSeIlsor在其他地方提供初始化和配置函数。所以在CameraScIlsor里需要做的主要工作就是C锄craScllsor的初始化和配置代码的实现。主要工作是使启动、配置Came豫Sensor使其正常工作,其流程如图5.3所示。 第五章Android下的C锄e随模块实现35图5.3Came随Se∞or初始化流程图5.3描述了C锄emSeIlsor的初始化流程,其每一步详细实现如下:第一步:上电。开发板上会包含一个PMIc来管理硬件的电源。该设备也需要一个驱动,不同的PMIC与芯片通信的方式也不同。这里只需要利用驱动提供的接口就可以了。例如在高通的7227平台上利用wegsetlevel函数即可把与C锄efa相连的相应的pin脚电压设为一个值。第二步:硬件复位Se邮or。通过改变GPIO的值来拉高拉低pin脚。关于GPIO也是需要驱动的,每个GPIO的值都对应这芯片上的某些寄存器,通过这些寄存器值的改变来配置GPIo,通常芯片厂会在“nux里提供接口的。在高通7227平台里,提供的接口有gpioirectioll』删int,i11t),它把GPIo号为第一个参数的piIl脚设为输出并把它的值设为第二个参数的值。第三步:给ScIlsor提供时钟。这也是通过对芯片的操作实现的,也需要驱动,高通7227平台给的函数是msIll.camioclkrateset(int)。第四步:使PWDN不为使能状态,和第二步一样配置某个GPIo的值。第五步和第六步实际上都是对C锄eraSeIlsor里寄存器的配置,在OV系列的C锄eraseIlsor里使用SCcB协议与cPU通信,该协议与12C协议兼容,所以 36基于Android系统的C锄em模块设计和实现这里只需调用12C驱动提供的接口与它通信即可。2)使用GPIo模拟12C编写C锄emSeIlsor驱动这种方式需要把C锄era设备的SCL,SDApin脚接在芯片的普通GPIO上,通过对GPIO的操作与C锄eraSeIlsor通信。当然,它需要符合基本的12C协议。由于这两个GPIO只接CameraS胁sor一个设备,所以该模拟函数不必像12C控制器那样需要处理多个设备之间通信冲突问题,只需关心最基本的协议即可。12C基本协议如图5.4所示:SnASCL8t献俐锄翩触删蒯笋。1厂1■弋—Y—V■r]rnlMS8————l-SBSf.八.J‘PA刀鼍酌p∞喇嘲∞图5.412C协议标准基本规则图5.4中的SDA,SCL分别代表着数据线和时钟线。它们的高低代表着处于高电平或低电平。它们之间通过在某个时段的配合来实现某种意义。12C设备分为主设备和从设备,它们之间通过这两个SCL'SDA的连接、配合来实现通信。在开发板上,12C控制器或模拟12C协议的GPIO就是主设备,而外设上的12C设备如C锄eraSeIlSor就是从设备。关于以12C协议传输数据存在开始位、结束位、应答位等概念。开始位:在SCL为高时,sDA如果产生一个下降沿,表示开始传输数据。如图5.4最左边的方框所示。结束位:在sCL为高时,SDA如果产生一个上升沿,表示停止传输数据。如图5.4最右边的方框所示。应答位:当发送方传送完8位时,发送方释放SDA,由接收方控制SDA,使SDA为低,表示接受到正确的数据【引。如图5.4中标写A的地方所示。GPIO模拟12C需要两个GPIO分别模拟时钟线SCL,数据线sDA。这两个GPIO通过拉高拉低来模拟SDA,SCL的高低电平。使用GPIo模拟的12C与外设通信和使用12C控制器驱动提供的接口不一样,12C控制器驱动提供的接口一般只需要把设备地址、需要操作的寄存器地址传入即可,但使用GPIO模拟不仅需要完成读写字节的操作,还需要知道外设读写流程。每个12C外设(从设备)都有一个7位的设备地址。读写12C设备时,发送的第一个字节会是设备地址的7位加上最后一个读写标记(读为l,写为O)。 第五章Android下的C锄em模块实现写操作的顺序是:开始传输,发送设备地址(包括标记位O),等待ACK,发送寄存器地址,等待ACK,发送要写入该寄存器的值,等待ACK,停止传输。读操作的顺序是:开始传输,发送设备地址(包括标记位O),等待AcK,发送寄存器地址,等待ACK,重新开始传输,发送设备地址(包括标记位1),监测SDA数据线,接收读取到的数据。在I,inuX里,还需要注意配置GPIo的方向,当主设备需要操作GPIo时需要把GPIO设为输出,在从设备操作GPIO时,需要把GPIO设为输入。由于只有主设备可以控制SCL数据线,所以只需要注意SDA的方向即可,通常在主设备接受ACK,或读取数据时SDA的控制权为从设备,这是需要配置GPIO的方向为输入。例如GPIO模拟12C开始位可用以下代码:通过操作GPIo来配置SCL,SDA,通过udela),()函数来实现GPIO值所要保持的时间来达到模拟12C协议的效果。简单介绍下udelay()函数,它是实现内核忙等待的函数。为了使GPIO值保持一段时间,需要用到类似的延迟函数。类似的函数Ijmlx里还提供了usle印()函数,它是通过使这个进程休眠以达到延迟的作用,但不会使CPU处于忙等待状态,在这里使用udelay是因为llsleep不能再中断上下文中使用。而使用的12C操作时常需要在中断里与C锄eraS哪0r通信,所以需要使用udelay函数而不能使用会产生休眠效果的llsl唧函数。其他的功能如结束位、传送一个字节,接受一个字节都可以用类似的方法实现。最终用这些功能函数实现对12C设备的读写函数。这部分使用GPIo模拟12C的读写是代替Li肌x下12C接口i2c仃觚sf打函数的功能,只关系到.C锄eras饥sor驱动里与设备寄存器通信的部分,其他的代码和上节使12C控制器的代码一样。 38基于Android系统的C锄era模块设计和实现5.2C锄era模块的普通字符设备方式实现上节是通过V4L2标准实现的C锄era的HAL层和C锄era控制器的驱动。C锄eraSellsor的驱动由于只是关系到C锄eraseIlsor本身的初始化和配置,并不属于V412标准的范围。所以,C锄efaSenSor部分的驱动是通用的,利用上节实现的代码即可。5.2.1HAL层实现HAL层由于是要操作C锄era控制器在用户层的节点,所以需要根据C撇efa控制器的驱动来具体考虑,如果在Camera控制器驱动里把C锄era控制器注册为多个字符设备,那么在HAL层就需要根据C锄efa控制器驱动的结构作相应的调整,所以在普通字符设备方式写的C锄era控制器驱动里,HAL的变化必须符合C锄era控制器驱动的变化。但其流程与V4L2标准下的HAL层类似,例如需要通过ioctl给C锄em控制器发命令初始化和配置Camem控制器,通过ioCtl配置C锄era控制器上的DMA,通过iocn或伽nap函数来接受一帧图像数据。需要注意的是由于没有使用V4L2标准,V412定义的ioctl在用普通字符设备驱动模式写的c锄efa控制器驱动也就都不能使用了,需要重新定义可以使用的io以宏。在LinuX下定义ioctl系统调用需要有一些规则:ioctl函数用户层原型是intioctl(intfd,强si印edlongcmd,⋯)。fd是文件描述符,是通过系统调用open打开一个文件后所返回的。伽m是用户程序对设备的操作命令,是用户层与内核层确定是哪个系统调用使用的,其值通过用户层传到内核层,所以需要在用户层和内核层定义相同的值以正确匹配。⋯代表着可变参数,但在实际系统中,系统调用不会使用可变数目的参数,而必须有精确的原型。所以从本质上讲每个ioctl命令都是一个独立的系统调用。在编写ioCtl代码之前需要对不同的操作进行编号,即参数cmd的值。为了创建唯一的ioctl命令,Lin_11)【把一个命令分为多个位字段,LinuX第一个版本使用了一个16位的整数:高8位是与设备相关的“幻”数,低8位是一个序列号码,在设备内是唯一的。在Linux头文件<删n/io谢.h>里定义了一些构造命令的宏jo㈣c'nr)用于构造无参数的命令编号;joR(type,屿dat哟l,pe)用于构造从驱动中读取数据的命令编号:jo.W(type,屿dat的憎e)用于写入数据的命令;jOWR(type,屿datatype)用于双向传输。Type和nr是两个位字段通过参数传入。V4L2标准的ioctl命令就是用这种方式构造的,所以在用V4L2标准操作时就不必重新定义这些命令,直接用就可以了。例如在为CaIIlera设备创建一个向设备写入的ioctl系统调用。首先需要定义 第五章Android下的C锄e豫模块实现39一个“幻”数,通常它是一个字母如’c’,撑defineC州oCMAGIC“c,’,它与这个Ca删湘设备相关。再为对设备的每个操作定义操作命令,如对C锄em配置Camem亮度的操作命令树efineCIAMSETB刚GHTNESS-IoW(CAMjOCMAGIC,l,int).这样就定义了C岬ET.JRIGHTNESS命令,在HAL层和内核层都需要这样定义一下以保持命令的一致性。5.2.2Lill.吸驱动层实现L汹隧驱动层实现主要是C锄era控制器驱动的实现,C锄eraS吼sor驱动与V4L2标准下的驱动一样。以下是实现camera控制器的驱动。.普通字符设备就按照一般的字符设备去注册。首先定义一个s饥lct6leopera:tions结构体,它负责字符设备节点的各个操作。需要定义的操作函数和V4L2标准的类似,有0peIlO、rcl哪co、ioctlO、阳adO、writeo、I眦ap()。其中0peIl'rele硒e,豫ld,、)l,rite,mmap函数和V4L2标准里的类似。但在ioctl函数里需要像上节所说的,定义一些iocⅡ命令所需要的宏,iocⅡ函数也不能再用v412.ioCtl.c文件里定义的、,id∞ioctl2函数,因为自定义的ioCⅡ只需要考虑这个C锄em控制器字符设备,不需要再去分类。在ioctl函数里只需要通过c舔e某个命令,再给。。出对应的操作即可。在ioCtl里需要实现的命令函数和V4L2类似,也可以自定义一些操作,比较灵活。必须实现的有初始化和配置C锄era控制器并调用C锄eraSensor初始化函数的命令,配置准备DMA传输的命令,开始DMA传输,获取图像帧数据的命令,也可以自定义一些命令来在适当的时候操作一些C锄era控制器寄存器,比如让图像旋转,改变图像传输格式等。代码流程可以按照以下步骤,用allocchfdevrel;ion函数来分配字符设备空间和动态分配字符设备的主设备号;通过cdeviIlit函数来关联字符设备和它对应的操作,通过cdevadd函数来添加字符设备到内核;再通过cl舔screate函数创建一个类,它会在虚拟文件系统sys/cl嬲s目录下创建一个文件夹,最后调用device蹦斌e函数并以c1鹤screate函数创建的类为参数,这样会在syS/d嬲s目录刚创建的文件夹下根据设备名称创建一个文件夹,之后会通过deVicecreatefile函数创建ucvent等文件,用户空间会根据这个uevent自动创建设备节点。这样HAL层就可以通过这个设备节点与C锄e豫控制器进行通信了,对设备节点相关的操作已在驱动里s仃uctfileoper撕ons结构体里的函数实现了。用普通字符设备去实现C锄era控制器驱动也不必一定只注册一个设备节点。为了进行某些寄存器之间的配合,少用ioCtl函数,也可以注册多个设备节点,让HAL层有更多的灵活性。总之,用普通字符设备实现的HAL层和C锄e豫控制器驱动灵活性较大,可 基于Android系统的C锄era模块设计和实现以为用户层提供较大的修改空间,需要实现的东西也较多。用V4L2标准写的可以利用的接口较多,但需要多配置一些参数,但通常只需要按照一定的流程去写即可,不需要重新设计模块的框架。 第六章C锄e豫模块的测试4l第六章C锄era模块的测试Amdroid下的C锄era模块由上层应用程序、HAL层、C锄era控制器驱动、C锄e豫SeIlsor驱动组成。当在应用层打开C锄era应用程序时,在LCD屏幕上可能会出现黑屏、有图像但图像不正确、配置C锄era时出错或图像效果很差等问题。但从直观上无法判断C锄era模块在那个阶段出现了问题,因为从上层应用到C锄era底层硬件都有可能存在导致以上情况的问题,而且和c锄em关联的其他模块也有可能影响到C锄era。本章会按照一定的顺序对Camem的每个部分进行测试,以便C锄era出现问题是能够迅速的发现错误,找出错误产生的原因,并给出正确的解决方法。6.1C锄era模块的测试环境进行测试需要的基本硬件测试环境如下:·PC机一台●s锄趴ln96410开发板一块·示波器一台◆电压表一个·串口线一根●C锄em摄像头一个●各种C锄era效果测试卡其网络拓扑图如图6.1所示:(已装头)图6.1测试所需硬件的拓扑图图6.1是测试所需硬件的拓扑图,需要在PC机装Ub瑚加操作系统(其它Linux发行版或WiIldows也可),串口工具如:millicom,在PC机端通过串口工具观 42基于Android系统的C锄era模块设计和实现察和控制开发板,通过电压表、示波器等测试C锄era硬件状态。通过开发板的显示屏观察Camem效果。6.2C锄era模块的功能测试C锄era模块的测试本文按照从C锄era硬件、CamemSeIlsor驱动到C锄盯a控制器驱动以及HAL层的顺序进行。’6.2.1C锄em硬件测试C锄era硬件是C锄era模组厂商对C锄eraSenS0r的重新封装。模组厂商会在封装之后提供camI溉硬件关于镜头、pin脚等相关信息。在硬件方面需要比对C锄era硬件和芯片上的’C锄era接口使他们一一对应。1.测试目的检测C锄e托硬件设备是否完好,与开发板的连接是否正确,芯片提供给C锄em的电压、晶振是否正确。2.测试项和测试步骤1)连接测试在驱动程序里用Ijnll】【提供的GPIo驱动对piIl脚进行配置,使他们或高或低,并读取G-PIO的值,观察其是否能够正常操作。2)电压测试在开发板上运行Android,打开C锄em应用程序,使其处于预览模式。用电压表检测C锄era硬件的三个piIl脚AVDD、DOVDD、VDDl.8的三个电压值,观察其是否分别为2.8V、2.8V、1.8V。3)外部晶振测试同样打开Android应用程序,在应用程序进入预览模式时,用示波器检测C锄era硬件上的MCLKpill脚,观察示波器,看示波器上显示的频率是否与驱动代码里提供的一致。3.测试结果及分析GPIO都可以正常操作,电压表显示的电压与代码提供的电压只存在微小的差异,示波器显示的频率和通过代码操作芯片提供的频率只存在微小的误差,不影响整体结果。 第六章C锄em模块的测试436.2.2I.inlⅨ驱动测试1.测试目的确保‰驱动层按照一定的步骤去操作设备,不出现错误,对芯片和C锄efa硬件的操作都能正确执行。2.测试前提’在需要调试驱动的内核里也需要开发板芯片上的串口驱动的支持,并且在编译前使用makem艄n堍配置的时候也需要把串口驱动编译进内核文件,并在kenlelhaddng菜单选择相应的需要打印的信息。3.测试和调试方法’IjnuX驱动调试常用的方法有触kgdb,opps等方式,也可以使用第三方软件和硬件进行调试如缸.ace32,MultiICE等锄仿真器进行调试,但这些仿真器软件都较为复杂,需要特定的脚本来实现某些调试功能,而且这些仿真器的硬件设备都比较贵。但在C锄e豫模块驱动的调试里,常用的方法就足够了,而且成本也很低。常用的触kgdb,opps方法需要串口的支持,因为调试信息需要通过串口与主机交互,显示在主机的显示屏上。1)眦方式LinuX内核里的曲n位()函数和c标准的prifItf【)函数很类似,是内核里打印信息的函数。通过在内核特定位置调用眦()函数可以把所关心的信息通过串口打印到主机屏幕上,从而可以观察程序的执行过程和所关心的变量或指针的值,其原型为衅(constch盯事缸t⋯.)。它与pIiIltf不同之处在于它可以附加不同日志级别,可以让雠根据这些级别对消息进行分类。通常用宏来指示日志级别。在里定义了八种不同级别的日志字符串。例如ⅪzIⅢINFo,表示提示信息;KERNW舢斟ING用于对可能出现的情况进行警告。默认的级别是DEFAULTMESSAGELOGLEVEL。例如:prifItk(“nlisisates恤,’);命令与p血墩(DEFAULTMESSAGELoGLEVEL‘恤sisates衄”);命令是相同的。根据日志级别,内核可能会把消息通过串口打印出来。当优先级值小于consolejo西eVel时消息才会显示出来。consolejo哲evel初始值是DEFAULT-MESSAGB_王。oGLEVEL,可以通过sySlog系统调用修改其值。2)KGDB方式GDB是GNU开源组织发布的一个uNⅨ下的程序调试工具,KGDB提供了一种使用GDB调试Lin_u】【内核的机制。使用KGDB可以像调试普通的应用程序那样,在内核中进行设置断点、检查变量值、单步跟踪程序运行等操作。它可以通过一系列KGDB的命令,在主机端给开发板发送命令进行调试。调试过程中, 基于Android系统的C锄em模块设计和实现被调试的内核运行在开发板上,GDB调试器运行在主机端。4.测试项和测试步骤1)C锄eraSellsor驱动测试上电,由于C锄efaSeIlsor上电需要一个上电时序,可以通过示波器分别检测两路电,观察他们是否符合上电顺序。硬件复位,硬件复位是通过操作rcs邑pin脚实现的。通过Linll)【提供的GPIo操作,在复位操作的时候分别读取它的值,再通过龇函数打印出来,以确定reset操作是成功的。PWDNpiIl的不使能。和复位一样通过,通过GPIO的操作来确定其执行成功。至此,C锄eraSe粥or已开始工作了,芯片已可以通过Ijn_11)【驱动提供的12C接口与C锄eraS饥sor通信了,接下来就是确保12C通信的正常。利用12c通信的相关接口去写相关寄存器,然后再去读取寄存器的值确保对寄存器操作的正确。通过初始化相关寄存器后,C吼盯a就可以工作了,在c锄era设备的data[O.7】pin脚通过示波器就可以检测到数据的变化了。至此可以确保C舭lemSe邶0r硬件和驱动的正常,但还不能确定一些寄存器的配置是否正确,因为其中一些寄存器需要与C锄e豫控制器驱动配合。2.)C锄em控制器驱动测试C锄era控制器的一些配置需要与C锄eraSeIlsor的配置相同,如VSyIlc,href,pcll【极性,图像的Wbcr顺序等,否则Camera控制器会得不到正确的数据。首先要确保写入和读取寄存器的值是一致的。可以通过LinuX提供的re{ldl,嘶td函数进行测试。在驱动里的流程可以通过prirI墩函数打印到屏幕上以确保对控制器的操作流程确如驱动程序里写的那样。5.测试结果及分析通过串口打印的分析,与Came豫相关的pin脚都可以被正确的操作,C锄e豫硬件没有短路现象,C锄em硬件与芯片的连接也正常。C锄eraSellsor的寄存器都配置成功没有进入出错处理代码。C锄era控制器寄存器的读写都正确,读取的数据和写入的数据完全一致。6.2.3HAL层测试1.测试目的确保HAL层的代码和Android提供的C锄era接口相衔接,确保Linux驱动层提供的设备节点可以正常使用。2.测试项和步骤 第六章C锄em模块的测试451)批id接口实现打开№id下C撇era应用程序,在串口中输入logCat命令,观察串口的打印信息,是否出现错误提示。2)LiIl:弧驱动提供的设备节点打开Android下的C锄e豫应用程序,使其处于预览模式,观察串口工具miIliC0m的打印信息,判断HAL层对设备节点的0pen'ioctl等操作是否在驱动里被正确执行。一‘’3.测试结果及分析打开camera应用程序,对其进行预览、拍照等操作,串口工具millicom的打印信息显示C锄era的HAL层代码按照设想的步骤执行,没有打印任何出错信息,HAL层工作正常。,‘6.3C锄era拍摄效果测试在测试效果的时候,C锄em应用程序已可以在屏幕上显示出C锄era设备获取到的图像了,拍摄效果的测试就是需要对其中图像遇到的问题进行测试和调试,使其达到预期的效果。i毋在C锄em效果测试里直接通过人的感觉去分辨难以达到满意的效果。通常会辅助一些效果测试卡。如分辨率测试卡、24色卡、对比度测试卡、灰阶卡、灯箱等。这些卡通过放大实际的卡片图像与C锄efa的图像显示效果来供调试人员方便的找出图像的问题,有针对性的对图像进行微调。1.测试目的C锄era拍摄效果直接影响到用户对产品的体验,是测试重要的一部分。测试的目的是使c锄efa应用程序在显示屏上正确反映所拍摄到的实际物品。2.测试项和测试步骤1)图像的颜色打开眦id的C锄era应用程序,使其处于预览模式,用C锄e豫拍摄C锄era测试卡中的24色卡,观察屏幕中显示的颜色与24色卡上的颜色是否一致。24卡如图6.2所示: 基于Android系统的C锄era模块设计和实现图6.2C锄em测试卡中的24色卡图6.2是C锄era的24色测试卡,可以用来判断C锄e豫获取的图像颜色是否正确。2)图像分辨率打开Android的C锄era应用程序,使其处于预览模式,用C锄era拍摄C锄era测试卡中的分辨率卡如图6.3所示(或拍一张图片),观察图像是否出现线条模糊等现象。图6.3C锄e船分辨率测试卡图6.3显示Camem测试卡中的分辨率卡,通过拍摄图像和实际卡的图像对比就可以测试C锄era的分辨率是否达到一个好的效果。3)图像动态范围 第八章C锄em模块的测试47打开Amdroid的Camera应用程序,处于预览模式,使C锄em拍摄C锄era测试卡中的灰度卡如图6.4所示,观察屏幕和测试卡的图像偏色来确定C锄era的效果是否达到要求。图6.4C锄e豫灰度测试卡图6.4是C锄em测试卡中的灰度测试卡,可以测试C锄era的动态范围,信噪比等。3.测试结果及分析.了测试项1):如果屏幕显示颜色和测试卡存在较大的区别,可根据CameraS吼sor数据手册中的关于颜色的寄存器进行调节如:白平衡,在o'v2655SeIlsor中对应的寄存器为o】【3306寄存器。RGB色彩,在oV2655sellsor中对应的寄存器为0x3350.0】【3366寄存器。根据不同的色彩偏差对这些寄存器进行调节以达到最佳效果。测试项2):与图像分辨率相关的寄存器有锐利度、饱和度等,在OV2655中有o】【3370.o)【3379、oX3394、0】【3395等寄存器,参考其数据手册对这些寄存器进行调节然后反复测试以达到较好的效果。测试项3):与图像动态范围相关的寄存器主要是对比度的调节,在OV2655Sellsor中相关的寄存器有0)【3390、0x339l、0】【3398、0】【3399等。通过对相关寄存器的调节来反复测试以达到较好的效果。其他如测试工具如灯箱以及一些专业的硬件测试工具等较为昂贵,对C锄em效果要求不是非常重要的话用测试卡即可。项1)、项2)和项3)等C锄em测试之间还存在一系列关联,如项2)中如果锐 基于Android系统的C锄em模块设计和实现利度调节过高可能产生较多的噪点,对项3)也会产生一定的影响,C锄era效果的测试和调试并不能达到完美,只是在各项测试和尽量好的前提下达到一种平衡,从而实现C锄era相对较好的效果。 第七章结束语随着mldroid系统的逐渐成熟,批id上应用程序的日益丰富。基于Android系统的手机已越来越受人们的欢迎,国内外的芯片公司、手机设计公司都非常热衷于触id系统产品的开发。本文基于Am(1roid源代码和某款芯片的BSP,通过分析AndroidCamera模块的工作原理和工作流程,实现了眦id下的C锄era模块。在分析阶段把C锄em模块分为应用层、HAL层和LiIl_uX驱动层,通过分析这些层的关系,确定在一个开发板上实现C锄era模块的主要工作在HAL层和I.inlⅨ驱动层,在驱动层再把C锄cra驱动分为芯片上C锄era控制器驱动和用来.采集图像的C锄e豫S郇or驱动,并且分析了它们之间的关系和操作流程。在c锄era实现部分,根据分析阶段的结论,在HAL层利用An(1roid提供的接口实现C锄e托在HAL层的功能;在驱动层利用V4L2标准接口和普通字符设备驱动接口分别实现了C锄em的控制器驱动和C锄eraS%sor驱动。达到了对C锄efa模块工作原理和其一般实现方法进行总结的目的。在调试和测试章节,对手机用户更为关心的C锄e豫成像效果进行了分析,找到与其相关的软硬件方面的影响,通过给出的调试和测试方法去使c锄e豫的成像效果达到最佳以满足用户的需求。本文详细介绍了Am(hoidC锄era模块的框架,为龇id下的c锄era模块开发提供了模板。由于Android的各模块结构类似,也可以为Android下的其他模块的开发提供参考。本文虽对A麒koid下从HAL层到驱动层进行分析和实现,但由于本人水平有限,对眦idC锄era模块的应用层没有做详细的分析,这部分内容会在以后的工作学习中进行分析和完善。 50基于Android系统的C锄em模块设计和实现 致谢5l在论文所述内容的实际开发和论文的写作中,得到了各位老师、同学和实习单位同事的帮助。在此,向所有支持我论文写作的人们致以深深地谢意。首先要感谢我的导师郭万有教授,这篇论文是在郭老师的指导和帮助下完成的。在论文选题和写作过程中都得到了郭老师的悉心支持和帮助。郭老师渊博的专业知识,严谨的治学态度,平易近人的学者风范使我不仅学到了很多知识,更学会做人做事的道理,再次对敬爱郭老师表示感谢。特别要感谢在上海贝尚实习期间指导我工作、给予我帮助的高级工程师陈琦。实习期间,陈老师在学习和工作上给了我极大地帮助,他孜孜不倦的学习态度、乐于助人的精神是我学习的榜样。感谢软件学院提供给我学习的机会和条件,感谢学院的各位老师,他们在研究生阶段两年多的关心和帮助,使我愉快的度过了研究生阶段。感谢我在上海贝尚实习期间的各位同事和和我一起实习生活的同学,他们在生活和工作上给了我许多的帮助和支持。 参考文献53[1】宋宝华.LIMⅨ设备驱动开发详解.人民邮电出版社.2008【2】(美)科波特,魏永明(译).LINIⅨ设备驱动程序(第三版).中国电力出版社.2006【3】(美)博韦、西斯特,陈莉君(译).深入理解UNlUX内核(第三版).中国电力出版社.2007[4】(美)拉芙,陈莉君(译).LinuX内核设计与实现(第二版).机械工业出版社.2006【5】韩超、梁泉.Android系统原理及开发要点详解.电子工业出版社.2009【6】Qualc0I砌公司,Android』锄哪o、,e耐cw等文档.2010【7】oVT公司.OV2655等c锄盯aseIlsord她劬eet.2010[8】12C协议标准2.1.2000【9】www.粤m.org.乎mmakemanual.2010【10】Wolf窑锄gMauer盯.ProfessionalLiml】【K啪dArCllitectllre.WROXPR/PEERINFORMATIoNINC.2008[11】Sre“曲maIlVeI:11【atesw删1.Ess%tial“棚xDeviCeDrive娼.PrenticcHall.2009【12】h卸://v412spcc.b”eseX.org.V4L2APISpeci6cation(RcvisionO.24).2010【13】TravisS、)I,ic9900d.Pr卿aticVersionCon昀lUsingGit.PRAGMATICBooKSHELF.2008[14】Goo百e公司.Anatomy&PllysiologyofAndroid.2009【15】R咖Mei既Professio砌Android√伽licationDevel叩.WROXPR/PEERⅣFoRMATIoNINC.2009 基于Android系统的C锄em模块设计和实现

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
关闭