《電子技術(shù)應用》
您所在的位置:首頁 > 嵌入式技術(shù) > 設(shè)計應用 > PCI/PCI-E高速實時DMA傳輸驅(qū)動設(shè)計
PCI/PCI-E高速實時DMA傳輸驅(qū)動設(shè)計
來源:電子技術(shù)應用2012年第11期
何 柳1, 陳 勇1, 吳 斌2, 楊 坤2
1. 重慶郵電大學, 重慶400065; 2. 中國科學院微電子研究所, 北京100029
摘要: 根據(jù)WDM驅(qū)動模型設(shè)計了驅(qū)動程序,介紹了WDM驅(qū)動的設(shè)計方法,對驅(qū)動開發(fā)中的常見問題進行了詳細闡述,著重講解了高速實時DMA傳輸系統(tǒng)中驅(qū)動和上層控制程序的設(shè)計方案。以VC++6.0和WDK作為開發(fā)平臺,完成了Windows NT系統(tǒng)下高速實時數(shù)據(jù)傳輸驅(qū)動的開發(fā)。
關(guān)鍵詞: PCIPCI-E DMA WDK 實時
中圖分類號: TP311
文獻標識碼: A
文章編號: 0258-7998(2012)11-0143-03
Design a high speed and real time PCI/PCI-E DMA transmission driver
He Liu1,Chen Yong1,Wu Bin2,Yang Kun2
1. Chongqing University of posts and telecommunications, Chongqing 400065, China; 2. Institute of Microelectronics of Chinese Academy of Science, Beijing 100029, China
Abstract: Designed a driver program according to the principle of WDM driver model. Firstly, introduced the way of designing WDM driver and expatiate the usual problems in driver design, then focused on the driver and its upper control program design of a high speed and real time DMA transmission system. Finally realized the development of high speed and real time transmission driver using VC++6.0 and WDK tools.
Key words : PCI/PCI-E; DMA; WDK; real time

    隨著在線高清電影以及實時視頻會議等應用的快速發(fā)展,數(shù)據(jù)傳輸呈現(xiàn)速率高、實時性強,數(shù)據(jù)量大的趨勢,由此產(chǎn)生了高速實時數(shù)據(jù)傳輸?shù)膯栴}。在眾多高速實時數(shù)據(jù)傳輸?shù)脑O(shè)計方案中,PCI/PCI-E總線不可比擬的傳輸速率優(yōu)勢成為設(shè)計高速傳輸設(shè)備時的首選總線[1-2]。

    為了能夠正常使用PCI/PCI-E總線進行高速數(shù)據(jù)傳輸,必須開發(fā)相應平臺下的設(shè)備驅(qū)動程序。本文以自主研發(fā)的BCS5731芯片為例,介紹了在Windows NT環(huán)境下基于WDM模型的PCI/PCI-E總線設(shè)備驅(qū)動開發(fā)方案,著重分析了高速實時傳輸系統(tǒng)中驅(qū)動部分的設(shè)計與實現(xiàn)。
1 WDM驅(qū)動程序設(shè)計
1.1    WDM驅(qū)動模型介紹[3]

    WDM模型是微軟針對Windows 2000及后續(xù)操作系統(tǒng)制定的驅(qū)動開發(fā)模型,具有即插即用和電源管理等方便用戶使用的特性。目前微軟正力推新一代的WDF驅(qū)動開發(fā)模型,但從本質(zhì)上來說WDF是對WDM進行封裝后的模型;而且WDM模型的驅(qū)動開發(fā)實例眾多,極大地方便了驅(qū)動的開發(fā),所以本文采用了WDM驅(qū)動開發(fā)模型。
    WDM驅(qū)動基于分層的模式實現(xiàn)。完成一個設(shè)備的操作至少需要兩個驅(qū)動設(shè)備共同完成[4]。其中與系統(tǒng)連接最緊密的是底層總線驅(qū)動,而總線驅(qū)動也是最為復雜的部分。目前總線驅(qū)動通常由操作系統(tǒng)提供,驅(qū)動開發(fā)者只需要開發(fā)設(shè)備驅(qū)動以及可能需要的過濾驅(qū)動。圖1所示為WDM驅(qū)動模型層次結(jié)構(gòu)圖。

1.2 驅(qū)動實例設(shè)計
    對于WDM驅(qū)動而言,主要的函數(shù)是DriverEntry例程、AddDevice例程、PnP例程以及各個IRP的派遣例程。對應于應用程序的main入口函數(shù),Windows驅(qū)動程序相應的入口函數(shù)為DriverEntry[5]。
    DriverEntry例程由內(nèi)核中的I/O管理器負責調(diào)用,是驅(qū)動第一個執(zhí)行的例程。在本設(shè)計中,根據(jù)需要在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函數(shù)
    AddDerice Routine函數(shù)只出現(xiàn)在WDM驅(qū)動程序中,在NT式驅(qū)動中沒有此回調(diào)函數(shù)。此函數(shù)用于創(chuàng)建設(shè)備對象,并由PnP管理器調(diào)用。具體操作包括:創(chuàng)建設(shè)備對象,創(chuàng)建并注冊設(shè)備接口(為兼容也可創(chuàng)建符號連接),將創(chuàng)建的設(shè)備掛載到設(shè)備堆棧中,最后設(shè)置相關(guān)標志。值得注意的是,標志位中的讀寫方式在創(chuàng)建后不能在程序其他方面進行修改,且不同的讀寫標志位在編寫讀寫部分代碼時具有著不同的實現(xiàn)方式。
    (2) PnPRoutine函數(shù)
    PnPRoutine函數(shù)執(zhí)行即插即用功能,一個功能完整的PnP函數(shù)需要處理眾多的子IRP, 如IRP_MN_START_
DEVICE、 IRP_MN_STOP_DEVICE、IRP_MN_REMOVE_DE-
VICE等20多個子類IRP。在實際的接口驅(qū)動開發(fā)中,大部分PnPRoutine的子類IRP不需進行逐一編寫,驅(qū)動開發(fā)者只需處理必要的子IRP,其余的子類IRP可以統(tǒng)一傳遞給總線驅(qū)動處理即可。通常IRP_MN_START_DEVICE和IRP_MN_REMOVE_DEVICE和兩個子類IRP是WDM驅(qū)動必需單獨處理的IRP。
    (3) ControlRoutine函數(shù)
    ControlRoutine函數(shù)常用于應用程序與驅(qū)動程序之間的通信。程序設(shè)計者首先定義一種I/O控制碼,然后用函數(shù)DeviceIoControl將控制碼和請求一起傳遞給驅(qū)動程序。驅(qū)動程序則在ControlRoutine中實現(xiàn)這些控制碼。
    控制碼的實現(xiàn)往往采用Switch(){case:}的形式。在本設(shè)計中,采用ControlRoutine進行DMA分配和寄存器配置。因此需要定義數(shù)種不同的控制碼。
    (4) ReadRoutine和WriteRoutine函數(shù)
    兩個函數(shù)分別用于target讀寫操作,當應用層調(diào)用ReadFile和WriteFile時,I/O管理器生成相應的IRP并發(fā)送到對應的函數(shù)中。驅(qū)動程序創(chuàng)建的設(shè)備通常有三種讀寫方式:緩沖區(qū)方式、直接方式和其他方式。ReadRoutine和WriteRoutine中使用的讀寫方式是由AddDeviceRoutine中設(shè)置的標志位決定。因此在驅(qū)動創(chuàng)建設(shè)備對象時,需要確定采用哪種讀寫方式。在實際的開發(fā)過程中,為了保證數(shù)據(jù)的安全盡量不采用第三種實現(xiàn)讀寫方式(其他方式)。
    (5) DefaultRoutine函數(shù)
    設(shè)置的默認處理例程,程序中簡單地略過當前IRP,然后調(diào)用底層總線驅(qū)動??偩€驅(qū)動處理傳遞來的IRP_MJ_CLOSE和IRP_MJ_CREATE子類IRP。
1.3 高速連續(xù)DMA傳輸設(shè)計[6]
    本設(shè)計需要解決的一個難題是高速實時數(shù)據(jù)的傳輸。整個傳輸系統(tǒng)如圖2所示。

    系統(tǒng)傳輸流程為:基帶芯片通過有線或無線方式接收到大量高速實時數(shù)據(jù),傳遞到PCI Local端。PCI local端將數(shù)據(jù)傳遞到PCI Core與主機連接端,將數(shù)據(jù)通過PCI接口寫入主機分配的DMA內(nèi)存中;或者設(shè)備從DMA內(nèi)存中讀取主機數(shù)據(jù)。在傳輸過程中采用設(shè)備主控DMA方式。
    由于硬件基帶的傳輸速率高達300 Mb/s,且主機只能分配規(guī)模有限的DMA內(nèi)存,所以在主機數(shù)據(jù)接收時,若主機PCI接口端無法設(shè)計一種高效的數(shù)據(jù)讀取方式以及主機與硬件實時的信息交互渠道,將會造成大量數(shù)據(jù)的丟失和數(shù)據(jù)讀取的錯誤。
    本文設(shè)計了一種高效的同步機制,該機制采用DMA傳輸數(shù)據(jù),從而保證了數(shù)據(jù)傳輸?shù)母咝?。此外在?qū)動層和PCI接口層進行同步驗證,保證了數(shù)據(jù)的一致性,如圖3所示。設(shè)計思路如下:

    (1) 驅(qū)動采用公共內(nèi)存編寫方式。根據(jù)應用層輸入信息分配相應大小的DMA內(nèi)存,將該內(nèi)存抽象為1~N個長度為M字節(jié)的DMA寄存器,并將分配的DMA首地址傳輸給硬件。設(shè)內(nèi)存首地址用指針DMAmemory表示。
    (2) 驅(qū)動設(shè)備擴展中申明一個整型變量,用于保存上次硬件操作完畢時的DMA寄存器編號,命名為RegNumber,在驅(qū)動初始化階段初始化為0值。
    (3) PCI接口中分配一個長度為N bit的寄存器稱為寄存器R,寄存器R的位數(shù)與DMA寄存器個數(shù)一一對應。將寄存器R初始化為全0。
    (4) 硬件實時查詢寄存器R,若不為全1,則FPGA向主機寫入數(shù)據(jù); 若為全1,則暫停數(shù)據(jù)寫入。
    (5) 當數(shù)據(jù)從基帶傳輸?shù)街鳈C端的PCI接口時,硬件首先填充DMA內(nèi)存的第一個寄存器,填充完畢后將寄存器R的首位設(shè)置為1。后續(xù)數(shù)據(jù)依次填充DMA寄存器,并置位寄存器R對應的位為1。硬件填充完一個寄存器后,向主機發(fā)送一個電平中斷。
    (6) 主機端驅(qū)動檢測到硬件中斷,中斷例程中簡單清除電平中斷后,啟動DPC例程。
    (7) DPC例程中首先判斷寄存器R是否為全0,若為全0,則表示數(shù)據(jù)未寫入DMA內(nèi)存中。DPC例程直接返回,等待下個中斷。
    (8) 若寄存器R不為全0,則表示已有數(shù)據(jù)寫入。檢查RegNumber值,并從RegNumber+1編號的DMA寄存器開始讀數(shù)。讀取完一個寄存器后,向該DMA寄存器對應的寄存器R中的bit位發(fā)出寫1命令,將硬件接收PC機下發(fā)的操作命令對應為0。
    (9) 更新RegNumber,if(RegNumber < N) {RegNumber++;} else{RegNumber = 0;}。
    (10) DPC執(zhí)行完畢,函數(shù)返回。等待下一個中斷。
2 控制程序設(shè)計
    本文設(shè)計的驅(qū)動實現(xiàn)了數(shù)據(jù)收發(fā)完整功能,能提供用戶層進行可變大小DMA內(nèi)存分配,使能數(shù)據(jù)收發(fā)、接收數(shù)據(jù)校驗及提取數(shù)據(jù)幀頭信息等操作。
    本設(shè)計基于MFC實現(xiàn)了一個控制界面程序,通過界面操作可實現(xiàn)用戶定義DMA大小分配,數(shù)據(jù)收發(fā)控制命令、接收數(shù)據(jù)量顯示及幀頭信息顯示等功能,如圖4所示。控制界面與驅(qū)動通信采用IOCTL控制碼,步驟如下:

 

 

    (1) 使用CTL_CODE宏定義控制碼。本例定義的控制碼可簡單歸類為讀/寫寄存器。數(shù)據(jù)在應用層進行組裝。
    (2) 驅(qū)動程序中的ControlRoutine例程實現(xiàn)相應控制碼功能。
    (3) 編寫一個DLL,實現(xiàn)驅(qū)動與界面的交互接口。DLL內(nèi)部實現(xiàn)打開設(shè)備驅(qū)動,調(diào)用DeviceIoControl發(fā)送命令等操作。在外部向應用層提供用于發(fā)送命令的接口函數(shù)。如分配DMA、寫入DMA首地址、使能數(shù)據(jù)收發(fā)等。
    (4) 應用程序調(diào)用DLL提供的接口函數(shù),實現(xiàn)對設(shè)備的控制。
    本文分析了一般PCI/PCI-E設(shè)備驅(qū)動的設(shè)計要求與設(shè)計方式,詳細介紹了重要例程的設(shè)計需求,重點分析了高速實時DMA傳輸系統(tǒng)的設(shè)計方法,給出了驅(qū)動設(shè)計的詳細步驟,最后介紹了控制程序的設(shè)計。提出的高速實時DMA傳輸系統(tǒng)的設(shè)計方法,實現(xiàn)了高速實時數(shù)據(jù)傳輸功能,解決了當基帶與PC機傳輸速率不一致時。經(jīng)常出現(xiàn)的數(shù)據(jù)丟失和無法高速傳輸?shù)膯栴}。
參考文獻
[1]  尹勇,李宇.PCI總線設(shè)備開發(fā)寶典[M].北京:北京航空航天大學出版社,2005.
[2] PCI-SIG. PCI Express base specification revision1[S]. PCI_SIG,April 15 2003.
[3] 吳宏鋼,尹愛軍,秦樹人.基于WDM模型的PCI數(shù)據(jù)采集卡驅(qū)動程序設(shè)計[J].中國測試技術(shù),2008,34(3)59-62.
[4] 張帆,史彩成,等.Windows驅(qū)動開發(fā)技術(shù)詳解[M].北京:電子工業(yè)出版社,2008.
[5] Microsoft. Microsoft Windows Driver  Kits [EB/OL].[2010-2-26]. http//www.micorsoft.com//wdk.
[6] 王招凱,禹衛(wèi)東.基于PCIE總線的雷達數(shù)據(jù)記錄器驅(qū)動程序開發(fā)[J].微計算機信息,2008,24(4-2):89-91.

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