在我國的靶場測控領域,所有的數據交換都是基于簡化版的HDLC規程進行的,因此我們自行研制開發了基于簡化HDLC規程的通信卡。簡化HDLC規程主要是為了提高通信的實時性,將HDLC規程中所有通信聯絡命令幀全部簡化,只保留數據通信幀,從而保證一定的實時性。由于該卡具有可靠性高,使用簡單方便,工作時具有智能化等特點,被廣泛地應用于測控系統數據傳送的各個領域中。同時,隨著WindowsXP操作系統在測控系統逐漸應用,開發通信卡WindowsXP驅動程序勢在必行。因此,我們針對自行研制的通信卡開發出了核心態的驅動程序,經過廣泛的用戶使用,普遍反映應用好。下面介紹該通信卡的設計以及驅動程序的設計。 通信卡的硬件設計 1 通信卡的主要特點 通信卡的硬件設計目的是智能化通信:在卡上具有4個DMA通道及相應的數據緩沖存儲區。在數據的接收過程中,通信卡會自動接收幀數據,判別幀長度,在幀尾將接收到的幀數據提交系統。在發送數據過程中,系統只須把發送的數據提交給本卡,具體的發送過程由該卡自行完成,不因多路通信而使主機增加開銷。該卡有內/外時鐘兩種工作方式,近距離可省去調制解調器,波特率為600b/s~64Kb/s,提供2路符合RS-232/CCITT V.24和RS-422A標準的接口信號。 2 通信卡的電路設計 圖1 通信卡框圖 通信卡組成框圖如圖1所示。其主要由DMA控制器、總線竟爭仲裁器、串行通信控制器、數據緩沖存儲器SRAM、存儲器I/O映像和物理地址產生器、總線接口及防護、波特率產生器、接口電路等單元電路組成。 DMA控制器作為通信卡的主設備,控制卡上的數據接收和發送(來自通信控制器和CPU),并負責仲裁優先權。由于在進行數據通信時,允許主機CPU訪問本卡SRAM,且主機對其中某一路發控制命令時,不影響其余三路通信,這樣將會使主機CPU與本卡DMA竟爭本卡總線控制權。而總線上沒有給出主機CPU指令排隊狀態序列,故不能直接設計多主竟爭,因而在本卡總線上用門陣列設計了一個狀態機,不斷地監視總線爭用情況,完成本卡總線竟爭、仲裁功能。完成HDLC規程的串行通信的器件是INTEL8274多規程串行控制器,它能完成2個獨立的串行接收/發送全雙工通信。為了使4個信道在一幀數據的發送或接收過程中,主機不干預,故將發送的一幀數據在發送開始前由CPU用批命令放入卡上的SRAM中;同樣,在接收過程中,卡上DMA將接收到的數據放入SRAM中,等一幀接收完成后,再用批命令取出,放入系統存儲器中。卡上SRAM不占用主機內存地址,采用I/0映像,該適配器插入主機之后,主機通過系統I/O地址對其訪問,這由地址產生器完成。總線接口包括數據收發器,數據開關電路,讀、寫及中斷等控制電路,地址譯碼等。波特率產生器提供了一個可編程的時鐘信號發生器,用戶可自行設置通信速率,供工作于內時鐘方式時使用。接口電路提供符合RS-232/CCITT V.24和RS-422A標準的接口信號。 3通信流程設計 如果要發送一幀數據,CPU用批命令將數據放到本卡SRAM中,然后設置相應的發送DMA通道。DMA通道是非自動重裝方式,啟動8274控制器發送,然后CPU就不需要管理,由卡上硬件自動發送。 如果需要接收數據,啟動接收通道。接收通路自動搜索輸入信號,搜索到數據幀時,由卡上DMA控制器來管理,將接收的數據放入本卡SRAM中,并向CPU請求中斷,讀出數據。 4 總線竟爭設計 由于同時可進行四路通信,且CPU可隨時對某一路發控制命令或訪問卡上SRAM存儲器,就將出現CPU與本卡主設備DMA爭用本卡總線的狀況。由于ISA總線沒能給出CPU指令排隊狀態序列,這給總線仲裁帶來了困難,而本卡的總線竟爭、仲裁是由可編程邏輯器件設計的狀態機來完成的。狀態機使用一個4MHz信號作為時鐘,共設3種狀態: ① CPU控制狀態。 ② DMA控制狀態。 ③ 空閑狀態, CPU及DMA均未能得到控制權。 當狀態機檢測到無CPU及DMA申請總線使用權時,就進入空閑狀態,而一旦CPU或DMA請求總線,狀態機立即將總線使用權交給CPU或DMA。如果正在CPU控制狀態期間,DMA申請總線使用權,狀態機仍然判定CPU控制總線,讓DMA處于等待,直到檢測CPU指令完成,狀態機才轉為DMA控制狀態。如果在DMA控制狀態時,CPU申請總線使用權,狀態機仍然判定DMA控制總線,讓CPU處于等待,直至DMA字節傳送完,狀態機轉為CPU控制狀態。CPU及DMA對總線的使用權是單個指令或字節傳送,不設置總線封鎖,因而CPU、DMA可頻繁交換使用權,不會出現等待時間過長的現象。 通信卡的驅動程序設計 1 設備驅動程序的I/O模型 通信卡的驅動程序是利用WindowsXP的DDK軟件開發的標準的核心態設備驅動程序。它使用統一的“文件”形式,用戶可以通過代表通信卡設備的文件名,在WIN32子系統中用文件操作函數來訪問。該設備驅動和程序可以根據用戶的需要,設置為自動加載,或手動加載,也可以動態的加載該驅動程序。通信卡的驅動程序設計成為支持同步I/O模型,也可以為異步I/O模型。 2 發送數據I/O例程設計 在用戶態提交發送任務到核心態,由I/O管理程序負責調用驅動程序,驅動程序發送IRP交給硬件,假若當前發送器不忙,則具體的發送操作全部由發送器自行完成,而驅動程序則返回已經一個本幀可以發送的標志。具體的發送完成結果則可以在發送任務完成后查詢得到。可是,如果程序向當前設備發送器提交發送任務時,該發送器正在處理上一幀,那么則有兩種方法處理。 ① 立即方式:立即返回一個錯誤,當前設備忙,不能發送。 ②阻塞方式:I/O管理器程序會調度相應的異步處理例程,將當前的發送任務放進任務隊列中,返回一個標志:I/O掛起,當前設備忙,發送任務提交任務隊列。驅動程序會在發送器空閑時,提交任務隊列中的發送任務給發送器。完成發送任務后,將相關文件句柄設為有信號狀態,通知本次發送任務完成。 3接收數據I/O例程 接收數據例程采用客戶/服務器的模式設計。由于用戶的接收請求和硬件的接收并不是同步的,所以在設計中,為避免丟失數據,考慮創造一個專門的接收線程。這樣,同步用戶請求、接收線程、硬件層之間的通信就必須仔細地設計。圖2示意了用戶態接收請求、接收線程以及硬件層之間的通信同步。 圖2 用戶態接收請求、接收線程與硬件層之間的通信同步 ① 硬件層與接收線程之間通信 硬件層與接收線程之間通信的同步是通過同步事件對象來實現的。同步事件對象通常處于無信號狀態,只有當成功地接收到一幀時,才將該事件置為有信號狀態。接收線長久等待同步事件對象,在沒有收到數據時,因同步事件對象處于無信號狀態而阻塞。當硬件檢測到數據時,實時中斷服務程序負責將同步事件對象置為有信號狀態,接收線程就會釋放阻塞。將通信卡SRAM上的接收數據讀進接收線程緩沖區隊列,然后將同步事件對象置為無信號狀態,接收線程再次阻塞,等待接收下一幀數據。 ② 用戶層和接收線程之間的通信 當用戶提交接收任務時,由驅動程序的調度程序讀取接收線程的緩沖區隊列,并將標志置為“空”,同時將緩沖隊列事件置為無信號狀態,并返回,如果緩沖區是空,則 ● 立即方式:立即返回無數據。 ● 阻塞方式:阻塞直到有數據隊列進入。接收隊列的每個緩沖區都對應一個通知事件,如果接收線程將SRAM中的數據讀進隊列,就將相應的通知事件置為有信號狀態,用戶請求就等待該通知事件,只要有數據在隊列中,就讀取返回,否則被阻塞。 4 硬中斷服務程序設計 通信卡在全雙工的通信中具有實時性,而且在較高的波特率,硬中斷非常多。為了防止高優先級中斷過多地搶占CPU時間,設計中采用了實時中斷服務程序和延遲過程調用的方法。 在WindowsXP系統中,每個內核函數和過程都運行于特定的優先級。較高優先級的函數或事件可以搶占較低優先級,反之則不然。實時中斷服務程序ISR運行于DIRQL級,具有較高的優先級,它只能被更高級的硬中斷所搶占,不會對同級或較低優先級的硬中斷的響應。所以,在實時中斷服務程序中,只做盡量少的必須工作,即讀出中斷向量,而將大量的數據傳送及處理等工作交給延遲過程DPC去完成。因為DPC過程運行于DISPATCH_LEVEL級,是相對較低的優先級,它可以被任何級的硬中斷所搶占。這樣,既保證了硬中斷的及時響應,又提高了程序的性能。 5 驅動程序入口例程 WindowsXP為每個核心態的驅動程序提供了一個默認的標準入口點DriverEntry()。設計中,考慮到該例程運行于PASSIVE_LEVE級,系統只運行該例程一次就拋棄了,所以在驅動程序中用到的重要數據、對象等都不能保存在DriverEntry()例程中,必須在初始化過程中分配一塊NoPaged內存來保存。通信卡的驅動程序的DriverEntry()例程主要完成如下功能。 讀取Registry的硬件配置信息;聲明I/O地址、中斷等資源;創建代表通信卡的設備名MPSC,該名字對WIN32子系統是可見的;設置調度例程入口點;分配一塊NoPaged的內存,存儲重要信息;連接硬中斷,設置中斷服務程序;初始化線程、事件、信號燈、DPC等內核對象;返回狀態STATUS_SUCCESS。 如果在以上過程中遇到錯誤,則需要做以下工作:斷開硬中斷;釋放硬件資源;將相關的錯誤信息打包,并記錄;返回錯誤信息。 6 設計驅動程序中需要注意的問題 于通信卡在應用中具有一定的實時性,為了克服中斷的不確定性,提高系統的性能,開發了WindowsXP系統所有驅動程序中最難的異步驅動程序。在系統的內核開發,異步模型I/O操作中,內核對象的同步十分復雜,細微的差錯都會導致系統徹底崩潰。在設計驅動程序中需要注意以下問題。 ● 在程序中用到的內核對象:事件、信號燈、線程以及轉鎖等,都必須將其存儲在Nopaged內存中,否則,會造成系統崩潰。 ● 在DPC例程中,如果要訪問中斷服務程序ISR程序中用到端口地址,一定要將訪問語句放在系統提供的同步例程中,這是因為當DPC例程訪問該端口時,有可能被優先級高的ISR例程所搶占,而造成數據錯誤。 ● 驅動程序一定不要訪問WIN32子系統的運行庫函數。 |