劉敬輝,簡獻忠,肖兒良,姜冠祥,蔡留美,鄭照平
(1.上海理工大學 光電信息與計算機工程學院,上海 200093;2.上海雄博精密儀器股份有限公司,上海 200444)
基于WinDriver的高速PCI卡驅(qū)動開發(fā)
劉敬輝1,簡獻忠1,肖兒良1,姜冠祥2,蔡留美2,鄭照平2
(1.上海理工大學 光電信息與計算機工程學院,上海 200093;2.上海雄博精密儀器股份有限公司,上海 200444)
針對目前大數(shù)據(jù)背景下如何提高PCI卡高速傳輸穩(wěn)定性的問題,文中提出了基于內(nèi)核中斷處理及DMA傳輸?shù)腜CI卡驅(qū)動程序設(shè)計方法。在WinDriver生成驅(qū)動框架的基礎(chǔ)上,采取基于VC++6.0平臺進行了DMA 數(shù)據(jù)傳輸?shù)膶崿F(xiàn)和中斷響應(yīng)處理的PCI驅(qū)動程序開發(fā)。將驅(qū)動程序封裝為動態(tài)鏈接庫,用戶程序調(diào)用DLL驅(qū)動PCI卡,進行高速數(shù)據(jù)傳輸檢測。實驗發(fā)現(xiàn),當數(shù)據(jù)傳輸速度達到131 MB/s時,驅(qū)動程序運行穩(wěn)定可靠不丟幀不錯幀,為高速穩(wěn)定PCI卡驅(qū)動程序的設(shè)計供了一種思路。
WinDriver;PCI;驅(qū)動程序;DLL
目前大數(shù)據(jù)[1]越來越受到人們的重視,如何提高高速數(shù)據(jù)傳輸?shù)姆€(wěn)定性具有重要意義。外設(shè)部件互聯(lián)總線(PCI)標準是一種高速的傳輸協(xié)議,經(jīng)過幾年的發(fā)展已經(jīng)替代ISA、MAC等總線成為PC機主流總線標準[2]。它是一種地址線和數(shù)據(jù)線復(fù)用的高性能的32/64總線[3];且支持DMA傳輸機制[4]。因此PCI得到了廣泛的應(yīng)用。
基于Windows環(huán)境下PCI驅(qū)動程序的開發(fā)工具主要包括DDK[5],DriverStudio[6]和WinDriver[7]。相較于前兩者Jungo公司的WinDriver改變了傳統(tǒng)驅(qū)動程序開發(fā)方法,整個程序都工作在用戶態(tài)下,使開發(fā)者不需要掌握兩者所需要的預(yù)備知識就可以開發(fā)出與之相媲美的程序,大幅降低了開發(fā)難度[8]。目前國內(nèi)外學者進行了廣泛的研究[9-10],但存在高速傳輸穩(wěn)定性的隱患,如文獻[5]清中斷標志沒有在內(nèi)核中進行,導(dǎo)致清中斷標志操作滯后,增加了中斷誤響應(yīng)的概率;文獻[9]采用直接調(diào)用函數(shù)鎖定DMA緩沖區(qū),該方式存在當關(guān)閉程序并未停止數(shù)據(jù)傳輸時,會出現(xiàn)DMA緩沖區(qū)已經(jīng)解鎖,而PCI仍然向該內(nèi)存地址寫數(shù)據(jù),從而導(dǎo)致PC機死機或重啟等問題。
針對目前PCI卡高速傳輸穩(wěn)定性存在的問題,本文提出了基于內(nèi)核中斷處理及DMA傳輸?shù)腜CI卡驅(qū)動程序設(shè)計方法。為了實現(xiàn)主控計算機與目標板的快速數(shù)據(jù)傳輸,采用乒乓DMA方式傳輸數(shù)據(jù)。軟件開發(fā)基于VC++6.0平臺,為了便于用戶程序的調(diào)用,按照模塊化軟件思想,驅(qū)動程序以DLL動態(tài)鏈接庫的方式進行封裝。為了提高驅(qū)動程序的穩(wěn)定性采用內(nèi)核清中斷操作。為了提高驅(qū)動程序的容錯率采用開機時分配DMA緩沖區(qū)的方式。為提高工作效率,縮減開發(fā)周期選用WinDriver為開發(fā)工具。
1.1 WinDriver
Jungo公司的WinDriver是一款簡潔高效不涉及操作系統(tǒng)底層編程且兼容性很好的驅(qū)動開發(fā)工具。把所有復(fù)雜的底層操作都封裝在一個內(nèi)核模塊中,提供給用戶標準的WinDriver API函數(shù)來實現(xiàn)硬件訪問,加快了開發(fā)周期[10]。WinDriver體系結(jié)構(gòu)如圖1所示,它由用戶模式和內(nèi)核模式2部分組成[11]。用戶模式由WinDriver的用戶模式庫以及用戶編寫的驅(qū)動程序代碼組成,驅(qū)動程序通過調(diào)用WinDriver庫函數(shù)(Windrvr.h)實現(xiàn)對硬件的操作。內(nèi)核模式分WinDriver內(nèi)核模塊和內(nèi)核嵌入兩部分。WinDriver內(nèi)核模塊對用戶態(tài)庫提供服務(wù)支持,硬件通過內(nèi)核模塊來傳遞中斷請求信息和對I/O端口以及內(nèi)存映像地址的讀寫信息,同時內(nèi)核模塊將中斷處理以及端口讀寫信息傳遞給內(nèi)核嵌入部分,內(nèi)核嵌入完成用戶態(tài)代碼的嵌入,實現(xiàn)代碼核態(tài)下運行。
圖1 WinDriver體系架構(gòu)圖
1.2 基于WinDriver驅(qū)動程序開發(fā)步驟
WinDriver開發(fā)PCI驅(qū)動程序步驟如下:
(1)將PCI板卡插到機箱對應(yīng)PCI插槽中運行DriverWizard,在設(shè)備列表中找到并選中PCI設(shè)備,生成 INF文件,然后添加新硬件;
(2)測試硬件,利用Wizard來自動診斷硬件的地址讀寫操作能否進行,檢查寄存器及相關(guān)中斷是否正常;
(3)生成基于C++語言的驅(qū)動程序代碼框架;
(4)在生成驅(qū)動程序代碼框架的基礎(chǔ)上調(diào)試修改制作符合用戶程序要求動態(tài)鏈接庫;
(5)打包驅(qū)動程序(INF文件,DLL文LIB文件,函數(shù)頭文件);
(6)用戶程序調(diào)用動態(tài)鏈接庫,完成定制功能。
本驅(qū)動程序的主要功能是實現(xiàn)PCI卡的I/O以及內(nèi)存映射地址的讀寫,還有對PCI卡發(fā)出中斷的處理;針對高速傳輸穩(wěn)定性問題,主要進行DMA緩沖區(qū)鎖定方式,數(shù)據(jù)傳輸機制,中斷機制和DLL接口4個方面的設(shè)計。
2.1 DMA緩沖區(qū)的鎖定
PCI進行DMA傳輸數(shù)據(jù)到上位機,需要通過WinDriverAPI函數(shù)鎖定內(nèi)存區(qū)域作為數(shù)據(jù)緩沖區(qū)。而WinDriver鎖定DMA緩沖區(qū)有兩種方式,一種是分配一整塊連續(xù)的指定大小的內(nèi)存塊(WDC_DMAContigBufLock())另一種是分配離散的指定大小的內(nèi)存塊(WDC_DMASGBufLock())[12]。
但是,不管用哪種方式,若只是簡單的調(diào)用函數(shù)鎖定DMA緩沖區(qū)就會出現(xiàn)以下問題:當關(guān)閉程序時并未停止數(shù)據(jù)傳輸,就會出現(xiàn)DMA緩沖區(qū)已經(jīng)解鎖,而PCI仍然向該地址寫數(shù)`據(jù),從而導(dǎo)致PC機死機或重啟等狀況。
WinDriver V12.0.0的一項新功能[13]可以完美解決此問題,即可以實現(xiàn)在開機時分配內(nèi)存,即使程序不正常關(guān)閉,該內(nèi)存區(qū)域卻不會解鎖,大幅提高了驅(qū)動程序的容錯性,要實現(xiàn)該功能需要使用前者鎖定緩沖區(qū),所以采用函數(shù)WDC_DMAContigBufLock()。
整體操作流程如下:首先更改驅(qū)動INF文件的注冊項目[UpdateRegistryDevice]下的語句,更改要鎖定兩塊內(nèi)存的大小,這樣在開機時就會自動鎖定兩塊內(nèi)存緩沖區(qū);在驅(qū)動程序初始化鎖定內(nèi)存時調(diào)用WDC_DMAContigBufLock(),參數(shù)要設(shè)置成與INF文件中的相匹配,這樣所鎖定的內(nèi)存區(qū)域就會自動分配到開機時已經(jīng)鎖定的內(nèi)存塊中。缺點是所鎖定的內(nèi)存會一直被占用,優(yōu)點是極大的提高了驅(qū)動程序的穩(wěn)定性和容錯性。
2.2 乒乓高速DMA傳輸
為完成大批量數(shù)據(jù)的高速傳輸,現(xiàn)開辟兩塊固定大小的DMA緩沖區(qū)通過WinDriver的API函數(shù)將該內(nèi)存映射到PCI可以直接訪問的物理地址中。通過寄存器將PCI訪問內(nèi)存的物理地址通知PCI。當開始傳輸寄存器有效時,PCI開始循環(huán)以DMA的方式向兩塊DMA緩沖區(qū)寫入數(shù)據(jù),每傳輸完一次數(shù)據(jù)發(fā)出一次中斷,并置位內(nèi)存塊選擇標志寄存器。
WinDriver中提供了WDC_DMASyncCpu()函數(shù)來完成DMA數(shù)據(jù)搬運,作用是將DMA緩存快中的數(shù)據(jù)搬移到CPU緩存中。PC機收到中斷響觸發(fā)事件,然后通過內(nèi)存塊選擇標志寄存器判斷讀哪一塊內(nèi)存。通過乒乓DMA數(shù)據(jù)傳輸方式保證數(shù)據(jù)傳輸?shù)母咚俜€(wěn)定。傳輸機制如圖2所示。
圖2 PCI與PC機傳輸示意圖
2.3 內(nèi)核清中斷機制
當PCI傳輸數(shù)據(jù)到DMA緩存區(qū)后,每完成一塊緩存區(qū)的數(shù)據(jù)傳輸,則觸發(fā)一次PCI中斷。
當PCI在高速傳輸數(shù)據(jù)的過程中,每秒可觸發(fā)中斷100次,高速有效的中斷響應(yīng)機制對PC機來說尤為重要。PCI中斷是電平觸發(fā)中斷,收到中斷后需要立即清除,即向中斷清除寄存器寫1,否則會導(dǎo)致中斷重復(fù)響應(yīng);并且由于PCI采用中斷共享,同一個中斷號會被多個硬件設(shè)備所共用,為防止中斷誤響應(yīng),需添加中斷標志寄存器用于區(qū)別于其它設(shè)備的中斷,而中斷標志的清除同樣要在中斷觸發(fā)時立即執(zhí)行,否則操作系統(tǒng)可能誤響應(yīng)其它設(shè)備發(fā)出的中斷。針對此問題,WinDriver中可以設(shè)計實現(xiàn)在內(nèi)核中進行中斷信號的判斷和清除[14]。在開發(fā)者調(diào)用WDC_IntEnable()函數(shù)時可以向內(nèi)核傳遞一條WD_TRANSFER結(jié)構(gòu)體指令,在結(jié)構(gòu)體中可以定義中斷來時內(nèi)核的操作,現(xiàn)共定義了3個操作:
(1)讀命令:讀中斷標志寄存器;
(2)CMD_MASK命令:判斷中斷標志寄存器中讀出的的數(shù)據(jù)是否為1,是則繼續(xù)向下執(zhí)行,否則忽略該中斷;
(3)寫命令:清除中斷標志,清除中斷信號。
通過以上中斷初始化操作后,每當觸發(fā)中斷,內(nèi)核便會立刻執(zhí)行WD_TRANSFER結(jié)構(gòu)體定義的指令,即立刻清除中斷信號和中斷標志。然后調(diào)用中斷處理函數(shù),進而進行數(shù)據(jù)傳輸和處理。中斷響應(yīng)流程如圖3所示。
2.4 PCI驅(qū)動程序DLL接口設(shè)計
為了便于用戶程序訪問驅(qū)動程序,驅(qū)動程序?qū)⒈环庋b為動態(tài)鏈接庫(DLL),用戶程序通過調(diào)用DLL的接口函數(shù)從而達到對PCI卡發(fā)送控制命令從而實現(xiàn)PCI到PC機的數(shù)據(jù)傳輸。為了方便用戶程序調(diào)用,現(xiàn)以模塊化的軟件設(shè)計思想,接口函數(shù)設(shè)計在滿足用戶程序所需功能的基礎(chǔ)上盡可能簡單規(guī)范,主要接口及其功能描述如下:
BOOL OpenDevice();打開設(shè)備
BOOL CloseDevice();關(guān)閉設(shè)備
BOOL CreateEvents(HANDLE hEvent);將建立好的事件句柄給驅(qū)動程序
BOOL ClearEvent(HANDLE hEvent);清除事件
BOOL CreateDMABuffer(ULONG size, PUSER_DMA_ADDRESS DMAAddess);分配數(shù)據(jù)緩存區(qū)
BOOL CloseDMABuffer (PUSER_DMA_ADDRESS pdma_address);關(guān)閉數(shù)據(jù)緩存區(qū)
ULONG MemReadDword(int memrange, ULONG offset);讀pci空間
BOOL MemWriteDword(int memrange,ULONG offset,ULONG val);寫pci空間
圖3 中斷響應(yīng)流程圖
3.1 PCI用戶程序開發(fā)
PCI驅(qū)動程序成功實現(xiàn)并進行DLL封裝后,下一步即考慮實際應(yīng)用。DLL不能單獨運行,必須作為應(yīng)用程序的一個軟件模塊,與應(yīng)用程序一起完成既定的功能。應(yīng)用程序通過對驅(qū)動程序DLL的有效使用完成設(shè)備初始化、開辟緩沖區(qū)、讀寫寄存器、DMA數(shù)據(jù)采集等操作。
圖4 中斷響應(yīng)流程圖
具體操作流程如下:(1)打開設(shè)備,調(diào)用函數(shù)OpenDevice();(2)開辟兩塊DMA緩沖區(qū)(每塊大小640×513×4Byte),調(diào)用函數(shù)CreateDMABuffer();(3)創(chuàng)建事件,調(diào)用函數(shù)CreateEvents()輸入事件句柄給驅(qū)動程序;(4)初始化參數(shù)設(shè)置,通過寫寄存器設(shè)置光纖源、圖片規(guī)格、像素格式等參數(shù);(5)開始傳輸,新建一線程循環(huán)等待事件被觸發(fā),并向傳輸開始寄存器寫1;(6)事件被觸發(fā),PC機從緩沖區(qū)地址讀取傳輸?shù)臄?shù)據(jù),將數(shù)據(jù)保存到本地文件,并實時顯示圖像及幀號等信息實時顯示在MFC界面上被觸發(fā),如圖4所示;(7)結(jié)束傳輸,向開始傳輸寄存器寫0,即停止傳輸。調(diào)用函數(shù)CloseDMABuffer(),關(guān)閉兩塊緩沖區(qū),調(diào)用函數(shù)CloseDevice()關(guān)閉設(shè)備。
3.2 實驗結(jié)果分析
在硬件方面,PCI卡采用Xilinx公司XC7A200T-2FFG1156 主芯片作為硬件主控平臺,設(shè)有兩塊光纖模塊,分別用于傳輸16位和32位的數(shù)據(jù),總線時鐘頻率設(shè)置為66 MHz保證FPGA內(nèi)部數(shù)據(jù)傳輸速率。
現(xiàn)設(shè)計數(shù)據(jù)源每秒產(chǎn)生100幀640×513×32 bit(數(shù)據(jù)源的產(chǎn)生速度為131 MB/s)的灰度圖像數(shù)據(jù),通過光纖1傳進PCI采集卡。此灰度圖像數(shù)據(jù)前512行數(shù)據(jù)為圖像每個像素點的像素信息;第513行為圖像信息,其中第513行的第111個32位數(shù)為幀號,每幀圖片幀號依次加1。在工程中,PCI內(nèi)部對發(fā)出的中斷數(shù)進行計數(shù);驅(qū)動程序在中斷服務(wù)程序中進行中斷計數(shù),用戶程序計數(shù)最終響應(yīng)事件的次數(shù),截取從第一次傳輸數(shù)據(jù)開始到1 200 s時間內(nèi)各個數(shù)據(jù)的變化如下。
表1 1 200 s后幀號與各部分中斷計數(shù)值變化
從表中可以看出,4個差值完全相同,即1 200 s中數(shù)據(jù)源發(fā)送的幀數(shù)與PCI向PC機發(fā)送的幀數(shù),驅(qū)動程序響應(yīng)中斷數(shù)和傳輸事件激活次數(shù)相同。以每秒100幀的速度,理論上1 200s應(yīng)該傳輸120 000幀數(shù)據(jù),與測得120 024有誤差,是由于計時本身存在誤差。
盡管WinDriver是一款功能強大,使用方便的驅(qū)動開發(fā)工具,但若要使編寫的代碼更加的穩(wěn)定高效,還需要認真研讀WinDriver生成的驅(qū)動框架,進而完成代碼的精簡和優(yōu)化。在本文中主要對以下幾個方面做出優(yōu)化:內(nèi)核中進行中斷的判斷和清除,避免中斷誤響應(yīng);開機時鎖定DMA緩存區(qū),保證該緩存區(qū)一直處于被鎖定狀態(tài);設(shè)計規(guī)范通用的DLL接口函數(shù)方便用戶程序調(diào)用。該接口卡目前應(yīng)用到三維免模板磨邊機系統(tǒng)中,進行高速數(shù)據(jù)傳輸實驗發(fā)現(xiàn),設(shè)計的PCI接口卡驅(qū)動程序具有傳輸速率高,穩(wěn)定可靠等特點, 能夠?qū)崿F(xiàn)在131 MB/s的速度下,數(shù)據(jù)傳輸穩(wěn)定,滿足項目高速穩(wěn)定傳輸數(shù)據(jù)的需要。
[1] 馮永強,張良,馮怡,等. 大數(shù)據(jù)應(yīng)用的現(xiàn)狀與展望[J].信息化建設(shè),2015(12):292-298.
[2] PCI.PCI local bus specification revision 2.1[M]. PCI Special Interest Group,1996.
[3] 邢林峰.PCI總線接口技術(shù)在高速數(shù)據(jù)傳輸系統(tǒng)中的應(yīng)用[J].自動化儀表,2007(S1):182-185.
[4] 李小龍,孟李林,邵瑞瑞,等.基于FPGA的PCI Express應(yīng)用平臺設(shè)計[J].電子科技,2014,27(12):108-111.
[5] 李晃,鞏峰,陳彥化.基于PCIE驅(qū)動程序的數(shù)據(jù)傳輸卡DMA傳輸[J].電子科技,2014,27(1):117-120.
[6] 趙彬,田澤,陳佳. 基于DDK的PCI設(shè)備驅(qū)動程序設(shè)計[J].電腦知識與技術(shù),2011(7):1534-1536.
[7] 楊波,柳征,姜文利. 用DriverStudio開發(fā)PCI總線設(shè)備驅(qū)動程序[J]. 微計算機信息,2007(25):279-281.
[8] 劉映杰,張在峰,劉瑋,等. 用WinDriver開發(fā)PCI設(shè)備驅(qū)動程序[J].信息技術(shù),2004(2):78-80.
[9] 王聰,王彬,薛潔,等. 基于PCIe總線協(xié)議的設(shè)備驅(qū)動開發(fā)[J].信息技術(shù),2013(3):32-35.
[10] 龍楊喜,孫書鷹,宋新民,等.基于Windriver的設(shè)備驅(qū)動開發(fā)[J].微計算機信息.2004(7):63-64.
[11] 景琦,殷永紅,李鵬. 利用WinDriver開發(fā)設(shè)備驅(qū)動[J]. 現(xiàn)代電子技術(shù),2005(19):67-69.
[12] 孫曉曄.基于PCIE的SGDMA高速數(shù)據(jù)傳輸系統(tǒng)[J].計算機技術(shù)與發(fā)展,2013(9):195-198.
[13] Jungo Ltd.WinDriver PCI/ISA/CardBus user’s manual v12.0.0[M].US: Jungo Ltd,2015.
[14] 胡波,原新晶. WinDriver開發(fā)驅(qū)動程序的KernelPlugIn技術(shù)的研究與應(yīng)用[J]. 計算機應(yīng)用,2003(11):134-136.
Design on Driver Program of High Speed PCI Card Based on WinDriver
LIU Jinghui1,JIAN Xianzhong1,XIAO Erliang1,JIANG Guanxiang2,CAI Liumei2,ZHENG Zhaopin2
(1. School of Optical-Electrical and Computer Engineering, University of Shanghai for Science and Technology, Shanghai 200093,China; 2.Shanghai SUPORE Instruments Co.Ltd, Shanghai 200444,China)
The method of designing the driver of PCI card was proposed which based on the kernel interrupt handling and DMA transfers, with regard to the problem of improve the stability of high-speed transmission PCI card and the environment of big data. PCI driver had been designed at platform of VC++6.0, which Based on the framework of driver generated by WinDriver, include the DMA data transfer and interrupt response processing. Then the driver was encapsulated into a DLL. User program drove PCI card by calling DLL, and processed the data transfers and detection. It was found that when the speed reached 131 MB/s, the driver was stable and reliable without losing frame or error frame, which provided a new way for the driver of high-speed and stable PCI card.
WinDriver; PCI; driver; DLL
2016- 06- 02
上海市寶山區(qū)科委產(chǎn)學研基金資助項目(bkw2015130)
劉敬輝(1991-),男,碩士研究生。研究方向:嵌入式系統(tǒng)。簡獻忠(1969-),男,博士,教授。研究方向:新能源等。
10.16180/j.cnki.issn1007-7820.2017.04.010
TP319
A
1007-7820(2017)04-040-04