Linux系統下USB攝像頭驅動開發

2021-07-30 03:54:03 字數 4691 閱讀 6558

一、

linux

系統中的

usb攝像頭驅動程式

usb攝像頭以其良好的效能和低廉的**得到廣泛應用。同時因其靈活、方便的

特性,易於整合到嵌入式系統中。但是如果使用現有的符合video for linux

標準的驅動程式配合通用應用程式,難以充分利用

usb頻寬,幀速不高,不易滿足實時監控等要求。本文首先介紹在

linux

系統下usb

攝像頭驅動編制的一般方法,然後說明在此基礎上如何提高幀速。

usb裝置驅動程式完全符合通用裝置驅動的準則,不同的是核心提供了一些特別的

api函式,方便驅動註冊、銷毀自己,例如

usb_resister()

和usb_deresister();2

.4版的核心還提供了對於

hotplug

的支援。

1

.1 usb

攝像頭驅動的一般編寫方法

linux

video for linux(

簡稱v4l)

。這個標準其實定義了一套介面,核心、驅動、應用程式以這個介面為標準進行交流。目前的

v4l涵蓋了視、音訊流捕捉及處理等內容,

usb攝像頭也屬於它支援的範疇。

因此,usbvideo_device

結構,並為其指定檔案操作函式指標陣列.

fops

,向系統註冊。在應用程式發出檔案操作的相關命令時,核心根據這些指標呼叫相應函式,並將該結構作為引數傳遞給它們。這樣,就完成了驅動和核心之間的通訊。例如:

static struct video_device vdev_template=;

//宣告video_device

,指出掛接驅動

static struct file_operations ov511_fops=;

//宣告本驅動的檔案操作函式指標

struct video_device*vdev

=video_devdata(file);

//從檔案指標中提取出

video_device結構

在video_device

結構中,有乙個私有指標

priv

,可以將它指向一塊保留記憶體。在這塊記憶體中,儲存著本驅動、本裝置的相關初始化資訊。這塊記憶體的申請、初始化、指標指向等工作都是在

usb驅動的列舉函式

.probe

中完成。這樣,在列舉函式將控制權返還給系統後,因為核心不銷毀保留記憶體,所以驅動仍然保留著自己的資訊。這點與

windows

系統中wdm

驅動有異曲同工之處。當然,在驅動解除安裝函式中,應當將申請的各塊記憶體全部釋放。

1.2

使用雙urb

輪流通訊

眾所周知,

usbl.1

urb中指定

usb_iso_asap

標誌。

urb->transfer_flags

=usb_iso_asap

;//盡可能快地發出本

urb

linux

系統中任何

usb傳輸都通過

urb實現。為提高速度,可以考慮擴大

urb的緩衝,這樣可以降低每個

usb事務中握手資訊所佔比例,提高有效資料的傳輸速度。但是受限於匯流排頻寬和具體的

usb裝置晶元,單純擴大

urb的緩衝不能無限制地解決問題。具體分析一下

usb傳輸在作業系統中的實現:每次傳輸都要包括

urb的建立、發出、**、資料整理等階段,這些時間不產生有效資料。因此可以建立兩個

urb,在等待乙個

urb被**時,也就是影象正在被感測器採集時,處理、初始化另乙個

urb,並在**後立刻將其發出。兩個

urb交替使用,大大減少了額外時間。工作流程如圖

1所示。

這個過程是在

urb的完成例程中實現的,有兩點需要注意:首先處理再次初始化的**時間不能長,否則會造成完成例程的重人,如果確實來不及,可以在完成例程中設定標誌,例如

「資料採集好

」旗語,由應用程式使用阻塞

ioctl()

來查詢該旗語並做處理;其次由於

cpu可能會在完成例程中停留較長時間,系統負擔較大,可以在.

open

函式中初始化兩個

urb並將其發出,有限度地減輕系統負擔。

1.3

使用雙幀緩衝提高效率

linux

系統中,檔案操作通常是由

read

、write

等系統呼叫來完成。這些系統呼叫在驅動中的解決方法就是用

copy_to_user()

、copy_from_user()

等函式在核態、戶態記憶體空間中互相拷貝。但是對於大批量的影象資料,採用拷貝的方法顯然會增加時間開銷,因此用記憶體對映的方法解決。首先使用

vmalloc()

申請足夠大的核態記憶體,將其作為影象資料緩衝空間,兩個

urb帶回的影象資料在這裡暫存;然後使用

remap_page_range()

函式將其逐頁對映到使用者空間中。戶態的影象處理程式使用

mmap()

函式,直接讀寫核態影象緩衝記憶體,大大減少額外開銷。

影象資料的處理可能要花費比較長的時間,不同的演算法對於資料保留時間的要求也不一樣。因此可以申請兩幀影象緩衝,在處理一幀影象的同時,將兩個

urb帶回的資料全部填充到另一幀緩衝中,這樣可以免去時間衝突上的麻煩。

值得注意的是:這種方法要求時刻持有當前幀的序號、每一幀的起始位址等資訊,不能將兩幀影象混淆。這些資訊可以儲存在保留記憶體中,當前幀的資料整理、序號改變在

urb完成例程中實現。

二、

v4l標準的改進

v4l標準目前已經發展到第二版

v4l2

,其基本思路與

v4l相同。

2.1

標準分析

根據v4l

標準,戶態程式在需要一幀影象時,

cpu的走向如圖2。

cpu按照

123456

的順序完成乙個迴圈。在這裡,有乙個細節被忽略:在完成例程中,也就是圖

2中步驟6,該

urb被立刻發出,但是由於這時使用者程式正在阻塞等待,沒辦法再次提出獲得影象的申請,因此在判斷有無新請求時,判斷的結果必然是當前無請求,導致下乙個

urb帶回的資料被驅動丟棄;由於核態、戶態的切換需要一定的時間,加上戶態多程序同步等開銷,等到應用程式能夠再次發出獲得一副影象的申請時,已經有不止乙個

urb帶回的資料被丟棄掉,這些

urb包含的資料正好是新一幀影象的開始部分。因此驅動必須等到再下一幀影象才能儲存資料、緩衝。這樣憑白損失了一幀影象,幀速最少下降一半。

2.2

改進思路:不間斷採集

為了解決這個問題,可以改進

v4l標準作,使其增加新的功能:通過新的引數,讓

ioetl()

函式通知驅動不間斷採集、緩衝影象資料,輪流儲存在兩幀緩衝區中,並在一幀影象採集好後,設定

「影象採集好

」旗語。戶態程式只需要發出一次

「獲得影象

」請求,就可以通過阻塞等待該旗語,不斷獲得影象。在採集結束後,再次通過新的引數,讓驅動停止緩衝即可。

cpu工作流程圖如圖

注意到圖2、圖

3,兩種

「判斷有無新請求

」的不同,即可發現新方法假定一直有請求,因此不丟棄每個

urb帶回的資料,輪流儲存在兩個幀緩衝內。

v4l已經作為約定俗成的標準被核心支援,因此如果使用全新的引數,工作量將相當巨大,並且不能和現有的應用程式相容。考慮到現有的影象採集應用程式使用

vidiocmcapture

作為引數,並提供幀序號,要求驅動將影象儲存到指定序號的幀緩衝內。由於驅動通常僅僅提供幾幀緩衝,因此該序號不會大於某個數字,如

10。因此可以繼續使用

vidiocmcapture

引數,搭配較大的序號來表示新增的功能,例如用

10000

和10001

來分別表示開始和停止緩衝影象資料的要求。驅動在收到

vidiocmcapture

要求後,檢查這個序號。如果小於

10000

,則按照正常的方法處理,否則按照改進方法。這種思路可以有效解決相容性問題。

2.3

實驗結果

在賽揚366、

usbl.1

介面的計算機平台上,採用上述不間斷採集改進

v4l標準,配合雙

urb、雙幀緩衝等方法後,幀速提高兩倍有餘,有效資料傳輸速度達

960kb/s

,接近等時傳輸方式下

usb

Linux系統下USB攝像頭驅動開發

摘要 介紹了在iinux系統下開發符合video for linux標準的usb攝像頭驅動的方法,並對該標準提出 不間斷採集 的改進思路,配合雙urb 雙幀緩衝等方法,提高採集速度。usb攝像頭以其良好的效能和低廉的 得到廣泛應用。同時因其靈活 方便的特性,易於整合到嵌入式系統中。但是如果使用現有的...

樹莓派使用免驅USB攝像頭

樹莓派使用免驅usb攝像頭 使用命令lsusb,查詢usb,插拔前後各用一次,找到usb口。使用命令ls dev video 插拔前後各查詢一次,得到裝置檔案。安裝fswebcamsudo apt get install fswebcam拍照fswebcam dev video0 home pi n...

USB攝像頭 介紹

從攝像頭的工作原理就可以列出攝像頭的主要結構和元件 1 鏡頭 lens 透鏡結構,由幾片透鏡組成,有塑膠透鏡 plastic 或玻璃透鏡 glass 2 影象感測器 sensor 可以分為兩類 ccd charge couple device 電荷耦合器件 cmos complementary me...