Windows下PCIe介面的多串列埠卡驅動開發小結

2021-06-28 06:22:55 字數 3000 閱讀 5867

近期在64位win7下開發一款pcie介面的多串列埠卡驅動程式,做個小結:

1. 因為在win下對wdf不熟悉,加上市面上ddk、wdm書籍較多,故選用wdm框架;

2. 多串列埠卡的硬體介面為pcie,因為在軟體驅動層面上,pcie和pci相容,直接借用常用的wdm即插即用框架。這裡用《windows驅動開發技術詳解(張帆等編寫)》第16章test5中的initmypci函式。該函式列舉了pci匯流排的各種資源,如中斷、io口、記憶體等,直接原封不動的拿來即可用;

① pci工具pciscope、rw,多多使用;

② windriver開發框架雖然簡單,但效率不高,做初期驗證不錯;但隨著對pci等匯流排的深入了解,發現還不如自己控制來的直接;driverstudio也是如此;

② 訪問乙個long型的reg,注意記憶體邊界訪問方式,:write_register_ulong((pulong)(g_membar0+(i * 4) + uart_tx_data), dwval);【這裡g_membar0是乙個unsigned char型別的】

3. 該串列埠卡沒有使用中斷,底層資料交換都是讀寫reg實現的。這種機制,驅動開發難度一下子減少了不少,故在核心驅動中啟動乙個執行緒,輪詢pcie定義的reg資源,排程執行緒每次sleep為1ms(但經測試debugview測試,實際在15ms左右)。這裡和硬體設計人員溝通,每次休息的15ms中,串列埠卡fpga中資料快取足夠大,不會丟失。但在串列埠使用層面看,寫入或讀出的資料會帶來約15ms的延時(忽略其他延時),這是乙個需注意的問題;

//延時函式,單位為ms

void mysleep(long msec)

由此看來,核心層的1ms睡眠,和win32的(1)精度一樣,不加高精度多**庫時,都是約15ms。

(關於在win32下測量sleep的精度問題,參見我的另一篇文章:裡面有詳細的測試方法和測試資料)

4. 驅動層面暴露給win32的串列埠com口,使用《windows驅動開發技術詳解(張帆等編寫)》第19章的virtual_com示例。

借用這個框架,能看出市面上最常用的串列埠除錯助手「sscom32.exe」,在讀取資料時,呼叫了ioctl_serial_get_commstatus,又呼叫了ioctl_serial_wait_on_mask(對應win32的waitcommevent),所以,自己寫的驅動裡,必須要處理這兩個請求:對第乙個ioctl_serial_get_commstatus,簡單點處理,要將當前可讀的資料個數賦值給amountininqueue成員;第二個請求,還用原框架內容:立刻pending該請求,但要在輪詢的執行緒裡,輪詢fifo(後面介紹)發現有資料時,釋放到這個請求。這個邏輯檢視函式drivercheckevent怎麼被呼叫的即可;

5. 如何多個裝置dev的建立?傳統的wdm是建立乙個fdo,附加在底層的pdo之上。靈活改變一下,將第乙個fdo建立時,呼叫ioattachdevicetodevicestack,但第二個、第三個....,不要呼叫該函式,這樣建立後,用devicetree檢視建立的裝置列表,發現他們都是「平行」關係,而不是「att」關係(只有第乙個是);

如此,在win32應用層createfile、readfile、writefile時,訪問的都是「當前」的那個dev,所以,要在驅動層裡,自己維護乙個全域性的裝置dev[n]陣列;

6. wdm的初始化pci裝置函式是放在irp_mn_start_device完成的,而irp_mn_start_device又依賴於「某乙個dev」的createfile完成的,怎麼辦?使用乙個全域性變數,當應用層createfile時第乙個裝置時(下標不一定是0),呼叫初始化pci裝置函式,將全域性變數置false,下次再有應用層

createfile不會呼叫initmypci;

由此看出,「wdm即插即用」和「傳統的ntdriver」並沒有區分的那麼明顯,像上面的思路,就是把兩者結合起來使用了;

7. 64位inf生成:只需要將張帆示例的inf新增個ntamd64即可,如下:

[manufacturer]

%mfgname%=mfg0,ntamd64

[mfg0.ntamd64]

; pci hardware ids use the form

; pci\ven_aaaa&dev_bbbb&subsys_cccccccc&rev_dd

%devicedesc%=youmark_ddi, pci\ven_9999&dev_9999

8. 64位win7的驅動需要數字簽名,目前沒有找到徹底解決辦法,暫時:

① 每次啟動按f8進入「禁用驅動簽名」;

② 進入testmode:bcdedit/set testsigning on(一定用管理員身份執行),但這樣結果導致會出現桌面右下角水印;

③ 使用工具dseo13b.exe(

④ 找網上的「去水印」工具(windows 7 watermark remover);

9. irp同步問題,做乙個假設:假設使用者應用程式不會開啟兩個執行緒同時呼叫readfile、writefile,因此在irp_mj_read、irp_mj_write處理裡,不考慮status_pending的情況,而是直接讀寫fifo緩衝區,即為乙個非阻塞的操作,無論有無資料都立刻返回。由上層使用者啟動執行緒時在呼叫readfile類似的函式時,自己sleep操作;

如果假設應用層開啟兩個執行緒同時readfile操作,那麼應該使用「序列化處理irp」(startio例程)技術,基本思路是irp_mj_read請求進來後,先pending掛起該請求,將該請求入隊,在startio例程裡去處理該請求,自己做取捨;

10. 硬體reg資料的使用:驅動中乙個執行緒高速輪詢reg,不斷的讀寫,讀出或寫入的資料不是和irp_mj_read、irp_mj_write互動,而是首先放到乙個fifo中再互動。這個fifo要在驅動裡自己實現,參見我的另一篇文章:推薦乙個vc下的fifo實現原始碼ccircularfifo,附帶測試程式),這個程式稍加改造,就可以在驅動層面中使用,記住在核心裡建立記憶體乾脆直接用nonpagedpool(非分頁記憶體)吧,現在的機器記憶體都不少於4g了,沒必要為區區一點「交換記憶體」而引起藍屏崩潰。

基於FMC介面的FPGA訊號處理PCIE訊號處理卡

技術指標 板載fpga實時處理器 xc7k325t 2ffg900i 介面指標 1.支援pci express 2.0規範 2.pcie gen2 x8 5gbps lane,理論資料頻寬40gbps 3.pcie雙向dma傳輸頻寬 3.2gbyte s,效率可達80 fmc介面指標 1.標準fmc...

windows遮蔽USB介面的指令碼

本指令碼在win10電腦測試通過 新建乙個檔案enableusb.reg 這個是開啟usb介面 windows registry editor version 5.00 hkey local machine system currentcontrolset services usbstor star...

PCIe驅動開發介面函式

realtek8168網絡卡時pci介面的網絡卡,其驅動程式就是乙個pci裝置的驅動程式例項,我們一起看看其流程。1 首先,初始化模組呼叫static inline int pci register driver struct pci driver driver 函式來註冊裝置驅動,這個函式的引數是...