《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 嵌入式技術(shù) > 設(shè)計應(yīng)用 > 基于FIMC接口的CMOS攝像頭驅(qū)動分析與設(shè)計
基于FIMC接口的CMOS攝像頭驅(qū)動分析與設(shè)計
2015年微型機與應(yīng)用第9期
鄧思斌,凌 強,,徐 駿,,李佳桐,李 峰,,單廷佳
(中國科學(xué)技術(shù)大學(xué) 信息科學(xué)技術(shù)學(xué)院 自動化系,,安徽 合肥 230027)
摘要: 目前的嵌入式系統(tǒng)中,USB攝像頭使用比較普遍,,但其應(yīng)用會受到傳輸速度的限制,。本文采用一款高速CMOS攝像頭,其驅(qū)動利用S3C6410內(nèi)置的FIMC接口技術(shù),,采用DMA和ping-pong緩沖池機制,,結(jié)合內(nèi)存共享策略,有效提高了傳輸速率并充分利用了有限的內(nèi)存資源,。深入分析了該驅(qū)動的原理和實現(xiàn)細節(jié),,并提出了改進設(shè)計,最終應(yīng)用在嵌入式圖像采集系統(tǒng)中,,能夠為應(yīng)用程序提供高清,、高速圖像。
關(guān)鍵詞: FIMC接口 OV9650 內(nèi)存共享 DMA
Abstract:
Key words :

  摘  要: 目前的嵌入式系統(tǒng)中,,USB攝像頭使用比較普遍,,但其應(yīng)用會受到傳輸速度的限制。本文采用一款高速CMOS攝像頭,,其驅(qū)動利用S3C6410內(nèi)置的FIMC接口技術(shù),,采用DMA和ping-pong緩沖池機制,結(jié)合內(nèi)存共享策略,,有效提高了傳輸速率并充分利用了有限的內(nèi)存資源,。深入分析了該驅(qū)動的原理和實現(xiàn)細節(jié),并提出了改進設(shè)計,,最終應(yīng)用在嵌入式圖像采集系統(tǒng)中,,能夠為應(yīng)用程序提供高清、高速圖像,。

  關(guān)鍵詞: FIMC接口,;OV9650;;內(nèi)存共享,;DMA

0 引言

  嵌入式系統(tǒng)具有體積小,、功耗低和成本低等天然性的優(yōu)勢,因而得到廣泛應(yīng)用,,甚至在許多場合得以取代傳統(tǒng)工控機,,比如視頻監(jiān)控系統(tǒng)和安防系統(tǒng)。目前嵌入式系統(tǒng)中最常用,、嵌入式Linux內(nèi)核支持最廣泛的是USB攝像頭,。然而受到嵌入式處理器性能的限制,,USB攝像頭接口的傳輸速率限制為12 Mb/s,,對于常用的640×480分辨率的YUV圖像,其最高幀率為3.75幀/s,,無法滿足實時性要求,。因此,基于CMOS圖像傳感器的高速攝像頭正在被推廣應(yīng)用,。CMOS高速攝像頭可以為嵌入式系統(tǒng)實時地提供高分辨率圖像[1],,很適合進行識別、跟蹤等實時圖像處理作業(yè),。采集640×480的VGA圖像,,CMOS攝像頭最高幀率可以達到30幀/s?;贠V系列的CMOS攝像頭應(yīng)用很多,,比如監(jiān)控[2]和人數(shù)檢測[3]都使用了OmniVision公司的OV9650攝像頭。參考文獻[4]介紹了基于S3C6410和OV9650的V4L2圖像采集系統(tǒng)的設(shè)計,,參考文獻[5]和[6]介紹了基于S3C2440中相機接口(Camera Interface,,CAMIF)的OV9650攝像頭驅(qū)動設(shè)計。

  本文涉及的S3C6410[7]的完全交互式移動相機(Fully Integrated Mobile Camera,,F(xiàn)IMC)接口是由S3C2440的CAMIF發(fā)展而來,,但是目前關(guān)于FIMC驅(qū)動的原理分析和設(shè)計實現(xiàn)的文獻仍然很少。本文對OV9650及FIMC接口驅(qū)動的原理和實現(xiàn)細節(jié)作了深入分析,,并對原有驅(qū)動進行了改進,,使之適用于視線檢測系統(tǒng)。

  本文首先分析攝像頭驅(qū)動所依賴的硬件接口,,然后重點分析其驅(qū)動軟件設(shè)計原理和實現(xiàn)細節(jié),,并給出改進設(shè)計,最后對下一步的改進工作提出展望,。

1 攝像頭驅(qū)動系統(tǒng)的硬件接口

  本文所涉及的驅(qū)動系統(tǒng)基于OK6410嵌入式開發(fā)板,,采用S3C6410作為中央處理器。S3C6410內(nèi)置的FIMC接口為開發(fā)板與CMOS攝像頭的連接提供了可靠便利的接口。該驅(qū)動系統(tǒng)的硬件結(jié)構(gòu)如圖1所示,。

001.jpg

002.jpg

  如圖1,,攝像頭為130萬像素、20引腳的OV9650,,通過FIMC接口接入S3C6410,。OV9650與FIMC對應(yīng)管腳連接如圖2所示。其中,,CAMYDATA7~CAMYDATA0負責(zé)圖像數(shù)據(jù)傳輸,CAMRSTN為復(fù)位信號,,CAMSYNC為同步信號,。OV9650的配置接口為SCCB接口,。由于S3C6410沒有專用的SCCB接口,因此使用GPB6,、GPB5分別模擬SIO_D,、SIO_C,,即數(shù)據(jù)和時鐘信號,。SCCB協(xié)議與I2C協(xié)議的區(qū)別僅在于設(shè)備地址不同,因此,,驅(qū)動中直接用I2C代替。

2 攝像頭驅(qū)動系統(tǒng)軟件

  2.1 Linux驅(qū)動模型

  在Linux操作系統(tǒng)中,,設(shè)備驅(qū)動為應(yīng)用程序提供訪問接口,屏蔽了底層硬件細節(jié),。從Linux2.6內(nèi)核開始,,設(shè)備被驅(qū)動和內(nèi)核映射為文件,應(yīng)用程序可以像訪問普通文件一樣訪問這些掛載在/dev目錄下的設(shè)備,,訪問接口被定義在驅(qū)動中file_operations結(jié)構(gòu)體對象內(nèi),。每一個接口函數(shù)其實都是一個系統(tǒng)調(diào)用,其具體實現(xiàn)由驅(qū)動程序完成,。Linux內(nèi)核中驅(qū)動模型包括總線(Bus)、設(shè)備(Device)和驅(qū)動(Driver)三個要素,,即設(shè)備和驅(qū)動作為對象掛載在相同的總線上,,由總線對設(shè)備和驅(qū)動進行一一匹配。

  Linux驅(qū)動模型將所有外設(shè)分為字符設(shè)備,、塊設(shè)備和網(wǎng)絡(luò)設(shè)備三種。攝像頭屬于字符設(shè)備,,其驅(qū)動遵循著字符設(shè)備驅(qū)動的框架,,包括設(shè)備號、設(shè)備注冊和最重要的文件操作函數(shù)的實現(xiàn),。特別地,,針對攝像頭設(shè)備,V4L2[8]接口為驅(qū)動程序提供了一套完備的文件操作標準接口和緩沖池管理策略,,目前大多數(shù)的攝像頭驅(qū)動都遵循V4L2接口標準,。

  2.2 V4L2驅(qū)動

  V4L2是Video For Linux 2的簡稱,是Linux內(nèi)核中關(guān)于視頻設(shè)備的虛擬驅(qū)動,,它不涉及硬件,,僅僅為應(yīng)用程序提供一套完備的操作接口,這些接口的具體實現(xiàn)都由遵守V4L2協(xié)議的驅(qū)動程序來完成,,比如常用的ioctl接口,。V4L2的存在極大地方便了應(yīng)用程序的編寫,使得同一套應(yīng)用程序可以應(yīng)用于多種攝像頭,。V4L2層次示意圖如圖3,。

003.jpg

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

  (1)打開視頻設(shè)備文件(一般為dev/video0),,初始化采集格式等參數(shù),;

  (2)在內(nèi)核空間申請若干視頻采集的幀緩沖區(qū),;

 ?。?)地址映射,,使得用戶空間的應(yīng)用程序?qū)彌_區(qū)有讀寫權(quán)限;

 ?。?)幀緩沖區(qū)在視頻采集輸入隊列排隊,,并啟動視頻采集;

 ?。?)從緩沖隊列取出幀緩沖區(qū),,獲得數(shù)據(jù)進行處理;

 ?。?)處理完,將幀緩沖區(qū)重新放入視頻采集輸入隊列,,循環(huán)往復(fù)采集連續(xù)視頻數(shù)據(jù),。

004.jpg

  V4L2為圖像采集程序維持一個環(huán)形緩沖隊列,如圖4,。該緩沖區(qū)隊列為ping-pong操作模式,,應(yīng)用程序需要使用的圖像數(shù)據(jù)會通過ioctl接口使對應(yīng)的緩沖區(qū)出隊,緩沖隊列的其余緩沖區(qū)繼續(xù)接收圖像數(shù)據(jù),,并在一個循環(huán)之后覆蓋掉原有的緩沖區(qū)數(shù)據(jù),,以保證緩沖區(qū)隊列中圖像數(shù)據(jù)的實時性。

  2.3 關(guān)鍵模塊驅(qū)動的設(shè)計與實現(xiàn)

  OV9650通過FIMC接口與S3C6410連接,,F(xiàn)IMC為輸入圖像進行格式轉(zhuǎn)換,、剪裁等預(yù)處理,最后傳輸?shù)絻?nèi)核中開辟的圖像緩沖區(qū),,供應(yīng)用程序讀取,。攝像頭驅(qū)動分為兩個部分:OV9650驅(qū)動和FIMC驅(qū)動。

  2.3.1 OV9650驅(qū)動

  OV9650驅(qū)動的主要作用是掛載驅(qū)動和配置寄存器,,其中.h文件定義了寄存器配置數(shù)據(jù),,并由.c文件調(diào)用。由于FIMC接口的存在,,應(yīng)用程序不需要直接操作OV9650攝像頭,,因此OV9650驅(qū)動不需要為應(yīng)用程序提供訪問接口,不需要定義file_operations結(jié)構(gòu)體,。

  從Mach-smdk6410.c文件中可以知道,,內(nèi)核在啟動時,將OV9650作為一個I2C設(shè)備掛載到內(nèi)核樹的I2C總線上,。之后內(nèi)核找到OV9650驅(qū)動,,執(zhí)行其入口函數(shù)——ov965x_init(),將OV9650.c文件中定義的i2c_driver驅(qū)動對象也添加到內(nèi)核樹中,,最后由總線根據(jù)其name將設(shè)備和驅(qū)動進行匹配,。在匹配工作完成之后,,內(nèi)核會調(diào)用其探測函數(shù)ov965x_probe(),將OV9650的配置數(shù)據(jù)傳遞給FIMC驅(qū)動中的一個全局參數(shù)s3c_fimc,,用于配置FIMC寄存器,,然后,初始化OV9650寄存器,。

  2.3.2 FIMC驅(qū)動

  FIMC是s3c6410芯片為攝像頭設(shè)備提供的一個接口,,用來對所采集的圖像進行裁剪、放縮等預(yù)處理,。FIMC為輸出圖像提供兩個DMA通道:preivew通道和codec通道,,并為每個通道分配四個ping-pong緩沖區(qū),以提高圖像傳輸速度和內(nèi)存使用效率,。如圖5所示,。

005.jpg

  FIMC接收OV9650圖像數(shù)據(jù),并向上傳遞,。因此,,F(xiàn)IMC驅(qū)動最重要的作用就是向應(yīng)用層提供標準的操作接口,供應(yīng)用程序使用,。

  FIMC驅(qū)動主要包括三個部分:(1)platform驅(qū)動注冊,;(2)file_operations接口定義;(3)V4L2接口實現(xiàn),。

  2.3.2.1 platform驅(qū)動注冊

  platform是Linux 2.6內(nèi)核所引進的一種新型驅(qū)動管理和注冊機制,。目前Linux內(nèi)核中大部分的設(shè)備驅(qū)動都采用platform架構(gòu),。在platform架構(gòu)中,,設(shè)備用platform_device表示,驅(qū)動用platform_driver表示,。Linux platform driver機制與傳統(tǒng)的device driver機制(通過drivce_register函數(shù)進行注冊)相比,,一個十分明顯的優(yōu)勢在于platform機制將設(shè)備本身的資源注冊進內(nèi)核,由內(nèi)核統(tǒng)一管理,,在驅(qū)動程序使用這些資源時通過platform device提供的標準接口進行申請并使用,,提高了驅(qū)動和資源管理的獨立性,并且擁有較好的可移植性和安全性(這些標準接口是安全的),。

  FIMC驅(qū)動入口函數(shù)是s3c_fimc_core.c中的s3c_fimc_register(),,該函數(shù)將platform_driver類型的s3c_fimc_driver掛載到platform虛擬總線。由mach-smdk6410.c文件可知,,內(nèi)核啟動時將所有platform_device(包括s3c_device_fimc0)掛載到platform總線,。platform總線的match函數(shù)將device和driver匹配之后,會自動調(diào)用s3c_fimc_driver中指定的probe函數(shù)探測設(shè)備,、申請內(nèi)存資源,、申請中斷等,,并將最終形成的platform_device類型數(shù)據(jù)保存到內(nèi)核中,供后續(xù)使用,。最后,,調(diào)用video_register_device函數(shù)將對應(yīng)的video_device注冊到內(nèi)核。

  video_device結(jié)構(gòu)體包括fops,、ioctl_ops,、release、name,、vf_type幾個成員變量,,其中,最重要的是file_operations類型的fops和v4l2_ioctl_ops類型的ioctl_ops,,分別實現(xiàn)文件操作接口和V4L2接口,。

  2.3.2.2 file_operations接口

  FIMC驅(qū)動遵循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,,

  };

  當(dāng)應(yīng)用程序通過系統(tǒng)調(diào)用open()打開攝像頭設(shè)備時,,內(nèi)核會最終找到s3c_fimc_open()函數(shù)來打開攝像頭,。

  應(yīng)用程序通過read()獲取圖像數(shù)據(jù),該函數(shù)通過copy_to_user()將內(nèi)核空間所申請緩沖區(qū)中圖像數(shù)據(jù)拷貝到用戶空間中開辟的圖像數(shù)據(jù)區(qū),。該函數(shù)沒有充分利用FIMC接口提供的ping-pong緩沖區(qū),,按字進行拷貝(memcpy),十分耗時,。

  mmap函數(shù)將內(nèi)核空間中申請到的圖像緩沖區(qū)映射到應(yīng)用程序所在的用戶空間,,這樣,應(yīng)用程序申請到的buffer將指向內(nèi)核空間的圖像緩沖區(qū),,應(yīng)用程序可以(不拷貝)直接對圖像進行操作,。該函數(shù)配合V4L2標準中的環(huán)形緩沖區(qū)隊列,節(jié)省了應(yīng)用程序讀取圖像數(shù)據(jù)所消耗的時間,。

  2.3.2.3 V4L2接口

  V4L2接口功能強大,,為應(yīng)用程序提供了完備的操作接口,包括設(shè)置格式,、幀率,、白平衡,、曝光模式、申請緩沖區(qū),、取數(shù)據(jù),、剪裁圖像等。此處僅列舉幾個重要接口,。

  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,,

  },;

  應(yīng)用程序通過ioctl接口使用這些函數(shù),比如ioctl(fd,,VIDIOC_S_FMT,,&fmt)用來設(shè)置圖像格式,此時V4L2會將VIDIOC_S_FMT命令映射為s3c_fimc_v4l2_s_fmt_vid_cap()函數(shù),,并將fmt指定的格式告知FIMC接口,,F(xiàn)IMC會將OV9650傳遞過來的原始圖像數(shù)據(jù)經(jīng)過類型轉(zhuǎn)換傳遞回應(yīng)用程序。

  s3c_fimc_v4l2_reqbufs()用于申請圖像緩沖區(qū),,該函數(shù)為應(yīng)用程序在內(nèi)核空間開辟ping-pong緩沖區(qū),。s3c_fimc_v4l2_qbuf()函數(shù)將緩沖區(qū)組成環(huán)形緩沖隊列,當(dāng)應(yīng)用程序需要調(diào)用圖像數(shù)據(jù)時,,使用s3c_fimc_v4l2_dqbuf()使指定的緩沖區(qū)出隊,,緩沖區(qū)在出隊期間,不會被新來的圖像數(shù)據(jù)覆蓋,,新到的圖像數(shù)據(jù)會被傳送到環(huán)形隊列中指定緩沖區(qū)的下一個緩沖區(qū)。由于FIMC控制器為P通道和C通道分別開辟了4個緩沖區(qū),,在內(nèi)核初始化時已經(jīng)申請到,,因此FIMC驅(qū)動中并不需要再重新申請。

  2.4 驅(qū)動錯誤分析與改進設(shè)計

  在驅(qū)動主體框架正確的情況下,,開發(fā)板(OK6410A)自帶的驅(qū)動并不能直接使用,。同一套V4L2圖像采集程序可以應(yīng)用在USB攝像頭上,應(yīng)用在OV9650上卻無法獲得圖像,,并且先后報出兩個錯誤:

 ?。?)tx or ty is lower than zero and this is a invalid target size

 ?。?)VIDIOC_QUERYBUF error

  上述錯誤出現(xiàn)之后,LCD屏幕沒有圖像,,緊接著串口會顯示display 0,,表示程序無法讀出圖像數(shù)據(jù),導(dǎo)致程序終止,。下面分別對兩個錯誤進行分析并改進,。

  2.4.1 錯誤1的分析與改進

  由于ov9650驅(qū)動僅僅將ov9650設(shè)備注冊進入系統(tǒng),并沒有其他處理,,因此ov965x.h和ov965x.c兩個文件不用修改和調(diào)試,。

  FIMC采用DMA通道向內(nèi)核緩沖區(qū)傳送數(shù)據(jù),需要專門的函數(shù)打開DMA輸出通道,。通過函數(shù)跟蹤得知,,原有s3c_fimc_v4l2_s_fmt_vid_cap()函數(shù)并沒有打開輸出DMA通道,因此CMOS攝像頭的數(shù)據(jù)并沒有傳送到內(nèi)核開辟的緩沖區(qū)中,,導(dǎo)致V4L2也無法獲取這些圖像數(shù)據(jù),。而且由于沒有打開輸出DMA通道,out_frame參數(shù)也沒有設(shè)置,,導(dǎo)致其對應(yīng)的尺寸參數(shù)也為0,,所以報出第一個錯誤。

  在s3c_fimc_v4l2_s_fmt_vid_cap()中通過調(diào)用s3c_fimc_ set_output_frame()函數(shù),,打開輸出DMA通道,,解決了該問題。

  2.4.2 錯誤2的分析與改進

  該錯誤由s3c_fimc_v4l2_querybuf()函數(shù)報出,,報錯條件是:

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

  ->type!=V4L2_BUF_TYPE_VIDEO_CAPTURE)

  該函數(shù)用于配置所申請圖像緩沖區(qū)的長度,、偏移量等屬性,從而使所申請的環(huán)形隊列緩沖區(qū)生效,。由于本系統(tǒng)中攝像頭僅用于圖像捕獲,,因此在該函數(shù)開頭可以將b->type進行強制設(shè)定,即:b->type=V4L2_BUF_ TYPE_VIDEO_CAPTURE,,從而解決圖像緩沖區(qū)申請的問題,,該錯誤不再出現(xiàn)。

  至此,,修正后的FIMC驅(qū)動程序可以正常工作,,圖像數(shù)據(jù)得以傳輸?shù)絻?nèi)核中為FIMC驅(qū)動開辟的圖像緩沖區(qū),應(yīng)用程序可以通過read()系統(tǒng)調(diào)用或者ioctl()的VIDIOC_DQBUF命令獲取圖像數(shù)據(jù),。

  圖像捕獲效果如圖6所示,。

006.jpg

3 結(jié)論

  本文深入分析了CMOS攝像頭驅(qū)動的原理和實現(xiàn)細節(jié)。FIMC驅(qū)動向內(nèi)核申請四個ping-pong緩沖區(qū),通過DMA方式傳入圖像數(shù)據(jù),,提高了圖像數(shù)據(jù)傳輸速率,。內(nèi)存共享策略使得應(yīng)用程序在訪問圖像緩沖區(qū)時免去了內(nèi)存拷貝的步驟,大大縮減了圖像獲取的時間,。但是目前的FIMC驅(qū)動在緩沖區(qū)出隊和入隊時的保護機制仍不夠完善,,需要在今后的工作當(dāng)中對這一部分不斷進行優(yōu)化。

參考文獻

  [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的嵌入式監(jiān)控設(shè)計[J].輕工機械,,2012,,30(2):50-53.

  [3] 官志平.基于ARM9的Linux系統(tǒng)移植以及在電梯轎廂內(nèi)人數(shù)檢測的應(yīng)用[D].廈門:廈門大學(xué),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.


此內(nèi)容為AET網(wǎng)站原創(chuàng),,未經(jīng)授權(quán)禁止轉(zhuǎn)載,。