王法臻,崔少輝,王 成
(陸軍工程大學(xué)石家莊校區(qū),河北 石家莊 050003)
測試總線PXIe 在PCIe 總線上擴展了觸發(fā)、定時等功能,是PCIe 總線在儀器領(lǐng)域上的擴展。PXIe 采用串行、點對點的連接方式實現(xiàn)設(shè)備間的通信,其背板帶寬[1]可達6 Gb/s,還能提供差分時鐘和同步,提高了儀器時鐘的抗噪聲性能。因此,PXIe 總線廣泛適用于測試、控制、高帶寬數(shù)據(jù)傳輸?shù)刃枰咚?、高帶寬的領(lǐng)域。要實現(xiàn)PXIe 總線設(shè)備與上位機的通信,就需要開發(fā)相應(yīng)的驅(qū)動程序。驅(qū)動程序是操作系統(tǒng)的組成部分,是直接與硬件溝通的媒介。
基于此,本文開發(fā)了一種PXIe 接口可重構(gòu)測試儀器的驅(qū)動程序。在實際測試中將儀器插入PXIe 機箱中進行調(diào)試,驅(qū)動程序運行穩(wěn)定可靠,成功實現(xiàn)了控制指令發(fā)送和數(shù)據(jù)傳輸?shù)墓δ堋?/p>
傳統(tǒng)ATS 采用平臺加適配器的共享資源架構(gòu),通過開關(guān)系統(tǒng)分配測試通道和資源,開關(guān)延遲、測試資源競爭和死鎖等問題不可避免。解決上述問題可采用專用資源架構(gòu),使得各個測試通道均具備在任何時刻可提供所有測試資源的能力,為此,可重構(gòu)儀器提供了良好的解決方案。PXIe 接口可重構(gòu)儀器以Cyclone IV GX 系列FPGA 為核心,具備數(shù)模轉(zhuǎn)換、模數(shù)轉(zhuǎn)換、波形產(chǎn)生和電壓比較等功能。儀器通過接收上位機經(jīng)PXIe 總線向下發(fā)送的指令,選擇和設(shè)置各測試通道的功能和參數(shù),同時將測量數(shù)據(jù)上傳至上位機進行處理。
PXIe 同PCIe 遵循相同的協(xié)議,是在PCIe 總線基礎(chǔ)上附加必要的時鐘信號、觸發(fā)總線、星形總線、本地總線等PXIe 擴展信號形成的[2]。因此,可重構(gòu)儀器通過PCIe IP 硬核設(shè)計實現(xiàn)PXIe 接口。該實現(xiàn)方式在保證較大傳輸帶寬的基礎(chǔ)上,可簡化電路設(shè)計,降低開發(fā)成本。若要通過PXIe 總線實現(xiàn)上位機與儀器的通信,設(shè)計可靠穩(wěn)定的驅(qū)動程序顯得十分關(guān)鍵[3]。
在Windows 7 x64 操作系統(tǒng)下安裝VS2013 搭配WDK8.1 工具包完成開發(fā)環(huán)境的搭建。該集成開發(fā)環(huán)境具有用于開發(fā)、編譯、生成以及調(diào)試驅(qū)動程序所需的配套工具。
WDF 驅(qū)動框架是微軟最新的驅(qū)動開發(fā)框架,是在WDM 驅(qū)動模型的基礎(chǔ)上進一步封裝發(fā)展而來,具備了真正意義上面向?qū)ο?、事件?qū)動的性質(zhì)特點[4?5]。
WDF 驅(qū)動框架負責管理與操作系統(tǒng)內(nèi)核相關(guān)的多數(shù)交互,實現(xiàn)了對電源管理、即插即用等公共功能的支持,從而隔離了驅(qū)動程序與操作系統(tǒng)內(nèi)核,而降低了驅(qū)動程序?qū)Σ僮飨到y(tǒng)內(nèi)核的影響[6]。
WDF 框架內(nèi)部由對象模型和事件回調(diào)例程構(gòu)建組成,框架中所有的事物諸如設(shè)備、中斷、I/O 請求等都由對象定義。對象模型的實現(xiàn)使得各個對象都具有相應(yīng)的屬性、方法和事件,因此可圍繞對象完成參數(shù)的獲取設(shè)置、觸發(fā)特定事件回調(diào)例程等各類操作。WDF 包括KMDF 和UMDF 兩種驅(qū)動框架模式,分別運行在操作系統(tǒng)內(nèi)核環(huán)境和用戶環(huán)境下。PXIe 驅(qū)動程序運行在操作系統(tǒng)內(nèi)核中,因而采用KMDF 模式進行開發(fā)[7]。PXIe 驅(qū)動程序的開發(fā)流程如圖1 所示。
圖1 PXIe 驅(qū)動程序開發(fā)流程
DriverEntry 例程作為驅(qū)動程序的入口,負責驅(qū)動程序框架的初始化,在系統(tǒng)第一次加載驅(qū)動程序時被調(diào)用創(chuàng)建驅(qū)動對象并設(shè)置PXIeEvtDeviceAdd 例程。PXIeEvtDeviceAdd 例程負責創(chuàng)建各類對象并完成初始化I/O 隊列、初始化中斷處理等工作。
驅(qū)動程序主要實現(xiàn)6 類功能:I/O 請求處理、硬件訪問、DMA 操作、中斷處理、設(shè)置Event 事件以及電源狀態(tài)管理。
上位機應(yīng)用程序通過I/O 請求實現(xiàn)與驅(qū)動程序的通信[8]。在WDF 驅(qū)動框架中,各類I/O 請求會被封裝成WDFREQUEST 對象放入I/O 隊列中進行排隊。驅(qū)動采用了框架的默認串行隊列,會按照先后順序自動調(diào)用對應(yīng)類型的I/O 處理例程進行處理。
PXIeEvtIoRead 例 程 、PXIeEvtIoWrite 例 程 、PXIeDeviceIoControl 例程分別負責對硬件的讀訪問、寫訪問和DMA 操作。
硬件訪問具體就是對BAR 空間的訪問,完成對各功能寄存器的設(shè)置,如設(shè)置DMA 配置寄存器啟動DMA傳輸,設(shè)置通道控制寄存器選擇信號通道等[9]。
驅(qū)動程序只有在實現(xiàn)設(shè)備內(nèi)存地址空間的映射后才能對硬件進行訪問。驅(qū)動程序在PXIeEvtDeviceAdd例程中創(chuàng)建并初始化PNP 及電源管理對象,通過PNP 及電源管理例程來建立硬件資源與系統(tǒng)的映射關(guān)系。
在驅(qū)動加載時,WDF 驅(qū)動框架便會調(diào)用PXIeEvtDevicePrepareHardware 例程來獲取設(shè)備的內(nèi)存地址空間。由于PXIe 接口的BAR 空間被配置為存儲器空間,所以不再處理I/O 端口資源和中斷資源。此時,對BAR 空間的物理地址映射必須調(diào)用MmMapIoSpace,將物理地址轉(zhuǎn)換成操作系統(tǒng)內(nèi)核模式下的虛擬地址。之后,驅(qū)動程序便可通過虛擬地址讀/寫B(tài)AR 空間相應(yīng)地址上的寄存器。PXIeEvtDevicePrepareHardware 例程獲取設(shè)備內(nèi)存地址空間的流程如圖2 所示。
圖2 獲取內(nèi)存地址空間流程
在完成映射的基礎(chǔ)上,當驅(qū)動程序收到應(yīng)用程序調(diào)用PXIeEvtIoRead 例程或PXIeEvtIoWrite 例程的I/O 請求后,可使用函數(shù)READ_REGISER_XXX 或WRITE_REGISER_XXX 訪問映射地址進行讀寫操作。
在移除設(shè)備驅(qū)動程序時,需在PXIeEvtDevice?ReleaseHardware 例程中調(diào)用MmUnmapIoSpace 解除內(nèi)存物理地址與系統(tǒng)虛擬地址的映射關(guān)系。
大量數(shù)據(jù)的高速傳輸采用直接存儲器訪問(Direct Memory Access,DMA)方式。由于在FPGA 中已經(jīng)實現(xiàn)DMA 控制器的設(shè)計,因此驅(qū)動程序僅考慮提供傳輸所需的內(nèi)存空間和DMA 配置寄存器信息即可。DMA 操作流程如圖3 所示。
3.3.1 創(chuàng)建DMA 傳輸對象
驅(qū)動程序初始化時,在PXIeEvtDevcieAdd 例程中創(chuàng)建WDFDMAENABLER 對象并說明DMA 通道的特性;同時創(chuàng)建對象WDFCOMMONBUFFER,向系統(tǒng)申請公共緩沖區(qū),即用一段物理地址上的連續(xù)內(nèi)存作為讀/寫內(nèi)存空間。此外還需創(chuàng)建WDFDMATRANSACTION 對象用于DMA 傳輸事務(wù)的控制。
3.3.2 DMA 傳輸事務(wù)初始化
當驅(qū)動程序接收應(yīng)用程序,調(diào)用PXIeDeviceIoControl處理例程,發(fā)起DMA 操作的I/O 請求后,調(diào)用WdfDmaTransactionInitialize 注 冊PXIeEvtProgramDma 例程,完成DMA 傳輸事務(wù)的初始化。
圖3 DMA 操作流程
在PXIeEvtProgramDma 例程中需依次配置DMA 數(shù)據(jù)傳輸首地址、數(shù)據(jù)傳輸長度以及中斷服務(wù)寄存器,最后配置讀/寫操作控制寄存器,用于通知設(shè)備啟動DMA傳輸。該例程在執(zhí)行啟動DMA 傳輸事務(wù)后被調(diào)用執(zhí)行。
3.3.3 啟動DMA 傳輸
調(diào)用函數(shù)WdfDmaTransactionExecute執(zhí)行啟動DMA傳輸事務(wù)后,注冊例程PXIeEvtProgramDma 隨即被調(diào)用完成各寄存器的配置并啟動DMA 傳輸。
3.3.4 中斷處理
DMA 傳輸完成時,設(shè)備會向上位機發(fā)出中斷信號,驅(qū)動程序需響應(yīng)中斷并進行相關(guān)處理。驅(qū)動程序通過中斷對象WDFINTERRUPT 實現(xiàn)上述需求。該對象在PXIeEvtDeviceAdd 例程中創(chuàng)建并初始化,并與中斷處理例程、延遲調(diào)用例程相關(guān)聯(lián)。中斷處理流程如圖4所示。
由于中斷服務(wù)例程處于硬件中斷DIRQL 級別上運行,長時間處于該例程會影響其他線程運行,且很多內(nèi)核函數(shù)無法被調(diào)用。因此完成中斷信號的判斷后,可調(diào)用運行在DISPATCH_LEVEL 級別上的延遲調(diào)用例程完成后續(xù)處理工作。
結(jié)合上述情況,中斷處理包含了中斷處理例程和延遲調(diào)用例程兩個部分。中斷處理例程的任務(wù):
1)判斷中斷信號來源是否由設(shè)備產(chǎn)生,通過讀取中斷服務(wù)寄存器的方式實現(xiàn)。由于設(shè)備采用INTx 中斷方式,共享中斷機制可能與其他設(shè)備共享中斷號,從而導(dǎo)致中斷信號并非來源于指定設(shè)備[10]。
2)清除中斷信號,若中斷信號由設(shè)備產(chǎn)生則必須清除中斷標志,即設(shè)置中斷服務(wù)寄存器至初始狀態(tài)。避免因清除不及時導(dǎo)致一個中斷信號多次調(diào)用中斷處理例程,造成系統(tǒng)死機的情況[11]。
圖4 中斷處理流程
延遲調(diào)用例程的任務(wù):
1)判斷DMA 傳輸是否完成,通過調(diào)用函數(shù)WdfDmaTransactionDmaCompleted 實現(xiàn)。若未完成則應(yīng)繼續(xù)進行 DMA 傳輸,若完成則調(diào)用函數(shù)WdfDmaTransactionRelease,結(jié)束當前DMA 傳輸。
2)通知應(yīng)用程序DMA 傳輸結(jié)束并對傳輸數(shù)據(jù)進行處理,通過事件通知方式實現(xiàn)。
事件是驅(qū)動程序喚起應(yīng)用程序進行操作的方法[12],驅(qū)動程序通過內(nèi)核事件的方式通知應(yīng)用程序DMA 傳輸結(jié)束。應(yīng)用程序在創(chuàng)建事件句柄后,通過發(fā)送I/O 請求將事件句柄傳遞給驅(qū)動程序。
驅(qū)動程序在PXIeEvtDeviceIoControl 例程中根據(jù)獲得的事件句柄構(gòu)造一個內(nèi)核事件。之后,應(yīng)用程序便在輔助線程上等待該內(nèi)核事件置位。知并讀取DMA 傳輸數(shù)據(jù)。
在設(shè)備電源功耗的控制方面,當驅(qū)動程序內(nèi)無任何活動的情況下,即設(shè)備處于空閑狀態(tài)時進入低功耗狀態(tài),可達到降低設(shè)備電源功耗的目的。
電源管理遵循ACPI 規(guī)范[13?14],因此設(shè)計在操作系統(tǒng)S0(系統(tǒng)工作狀態(tài))下,當設(shè)備處于空閑狀態(tài)達到規(guī)定時間后,自動由D0 狀態(tài)(設(shè)備工作狀態(tài))進入D2 狀態(tài)(設(shè)備休眠狀態(tài))。電源狀態(tài)管理流程如圖5 所示。
圖5 電源狀態(tài)管理流程
當有新的I/O 請求到達驅(qū)動程序時,喚醒并調(diào)整設(shè)備電源狀態(tài)至D0狀態(tài)。結(jié)構(gòu)體WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS 負責空閑功能參數(shù)的設(shè)置,PXIeEvtDeviceAdd 例程中代碼設(shè)計如下:
驅(qū)動程序的開發(fā)需要掌握操作系統(tǒng)、硬件設(shè)備等方面的知識,需要結(jié)合實際情況靈活實現(xiàn)驅(qū)動程序功能,從而實現(xiàn)軟硬件的協(xié)調(diào)工作。本文基于WDF 驅(qū)動框架設(shè)計了PXIe 可重構(gòu)儀器的設(shè)備驅(qū)動程序,成功實現(xiàn)了硬件訪問和DMA 傳輸?shù)裙δ?。在實際測試中將儀器插入PXIe 機箱中進行調(diào)試,驅(qū)動程序運行穩(wěn)定可靠,成功實現(xiàn)了控制指令發(fā)送和數(shù)據(jù)傳輸?shù)墓δ堋?/p>