《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 嵌入式技術(shù) > 設(shè)計(jì)應(yīng)用 > PCI/PCI-E高速實(shí)時(shí)DMA傳輸驅(qū)動(dòng)設(shè)計(jì)
PCI/PCI-E高速實(shí)時(shí)DMA傳輸驅(qū)動(dòng)設(shè)計(jì)
來(lái)源:電子技術(shù)應(yīng)用2012年第11期
何 柳1, 陳 勇1, 吳 斌2, 楊 坤2
1. 重慶郵電大學(xué), 重慶400065; 2. 中國(guó)科學(xué)院微電子研究所, 北京100029
摘要: 根據(jù)WDM驅(qū)動(dòng)模型設(shè)計(jì)了驅(qū)動(dòng)程序,介紹了WDM驅(qū)動(dòng)的設(shè)計(jì)方法,對(duì)驅(qū)動(dòng)開(kāi)發(fā)中的常見(jiàn)問(wèn)題進(jìn)行了詳細(xì)闡述,著重講解了高速實(shí)時(shí)DMA傳輸系統(tǒng)中驅(qū)動(dòng)和上層控制程序的設(shè)計(jì)方案。以VC++6.0和WDK作為開(kāi)發(fā)平臺(tái),完成了Windows NT系統(tǒng)下高速實(shí)時(shí)數(shù)據(jù)傳輸驅(qū)動(dòng)的開(kāi)發(fā)。
關(guān)鍵詞: PCIPCI-E DMA WDK 實(shí)時(shí)
中圖分類號(hào): TP311
文獻(xiàn)標(biāo)識(shí)碼: A
文章編號(hào): 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

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

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

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

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

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

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

 

 

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

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載。
主站蜘蛛池模板: 影音先锋国产系列精品 | 激情爽毛片私人影院 | japanese55老妇成熟乱 | 波多野结衣视频在线观看 | 亚洲成a人片在线观看导航 亚洲成a人片在线观看精品 | 黄毛片网站| 欧美一区二区在线播放 | 国产亚洲一路线二路线高质量 | 午夜精品国产爱在线观看不卡 | 五月婷视频 | 日日狠狠久久8888av | 污视频在线免费 | 欧美在线黄 | 日本xxxxx久色视频在线观看 | 国产一区二区高清 | 正在播放国产尾随丝袜美女 | 国产一级特黄一级毛片 | 欧美精品一区二区精品久久 | 亚洲国产成人精品一区二区三区 | 日韩美女一级毛片 | 日韩色在线 | 欧美日韩一区二区在线视频播放 | 黄色网一级片 | 高清视频 一区二区三区四区 | 91国自产精品中文字幕亚洲 | 亚洲国产天堂久久综合9999 | 波多野结衣一区二区三区在线观看 | 女人特级毛片 | 亚洲区一二三四区2021 | 中文字幕一区二区三区精品 | 精品国产成人a在线观看 | 97影院理论在线观看 | 国产japanese孕妇孕交 | 亚洲手机在线 | 免费一级国产大片 | 黄网站在线观看永久免费 | 成人深夜视频 | 天堂亚洲国产日韩在线看 | 欧美精品一线二线大片 | 精品欧美一区二区精品久久 | 国产日韩欧美一区二区三区在线 |