文獻標識碼: A
文章編號: 0258-7998(2012)11-0143-03
隨著在線高清電影以及實時視頻會議等應用的快速發展,數據傳輸呈現速率高、實時性強,數據量大的趨勢,由此產生了高速實時數據傳輸的問題。在眾多高速實時數據傳輸的設計方案中,PCI/PCI-E總線不可比擬的傳輸速率優勢成為設計高速傳輸設備時的首選總線[1-2]。
為了能夠正常使用PCI/PCI-E總線進行高速數據傳輸,必須開發相應平臺下的設備驅動程序。本文以自主研發的BCS5731芯片為例,介紹了在Windows NT環境下基于WDM模型的PCI/PCI-E總線設備驅動開發方案,著重分析了高速實時傳輸系統中驅動部分的設計與實現。
1 WDM驅動程序設計
1.1 WDM驅動模型介紹[3]
WDM模型是微軟針對Windows 2000及后續操作系統制定的驅動開發模型,具有即插即用和電源管理等方便用戶使用的特性。目前微軟正力推新一代的WDF驅動開發模型,但從本質上來說WDF是對WDM進行封裝后的模型;而且WDM模型的驅動開發實例眾多,極大地方便了驅動的開發,所以本文采用了WDM驅動開發模型。
WDM驅動基于分層的模式實現。完成一個設備的操作至少需要兩個驅動設備共同完成[4]。其中與系統連接最緊密的是底層總線驅動,而總線驅動也是最為復雜的部分。目前總線驅動通常由操作系統提供,驅動開發者只需要開發設備驅動以及可能需要的過濾驅動。圖1所示為WDM驅動模型層次結構圖。
1.2 驅動實例設計
對于WDM驅動而言,主要的函數是DriverEntry例程、AddDevice例程、PnP例程以及各個IRP的派遣例程。對應于應用程序的main入口函數,Windows驅動程序相應的入口函數為DriverEntry[5]。
DriverEntry例程由內核中的I/O管理器負責調用,是驅動第一個執行的例程。在本設計中,根據需要在DriverEntry例子中注冊了以下例程:
pDriverObject->DriverExtension->AddDevice = AddDeviceRoutine
pDriverObject->MajorFunction[IRP_MJ_PNP] = PnpRoutine
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlRoutine
pDriverObject->MajorFunction[IRP_MJ_WRITE] = WriteRoutine
pDriverObject->MajorFunction[IRP_MJ_READ] = ReadRoutine
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = faultRoutine
pDriverObject->MajorFunction[IRP_MJ_CREATE] = DefaultRoutine
下面對上述例程進行分析。
(1) AddDeviceRoutine函數
AddDerice Routine函數只出現在WDM驅動程序中,在NT式驅動中沒有此回調函數。此函數用于創建設備對象,并由PnP管理器調用。具體操作包括:創建設備對象,創建并注冊設備接口(為兼容也可創建符號連接),將創建的設備掛載到設備堆棧中,最后設置相關標志。值得注意的是,標志位中的讀寫方式在創建后不能在程序其他方面進行修改,且不同的讀寫標志位在編寫讀寫部分代碼時具有著不同的實現方式。
(2) PnPRoutine函數
PnPRoutine函數執行即插即用功能,一個功能完整的PnP函數需要處理眾多的子IRP, 如IRP_MN_START_
DEVICE、 IRP_MN_STOP_DEVICE、IRP_MN_REMOVE_DE-
VICE等20多個子類IRP。在實際的接口驅動開發中,大部分PnPRoutine的子類IRP不需進行逐一編寫,驅動開發者只需處理必要的子IRP,其余的子類IRP可以統一傳遞給總線驅動處理即可。通常IRP_MN_START_DEVICE和IRP_MN_REMOVE_DEVICE和兩個子類IRP是WDM驅動必需單獨處理的IRP。
(3) ControlRoutine函數
ControlRoutine函數常用于應用程序與驅動程序之間的通信。程序設計者首先定義一種I/O控制碼,然后用函數DeviceIoControl將控制碼和請求一起傳遞給驅動程序。驅動程序則在ControlRoutine中實現這些控制碼。
控制碼的實現往往采用Switch(){case:}的形式。在本設計中,采用ControlRoutine進行DMA分配和寄存器配置。因此需要定義數種不同的控制碼。
(4) ReadRoutine和WriteRoutine函數
兩個函數分別用于target讀寫操作,當應用層調用ReadFile和WriteFile時,I/O管理器生成相應的IRP并發送到對應的函數中。驅動程序創建的設備通常有三種讀寫方式:緩沖區方式、直接方式和其他方式。ReadRoutine和WriteRoutine中使用的讀寫方式是由AddDeviceRoutine中設置的標志位決定。因此在驅動創建設備對象時,需要確定采用哪種讀寫方式。在實際的開發過程中,為了保證數據的安全盡量不采用第三種實現讀寫方式(其他方式)。
(5) DefaultRoutine函數
設置的默認處理例程,程序中簡單地略過當前IRP,然后調用底層總線驅動。總線驅動處理傳遞來的IRP_MJ_CLOSE和IRP_MJ_CREATE子類IRP。
1.3 高速連續DMA傳輸設計[6]
本設計需要解決的一個難題是高速實時數據的傳輸。整個傳輸系統如圖2所示。
系統傳輸流程為:基帶芯片通過有線或無線方式接收到大量高速實時數據,傳遞到PCI Local端。PCI local端將數據傳遞到PCI Core與主機連接端,將數據通過PCI接口寫入主機分配的DMA內存中;或者設備從DMA內存中讀取主機數據。在傳輸過程中采用設備主控DMA方式。
由于硬件基帶的傳輸速率高達300 Mb/s,且主機只能分配規模有限的DMA內存,所以在主機數據接收時,若主機PCI接口端無法設計一種高效的數據讀取方式以及主機與硬件實時的信息交互渠道,將會造成大量數據的丟失和數據讀取的錯誤。
本文設計了一種高效的同步機制,該機制采用DMA傳輸數據,從而保證了數據傳輸的高效性。此外在驅動層和PCI接口層進行同步驗證,保證了數據的一致性,如圖3所示。設計思路如下:
(1) 驅動采用公共內存編寫方式。根據應用層輸入信息分配相應大小的DMA內存,將該內存抽象為1~N個長度為M字節的DMA寄存器,并將分配的DMA首地址傳輸給硬件。設內存首地址用指針DMAmemory表示。
(2) 驅動設備擴展中申明一個整型變量,用于保存上次硬件操作完畢時的DMA寄存器編號,命名為RegNumber,在驅動初始化階段初始化為0值。
(3) PCI接口中分配一個長度為N bit的寄存器稱為寄存器R,寄存器R的位數與DMA寄存器個數一一對應。將寄存器R初始化為全0。
(4) 硬件實時查詢寄存器R,若不為全1,則FPGA向主機寫入數據; 若為全1,則暫停數據寫入。
(5) 當數據從基帶傳輸到主機端的PCI接口時,硬件首先填充DMA內存的第一個寄存器,填充完畢后將寄存器R的首位設置為1。后續數據依次填充DMA寄存器,并置位寄存器R對應的位為1。硬件填充完一個寄存器后,向主機發送一個電平中斷。
(6) 主機端驅動檢測到硬件中斷,中斷例程中簡單清除電平中斷后,啟動DPC例程。
(7) DPC例程中首先判斷寄存器R是否為全0,若為全0,則表示數據未寫入DMA內存中。DPC例程直接返回,等待下個中斷。
(8) 若寄存器R不為全0,則表示已有數據寫入。檢查RegNumber值,并從RegNumber+1編號的DMA寄存器開始讀數。讀取完一個寄存器后,向該DMA寄存器對應的寄存器R中的bit位發出寫1命令,將硬件接收PC機下發的操作命令對應為0。
(9) 更新RegNumber,if(RegNumber < N) {RegNumber++;} else{RegNumber = 0;}。
(10) DPC執行完畢,函數返回。等待下一個中斷。
2 控制程序設計
本文設計的驅動實現了數據收發完整功能,能提供用戶層進行可變大小DMA內存分配,使能數據收發、接收數據校驗及提取數據幀頭信息等操作。
本設計基于MFC實現了一個控制界面程序,通過界面操作可實現用戶定義DMA大小分配,數據收發控制命令、接收數據量顯示及幀頭信息顯示等功能,如圖4所示。控制界面與驅動通信采用IOCTL控制碼,步驟如下:
(1) 使用CTL_CODE宏定義控制碼。本例定義的控制碼可簡單歸類為讀/寫寄存器。數據在應用層進行組裝。
(2) 驅動程序中的ControlRoutine例程實現相應控制碼功能。
(3) 編寫一個DLL,實現驅動與界面的交互接口。DLL內部實現打開設備驅動,調用DeviceIoControl發送命令等操作。在外部向應用層提供用于發送命令的接口函數。如分配DMA、寫入DMA首地址、使能數據收發等。
(4) 應用程序調用DLL提供的接口函數,實現對設備的控制。
本文分析了一般PCI/PCI-E設備驅動的設計要求與設計方式,詳細介紹了重要例程的設計需求,重點分析了高速實時DMA傳輸系統的設計方法,給出了驅動設計的詳細步驟,最后介紹了控制程序的設計。提出的高速實時DMA傳輸系統的設計方法,實現了高速實時數據傳輸功能,解決了當基帶與PC機傳輸速率不一致時。經常出現的數據丟失和無法高速傳輸的問題。
參考文獻
[1] 尹勇,李宇.PCI總線設備開發寶典[M].北京:北京航空航天大學出版社,2005.
[2] PCI-SIG. PCI Express base specification revision1[S]. PCI_SIG,April 15 2003.
[3] 吳宏鋼,尹愛軍,秦樹人.基于WDM模型的PCI數據采集卡驅動程序設計[J].中國測試技術,2008,34(3)59-62.
[4] 張帆,史彩成,等.Windows驅動開發技術詳解[M].北京:電子工業出版社,2008.
[5] Microsoft. Microsoft Windows Driver Kits [EB/OL].[2010-2-26]. http//www.micorsoft.com//wdk.
[6] 王招凱,禹衛東.基于PCIE總線的雷達數據記錄器驅動程序開發[J].微計算機信息,2008,24(4-2):89-91.