文獻標識碼: A
文章編號: 0258-7998(2014)04-0126-04
在高科技研究以及工業(yè)、醫(yī)療、交通、航空等眾多領域中,對高幀率和高分辨率的圖像數(shù)據(jù)需求逐漸加大,例如航天和軍工中高速物體運動軌跡的捕捉、3D動漫、視頻定位和測量、高速公路交通監(jiān)控等。然而,連續(xù)的高幀率和高分辨率圖像采集將產(chǎn)生巨大的數(shù)據(jù)量,例如以10 f/s幀率傳輸分辨率為4 928 V×3 280H的視頻圖像時,總線上的數(shù)據(jù)速率高達1.23 Gb/s;以500 f/s幀率傳輸分辨率為640 V×480 H的視頻圖像時,總線上的數(shù)據(jù)速率也高達1.18 Gb/s。為了實現(xiàn)1 Gb/s以上的傳輸速度且滿足實時性和長距離傳輸?shù)囊螅x用光纖技術和PCI Express(簡稱PCI-E)總線技術設計了PCI-E總線光纖接口卡。
光纖具有頻帶寬、傳輸距離長、損耗低、抗干擾能力強等優(yōu)點[1],適用于大量數(shù)據(jù)的遠程傳輸。PCI-E總線采用了串行點對點通信技術,使傳輸速率大幅度提高,PCI-E 1.0標準的單通道單向速率高達2.5 Gb/s,且最大支持32通道[2]。PCI-E 3.0標準單通道單向速率可達8 Gb/s,是傳輸高速、大數(shù)據(jù)量總線的首選,具有研究和應用價值。
本文基于Spartan-6芯片設計的PCI Express光纖接口卡的驅動程序,完成的功能有:(1)驅動程序對光纖接口卡硬件資源的獲?。?(2)光纖接口卡能夠將大量數(shù)據(jù)及時發(fā)送到計算機內存中; (3)合理的中斷機制能夠滿足處理高速圖像的需要; (4)計算機可以向光纖接口卡發(fā)送參數(shù)命令。
1 PCI Express接口卡的硬件結構
PCI Express接口卡基于Xilinx公司的Spartan-6 LTX系列FPGA設計,完成圖像數(shù)據(jù)收發(fā)、數(shù)據(jù)緩存以及PCI-E協(xié)議等工作,并將采集到的圖像數(shù)據(jù)通過PCI-E總線傳輸給計算機。Spartan-6 LTX系列FPGA內部包含一個PCI-E端點硬核,完整實現(xiàn)了PCI-E1.0標準協(xié)議中的數(shù)據(jù)鏈路層和物理層的功能,可以完成1鏈路的PCI-E總線傳輸[3]。光纖接口卡采用單片高性能FPGA設計,具有系統(tǒng)集成度高、硬件設計簡潔且便于擴展的特點。末端利用計算機對采集的圖像進行顯示、存儲以及回放等操作。PCI Express接口卡的硬件結構如圖1所示。
利用ISE中的IP核生成工具CORE Generator對PCIE端點硬核進行定制:設備ID采用默認值,Vendor ID = 0x10EE,Device ID = 0x0007,這是驅動程序識別該硬件的廠商號和設備號; 基址寄存器的類型選擇為Memory,開辟一個32 位尋址的1 KB大小的存儲器空間;中斷設置為采用INTA的傳統(tǒng)中斷類型。
基址寄存器設計是實現(xiàn)接口卡功能關鍵內容,按照偏移地址將1 KB的存儲器空間劃分成功能不同的寄存器,部分定義如表1所示。
2 PCI Express接口卡的驅動程序
2.1 開發(fā)工具Windows DDK簡介
Windows DDK是微軟提供的驅動程序開發(fā)工具包,包括了設備驅動開發(fā)的文檔、頭文件和庫文件、調試工具和程序示例。先將Windows DDK導入VC++軟件開發(fā)工具,然后用C語言編寫驅動程序代碼,編譯后再用Windows DDK中的調試軟件調試,生成可執(zhí)行的驅動程序。使用Windows DDK能夠開發(fā)出真正意義上的核心態(tài)驅動程序,它所開發(fā)的驅動程序效率也是最高的,但必須詳細了解操作系統(tǒng)的內核工作方式,開發(fā)難度較大[4]。
常用開發(fā)工具還有WinDriver和DriverStudio,為了獲得最大的驅動程序效率,選擇采用Windows DDK來設計PCI Express接口卡的驅動程序。
2.2 WDM啟動程序的結構
通常WDM驅動程序都是基于分層的結構設計,由功能驅動函數(shù)、總線驅動程序和過濾器驅動程序三部分組成。完成一個設備的操作,至少要有兩個驅動設備共同完成[5],一個是總線驅動程序生成的物理設備對象(PDO),另一個是功能驅動程序生成的功能設備對象(FDO)。
Windows XP系統(tǒng)檢測到PCI-E接口卡插入主板卡槽時,總線驅動會自動創(chuàng)建出一個PDO。但是PDO不能單獨操作設備,還需要將實現(xiàn)功能的FDO掛載在總線驅動生成的PDO上,即相當于功能驅動程序掛載到了指定的硬件設備上[6],實現(xiàn)驅動程序對硬件設備的控制。
2.3 接口卡發(fā)送數(shù)據(jù)
為了提高接口卡的傳輸效率,采用DMA的傳輸方式將圖像數(shù)據(jù)通過PCI-E總線發(fā)送到計算機。在DMA傳輸過程中,PCI-E接口卡作為DMA傳輸?shù)闹骺仄?,?shù)據(jù)的傳輸速度基本由PCI-E總線的傳輸速度決定[7]。
2.3.1 獲取接口卡的資源信息
接口卡發(fā)送圖像數(shù)據(jù)之前,驅動程序要將DMA傳輸?shù)哪繕说刂芬约皵?shù)據(jù)負載的大小發(fā)送給接口卡,驅動程序需要先獲取接口卡上的硬件資源,如接口卡端點內存的物理地址等。
首先根據(jù)設備類型和設備擴展的大小,利用函數(shù)IoCreateDevice生成并初始化一個FDO;其次利用函數(shù)IoAttachDeviceToDeviceStack將生成的FDO附加在系統(tǒng)生成的PDO上;然后向PDO轉發(fā)一個IRP_MN_START_DEVICE類型的I/O 請求包(IRP),PDO會根據(jù)設備的類型自動枚舉該設備的所有資源。為了使FDO能夠得到底層PDO處理IRP的結果,需要同時將一個同步事件發(fā)送給底層PDO。PDO處理完IRP后立刻激發(fā)同步事件,通知FDO查詢此次IRP的結果; PDO完成了對IRP_
MN_START_DEVICE命令的響應后,將獲取到的接口卡設備資源存儲在IRP中名為IO_STACK_LOCATION結構的設備堆棧中[8],流程如圖2所示。
利用函數(shù)IoGetCurrentIrpStackLocation可以獲得該IO_STACK_LOCATION結構,主要包含接口卡的中斷信息、端點內存寄存器資源以及接口卡的物理地址等設備硬件資源。
2.3.2 分配內存空間并實現(xiàn)乒乓操作
為了盡可能提高計算機內存資源利用率,驅動程序分配的內存空間大小與每次DMA傳輸?shù)膱D像數(shù)據(jù)大小需保持一致。先利用函數(shù)IoGetDmaAdapter獲取一個DMA適配器,包含了開辟內存空間的函數(shù)AllocateCommonBuffer,調用此函數(shù)獲得一段指定大小的連續(xù)物理內存,保存物理內存的邏輯地址作為DMA傳輸?shù)哪繕说刂贰?br/>
預先在計算機中分配了多塊內存空間,使計算機可以在處理一塊寫滿了圖像數(shù)據(jù)的內存緩沖區(qū)的同時,用另一塊閑置的內存緩沖區(qū)接收DMA傳輸?shù)膱D像數(shù)據(jù),從而實現(xiàn)乒乓操作,提高傳輸效率[9]。
接收到DMA傳輸開始的指令后,PCI-E接口卡會根據(jù)分配好的內存空間地址和設定好的DMA傳輸負載長度,不斷地向計算機發(fā)送帶有圖像數(shù)據(jù)的TLPs數(shù)據(jù)包[10]。每次DMA傳輸結束后,驅動程序都會根據(jù)是否希望繼續(xù)進行DMA傳輸選擇輪轉一塊新的內存地址發(fā)送給接口卡或者釋放相關資源。DMA傳輸操作流程圖如圖3所示。
2.4 驅動程序的中斷處理
驅動程序接收到PCI-E接口卡產(chǎn)生的中斷信號,表明PCI-E接口卡已經(jīng)向計算機指定的內存空間完成了一次DMA傳輸,要通知應用層程序對內存中的數(shù)據(jù)進行訪問,完成顯示、存儲等功能。先利用函數(shù)IoConnectInterrupt將中斷例程與設備產(chǎn)生的中斷信號綁定。根據(jù)計算機中斷優(yōu)先級的規(guī)則,硬件中斷會得到操作系統(tǒng)的優(yōu)先響應[11]。
計算機操作系統(tǒng)檢測到PCI-E接口卡的中斷信號來臨時,立即進入中斷服務例程(ISR)。由于接口卡采用的傳統(tǒng)中斷是一種電平中斷信號,還需要驅動程序在ISR中進一步完成對中斷來源的判斷和清除中斷的操作。
采用同步事件方式實現(xiàn)中斷信號的同步處理,先在應用程序中定義一個與驅動程序共享的同步事件,并通過DeviceIoControl函數(shù)把該事件句柄傳遞給驅動程序,等待事件觸發(fā)之后再進行讀數(shù)據(jù)操作。驅動程序根據(jù)所傳遞的這個事件句柄創(chuàng)建一個相應的內核事件[12]。中斷發(fā)生時驅動程序調用KeSetEvent函數(shù)將同步事件設置為激發(fā)態(tài),通知應用程序中斷已經(jīng)發(fā)生。盡量減少ISR程序的運行時間,將激發(fā)同步事件的動作設計發(fā)生在擁有較低中斷等級的延遲過程調用例程(DPC)中[13]。中斷處理流程如圖4所示。
2.5 驅動程序向接口卡發(fā)送指令
指令發(fā)送可以分為兩個子過程,首先應用程序與驅動程序實現(xiàn)交互,然后驅動程序再根據(jù)交互獲得的參數(shù),修改PCI-E接口卡端點內存中寄存器的值[14]。
用函數(shù)IoRegisterDeviceInterface將一個名為GUID的128位二進制數(shù)字標識符與PDO綁定在一起。應用程序利用函數(shù)OpenDeviceByGuid獲取被綁定的驅動程序的設備句柄,再利用這個設備句柄和函數(shù)DeviceIoControl完成應用程序與驅動程序之間的通信與交互。DeviceIoControl函數(shù)可以將指定字節(jié)數(shù)量的數(shù)據(jù)傳入驅動程序,同時也可以接收驅動程序返回的數(shù)據(jù)。
下面舉例給出一個發(fā)送光纖相機幀的行大小的參數(shù)指令代碼:
#define IOCTL_LINE CTL_CODE (// 定義控制碼
FILE_DEVICE_UNKNOWN,//對象類型0x828,//驅動程序定義的IOCTL碼METHOD_BUFFERED, //操作模式FILE_
ANY_ACCESS) // 訪問權限
hDevice = OpenDeviceByGuid(// 打開驅動
(LPGUID) &GuidDriver); //接口卡設備句柄
ULONG value=0; //初始化輸出緩沖區(qū)
value = (m_Line<<16)|0x03; //光纖相機幀的行大小
DeviceIoControl (//發(fā)送相機參數(shù)命令到驅動程序
hDevice, //上文打開設備后返回的句柄
IOCTL_LINE //控制代碼名稱
&value //輸入緩沖區(qū)地址
sizeof(value) //輸入緩沖區(qū)大小
NULL,//返回緩沖區(qū)地址
NULL 0 //返回緩沖區(qū)大小為0
&nOutput // 記錄返回的數(shù)據(jù)大小
NULL)// 默認為NULL
…
switch (ioStack->Parameters.DeviceIoControl
.IoControlCode) // 驅動程序獲取IOCTL碼
case IOCTL_LINE: // 驅動程序接收到命令
address=(ULONG)deviceExtension->
MemoryStart[FPGA]+LINE; //設定PIO傳輸?shù)哪繕说刂?br/>
WRITE_REGISTER_ULONG((PULONG)address,
*pBuffer); //寫接口卡寄存器
應用層將相機參數(shù)和指令一同發(fā)送給了驅動程序,驅動程序利用在獲取PCI-E接口卡硬件資源時,保存接口卡物理地址和端點內存的寄存器偏移地址,完成對寄存器中數(shù)據(jù)的修改,實現(xiàn)對前端相機的控制。
利用FPGA內的計數(shù)器不斷產(chǎn)生數(shù)據(jù),使PCI-E接口卡不停地進行DMA傳輸。應用程序使用QueryPerformanceFrequency獲取處理器頻率,使用QueryPerformanceCounter查詢定時器計數(shù)值。經(jīng)多次反復測試,系統(tǒng)實際最大有效傳輸速度為1.5 Gb/s,高于利用DriverStudio工具開發(fā)的驅動程序實現(xiàn)的720 Mb/s有效傳輸速度[15]。
PCI-E總線采用8b/10b編碼, 因此使用1.0標準的PCI-E總線的理論有效輸速度為2.0 Gb/s[16],分析實際有效傳輸速度沒能達到理論值的原因是: (1)驅動程序基于Windows XP系統(tǒng)設計,該操作系統(tǒng)不支持MSI中斷方式,在響應DMA傳輸?shù)膫鹘y(tǒng)中斷時會占用一定時間; (2)發(fā)起DMA傳輸前需要設置FPGA內相關寄存器,這也需要一定的時間。
經(jīng)安裝光纖相機后測試,能夠清晰、流暢地顯示圖像大小為1 280 H×720 V、幀率為120 f/s、傳輸速率為842 Mb/s的圖像數(shù)據(jù)。驅動程序工作穩(wěn)定,并且可滿足多種數(shù)據(jù)類型的傳輸。
參考文獻
[1] 吳德明.光纖通信原理與技術[M].北京:科學出版社, 2004.
[2] 王齊.PCI Express體系結構導讀[M].北京:機械工業(yè)出版社,2010.
[3] XILINX. Xilinx solutions guide for PCI express user guide [EB/OL].[2009-09-16]. Http://www.xilinx.com/.
[4] 李忠輝,張志文.PCI設備驅動程序的開發(fā)和應用[J].西安工業(yè)學院學報,2005,25(1):8-11.
[5] 張帆,史彩成. Windows驅動開發(fā)技術形式詳解[M]. 北京:電子工業(yè)出版社,2008.
[6] 蹇紅梅,居錦武,王蘭英. Windows設備驅動程序的開發(fā)[J]. 四川理工學院學報(自然科學版), 2007(4):11-13.
[7] 席華偉.基于Verilog語言的DMA控制器的設計與仿真[D]. 西安:西安電子科技大學,2007.
[8] 武安河.Windows 2000/XP WDM設備驅動程序開發(fā)[M]. 北京:電子工業(yè)出版社,2003.
[9] 何柳,陳勇,吳斌.PCI/PCI-E高速實時DMA傳輸驅動設計[J].電子技術應用,2012,38(11):143-145.
[10] 董永吉,陳庶樵,李玉峰,等.Xilinx PCI-Express核總線接口設計與實現(xiàn)[J].電子技術應用,2011,37(8):135-138.
[11] 田澤, 劉娟, 王琦卉.基于WDM的PCIE驅動設計和實現(xiàn)[J]. 軟件導刊,2010,9(4):9-10.
[12] 司剛,付少鋒,周利華.WDM驅動程序中設備事件通知技術研究[J].計算機技術與發(fā)展,2006,16(4):144-146.
[13] 梁國龍,何昕,魏仲慧,等.PCIE數(shù)據(jù)采集系統(tǒng)的驅動程序開發(fā)[J].計算機工程與應用,2009,45(31):63-65.
[14] Peng Yu, Li Bo, Liu Datong, et al. A High Speed DMA transaction method for PCI express devices[J]. Journal of Electronic Science and Technology of China, 2009,7(4):380-384.
[15] 王維,蔣景宏,劉垚.基于PCI Express總線光纖采集卡WDM驅動程序設計[J].計算機測量與控制,2013,21(1):272-275.
[16] PCI-SIG. PCI Express card electromechanical specification revision 1.0[S].2002.