驅動程序范文

時間:2023-04-09 11:54:56

導語:如何才能寫好一篇驅動程序,這就需要搜集整理更多的資料和文獻,歡迎閱讀由公務員之家整理的十篇范文,供你借鑒。

驅動程序

篇1

2、下拉菜單中選“屬性”,

3、屬性中選“硬件”,

4、硬件里選“設備管理器”,

5、設備管理器中點開“端口”,

6、端口里右鍵點“打印機端口”

7、選“屬性”

8、屬性里選“驅動程序

9、驅動程序里選“驅動程序詳細信息”

10、此時在驅動文件窗口里顯示的就是驅動文件所在位置及名稱。

篇2

這歸結于優化的功效,很多玩家都可以有針對性地對游戲進行優化設置,調整系統、優化資源,同時對游戲進行設置上的更改,尋找最佳的平衡點。

現在,我們來嘗試針對NVIDIA及ATI兩種主流顯卡品牌的驅動程序進行優化說明,來看看它們有什么秘密吧!

ATI 提高《Doom》運行速度有技巧

如果你想玩《Doom》一類采用OpenGL的游戲,尤其是當你的電腦使用ATI顯卡時,你必定會感到很煩惱。OpenGl性能不強使得ATI的顯卡在以《Doom》為首的OpenGL游戲中一向表現不佳。因此,針對OpenGL部分的調節非常必要,盡可能提高這方面的性能是優化ATI顯卡驅動程序的重要方向之一。

切換到ATI催化劑驅動程序的OpenGL選項卡上,選中“主要設置”的“自定義設置”,然后進行細節調整。將“紋理選項”和“Mipmap”的拉桿向左拉到“性能”上,這樣可以保證在不明顯降低畫面質量的情況下使OpenGL游戲速度得到保證,同時將“等待垂直同步信號”調整成“始終為關”。

要想將ATI顯卡的潛力進行最大化的挖掘,還要進行自定義設置。勾選“使用自定義設置”項后,再點擊“自定義”按鈕就可切換到自定義設置頁面。在其中“消除混疊”其實就是指全屏抗鋸齒,在這里,如果你的顯卡是低于X1000系列的,那么最好選擇2×或者干脆關閉。但是,最高級的顯卡也不要妄想開啟6×,這時根本無法體驗游戲樂趣了。

NVIDIA 讓秘密大白于天下

相比之下,NVIDIA的優化設置更為科學,不僅有預置的優化方案,也有適合高級玩家的細節調整。

先說簡單的方法,在NVIDIA的ForceWare驅動程序中提供了很多游戲、應用程序的優化設置方案,當你想運行某個游戲前,只要在驅動控制面板中選中相應的優化方案就可以了。驅動中的方案會不定期進行調整、添加,即便很多新的游戲,也會在短期內擁有相應的預置優化方案。

當然,還是有很多玩家不會滿足于預置方案,自主優化是另外一種選擇。其中最能影響性能及兼容性的選項莫過于“Anisotropic filtering”,即各向異性過濾了。這個選項在開啟時會讓畫面更加精細,但是,它還帶來了性能大幅度下降、兼容性不佳的“副作用”,所以,如果你的顯卡并不是非常新,但又想玩新游戲,不如把這個選項關閉,以獲得更好的運行速度。

篇3

關鍵詞:USB協議;Linux驅動;USB Device驅動

中圖分類號:TP316文獻標識碼:A文章編號:1009-3044(2011)22-5418-02

Design of USB Device Drver Program on linux

SUN Yong-gang, JIAO Li-fei

(College of Science, GuiZhou University, Guiyang 550025, China)

Abstract:USB interface, with its efficient, reliable and widely is used in various embedded products. However, existing data on linux operating system, more studies USB Host, USB Device driver rarely is done. Therefore this paperthrough a simpleintroduction of USB protocol, as well as analysis of USB driver architecture about linux, is about an design of USB Device driver of linux systemfor embedded microprocessor S3C2440 .

Key words: USB agreement; linux driver;USB device driver

嵌入式產品通過的USB接口品可以很方便與PC的USB進行通信以完成數據的傳輸與交互。ARM嵌入式處理器性以其性能高、功耗低而被廣泛地應用于消費電子、工業控制等眾多領域。以ARM內核為核心集成了USB功能的處理器使得產品更簡潔、更靈活、更方便。S3C2440集成了ARM920T內核,帶MMU功能,可運行linux操作系統,同時帶有兩個USB Host一個USB Device控制器,因此在此基礎上完成Linux 下的USB Device驅動程序有著重要的意義。本文是以此處理器為核心的嵌入式智能終端的Linux下的USB Device驅動程序設計。

1 USB體系結構及協議

1.1 USB硬件系統結構

USB接口是由+5V電源線、電源地線、信號線D+、信號線D-四根電纜線組成接口。其中+5V電源是向設備提供電源,信號線作用是傳輸數據, 為了提高信號傳輸的抗干擾能力這兩根數據線采用差分傳輸。主機可以通過D+和D-線的電平高低來確設備是高速設備還是全速設備。

1.2 USB數據傳輸通道

USB主機與USB設備由很多端點構成,它們之間通過端點進行通訊。通過設置與些端點相對應的寄存器,可以為這些端點分配唯一的地址(由端點號和傳輸方向組成)。USB總線支持四種傳輸類型,他們分別是控制傳輸、同步傳輸、中斷傳輸、批量傳輸。端點O只支持控制傳輸。

1.3 USB總線枚舉

USB總線枚舉就是當USB設備連接到USB主機時,主機通過缺省管道以控制傳輸方式來獲取USB設備發來的設備描述符、配置描述符、接口描述符、端點描述符信息,并根據這些描述相關內容對USB設備進行相應的配置。

2 Linux USB 驅動程序

在Linux系統中,USB驅動程序可以分為USB Host驅動程序和USB Device驅動程序。Linux USB Host驅動程序和USB Device驅動程序總體架構如圖1所示。

從圖1可以知,在Linux USB Host中,USB控制器驅動是運行在USB 控制器硬件上面的的驅動動程序。該驅動實現了對USB 控制器硬件進行控制,一般稱為USB固件驅動程序。USB設備驅動處于USB驅動的最頂層,它主要實現USB設備如何與主機進行通信。處在USB主機控制器驅動與USB設備驅動之間的是USB核心層,起到驅動程序橋梁的作用,該核心層為USB主機USB主機控制器驅動提供編程接口。

Linux系統中, USB Device驅動分為UDC驅動、Gadget API、Gadget驅動三個層次結構。UDC驅動處USB Device控制器硬件之上,該驅動程序控制USB控制器硬件工作,同時向上層提供操作USB控制器硬件的回調函數。處在中間層的是Gadget API層,該API向下層和上層提供統一的編程接函數的封裝。Gadget驅動程序完成設備功能的實現。通過編寫不同Gadget驅動程序可以使設備具有不同的功能。

3 S3C2440 USB Device驅動

3.1 S3C2440 USB接口特性

S3C2440嵌入式微處理器集成了一個設備控制器。該設備控制器具有以下特征:

1) 完全兼容USB1.1的協議。設備全速運行時可達到了12Mb/s。

2) 支持控制、中斷和批量傳輸,批量傳輸支持DMA接口。

3) 自帶5個的端點。端點EP0帶有16byte的FIFO,該端點為雙向的控制端點,其余4個端點都帶有128字節輸入/輸出的FIFO(異步雙端口RAM)的,支持中斷或DMA批量傳輸。

3.2 S3C2440 USB Device驅動程序設計

一個完整的S3C2440 USB Device驅動程序由S3C2440_UDA驅動和gadget驅動兩部分構成。S3C2440_UDA驅動是用來控制S3C2440的USB Device硬件控制器器,并把對硬件控制操作抽象為函數接口供上層調用。USB gedget驅動程序運行在S3C2440_UDA驅動程序之上的,不同的gedget驅動程序使該設備具有不同的功能。

Linux gadget驅動程序主要涉及到2個重要的結構體usb_gadget_driver和struct file_operations結構。其中usb_gadget_driver結構體包括bind、setup、disconnect等一些函數。Linux Gadget提供usb_gadget_register_driver函數對Gaget驅動進行注冊。當Gadget驅動被注冊后,Linux內核就會調用結構體usb_gadget_driver中的bind函數把Gadget驅動與UDA驅動進行綁定,這樣就可以在Gadget驅動中使用UDA提供的統一接口函數。

bind函數中需要完成以下工作:

1) 使用usb_ep_autoconfig函數申請以后用到的傳輸端點。

2) 通過usb_ep_alloc_request函數為Gadget驅動分配一個請求。

3) 通過調用register_chrdev_region注冊設備驅動程序。

Bind函數完成這后當有USB Host 向USB設備發出請求時,Linux系統將調用setup函數來響應請求。Setup函數把設備的設備描述符、配置描述符、接口描述符以及以后需要使用的幾個端點描述符發送給USB Host,這些配置信息的發送都是通過usb_ep_queue函數來完的。

struct file_operations結構包含有open、read、write等函數。通過該結構體定義的變量被register_chrdev_region函數注冊后該設備就可以像字符設備那樣使有了。該結構中的一些函數完成的功能如下:

1) open函數通過init_waitqueue_head完成等待隊列初始化。

2) read函數通過alloc_ep_req函數分配一個讀請求變量,并為該變量中的complete設置一個請求完成函數,調用usb_ep_queue函數向端點提交I/O讀請求。當內核從USB Device讀到數據時就會調有剛才的完成函數。在完成讀數據之前可以通過add_wait_queue和schedule()函數讓進程掛起,在完成函數中喚醒掛起的進程。

3) write函數通過alloc_ep_req函數分配一個寫請求變量,并為該變量中的complete設置一個請求,調用usb_ep_queue函數向端點提交I/O寫請求。當內核向USB Device寫完數據時就會調有剛才的完成函數。在完成寫數據之前可以通過add_wait_queue和chedule()函數讓進程掛起,在完成函數中喚醒掛起的進程。

至此整個驅動程序就設計完成了,圖2為USB Host 與 USB Device 通信測試效果。

4 結束語

USB Device 為眾多電子產品提供了一個與PC信息交互的更好的方案。本文通過對USB協議介紹,以及對Linux下USB驅動程序進行分析,在此基礎上實現了USB Device驅動程序進行設計。實踐表明該設計是可行的。

參考文獻:

[1] 馮國進.嵌入式Linux驅動程序設計從入門到精通[M]北京:清華大學出版社,2008.

[2] 薛園園.USB應用開發技術大全[M].北京:人民郵電出版社,2007.

[3] 劉少峰,韋克平.USB軟件系統的開發[J].計算機應用研究,2002,19(30).

[4] 于明,范書瑞,曾祥燁.ARM9嵌人式系統設計與開發教程[M].北京:電子工業出版社,2006.

篇4

首先找到我們電腦上的此電腦或者計算機,鼠標右擊彈出菜單選擇管理。

進入管理的頁面之后我們找到設備管理器。

在設備管理器下我們找到一個手機驅動的標識,如果這里安裝過了我們只需要自動更新一下即可,

如果沒有安裝的話我們使用數據線連接電腦查看我們的磁盤有沒有手機磁盤。

都沒有的話我們需要找到手機品牌官網,輸入自己的手機型號。

篇5

關鍵詞:VxWorks;USB設備驅動;管道;回調

中圖分類號:TP316文獻標識碼:A文章編號:1009-3044(2008)24-1200-04

Design of USB Device Driver Based on Real Time Operation System VxWorks

WANG Hao

(College of Computer, Xidian University, Xi'an 710071, China)

Abstract:The architecture of USB dirver based on VxWorks is given, general method and key technology in developing USB device dirver are analyzed.Then the device driver of LM9833 is implemented, expectant performace of target system is achieved. The general process of developing USB device dirver used in this paper can be refered by others USB device driver developing based on VxWorks.

Key words: VxWorks; USB device driver; pipe; callback

1 VxWorks下USB驅動概述

VxWorks是WindRiver公司開發的具有工業領導地位的高性能實時操作系統(Real Time Operation System, RTOS)內核。VxWorks5.5實現了USB1.1協議棧。圖1提供一個VxWorks下USB主驅動棧的簡單結構。

在棧的最低層是USB主控制器(USB Host Controller, HC),這是主系統中控制每一個USB設備的硬件。在主控制器上層是一個與硬件獨立的主控制器驅動(USB Host Controller Driver,HCD)。USBD是在HCD之上的與硬件獨立的模塊,USBD管理每一個與主機相連的設備,向高層提供可與USB設備通信的路徑,USBD實現了USB總線枚舉、總線帶寬分配、傳輸控制等操作。在棧的頂層是USB Client 模塊,一般是特定的USB Class Driver,負責管理與USB主機連接的不同類型的設備。用戶自己的USB設備驅動程序通常是在USBD這一層上完成。

2 VxWorks下USB設備驅動詳解

2.1 驅動程序提供的函數

2.1.1 向應用程序提供的接口函數

設備驅動程序的主要作用是向上層應用程序屏蔽硬件,向上層應用程序提供統一的接口函數,驅動程序一般需要實現的函數如表1所示。

圖1 USB主驅動棧結構

表1 驅動程序提供的接口

usbMSCDevInit();這是一個通用的初始化例程,可以在BSP中調用,也可以由應用程序來調用,但只能被調用一次,該例程初始化必須的數據結構,并向USBD注冊驅動程序。USB設備與USB主控制器之間的所有操作都通過USBD來完成,因此在調用usbMSCDevInit()之前必須確定USBD已經初始化,在使用USB設備之前也要確保USB主控制器已經掛接到USBD。

usbMSCDevCreate();這是一個創建設備例程,當有設備接入時,回調函數usbMSCDevAttachCallback()調用該例程創建一個邏輯設備,當這個例程被調用時必須在系統中存在一個實際的USB物理設備。

usbMSCDevDestroy();從系統中刪除設備。首先釋放設備占有的資源,從設備鏈表中移除該設備,同時調用usbdPipeDestroy()銷毀該設備與主機之間的通信管道,最后釋放設備結構體。

usbMSCDevShutDown();該例程卸載已注冊的設備驅動程序,并回收所有已分配資源,包括刪除設備、回收信號量等。

2.1.2 兩個重要的回調函數

在編寫USB設備驅動程序時,除了上述接口函數外,還需要編寫另外兩個重要的回調函數:usbMSCDevAttachCallback()和usbMSCIrpCallback()。usbMSCDevAttachCallback()用于跟蹤設備的請求實現動態接入或刪除;usbMSCIrpCallback()是一個IRP callback,當每一個IRP執行完成之后調用該回調函數,實現IRP之間同步。

2.2 設備標識

在VxWorks中USB設備用USBD_NODE_ID來唯一區別,它是USBD用來跟蹤一個特定設備的句柄,它與USB設備的真正USB地址無關。這表明Client并不關心設備是物理上與哪一個USB主控制器連接,應用為每個設備抽象一個Node ID,使Client可以不用考慮物理設備的連接細節以及USB地址分配。當一個Client通知有一個設備連接或斷開時,USBD經常通過Node Id來定位設備。同樣,當USB設備與USBD通信時,它必須向USBD傳遞該設備的Node Id。Node ID通常作為設備結構體的一個重要成員。

2.3 回調(Callback)

USB操作是嚴格遵守時序的,WindRiver USBD采用回調機制來解決時序問題。例如在USBD識別一個動態連接事件之后會激活一個動態attach callback操作,這是一個注冊到USBD的回調例程,回調函數會判斷當前的操作,如果是接入(USBD_DYNA_ATTACH),就會調用usbMSCDevCreate()來在當前的USB句柄上創建一個邏輯設備結構體;如果是移出(USBD_DYNA_REMOVE)就會調用usbMSCDevDestroy()來刪除設備。同樣,當USBD處理完成一個USB IRP之后,Client的一個IRP callback被激活,該回調例程是由Irp.userCallback域來指定。在IRP callback中釋放IRP同步信號量。

2.4 數據傳輸

USB設備與主機之間是通過USB管道進行通信的。一旦Client配置完一個設備,就可以利用USBD提供的管道(pipe)傳輸功能與設備進行數據交換。管道是建立在USBD Client與設備特定的endpoint之間的單向通道。調用usbdPipeCreate()函數創建一個管道后返回一個管道句柄USBD_PIPE_HANDLE,以后所有的讀寫操作都分別在各自的管道句柄上進行。管道在剛創建完后是處于終止的狀態,為了能有效使用它們,還必須用usbdFeatureClear()來清除該終止狀態。每一個管道有以下性質:USBD_NODE_ID、端點地址,管道類型、數據流方向、包的最大有效載荷量、帶寬需求等。對于塊傳輸沒有帶寬限制。VxWorks的USB驅動程序的各層驅動程序間通過IRP機制進行通信,當有數據傳輸請求發生時,上層向下傳遞IRP。USBD得到請求后,調用HCD接口,將IRP轉化為usb的傳輸。這就需要提供一個特殊的回調函數usbMSCIrpCallback(),當塊傳輸結束時調用該回調函數。以下是讀設備的具體過程。

1) 創建設備時創建out和in管道:

usbdPipeCreate(usbdHandle, NodeId, outEpAddress, configuration, interface, USB_XFRTYPE_BULK, USB_DIR_OUT,maxPacketSize,0,0, outPipeHandle);

usbdPipeCreate(usbdHandle, NodeId, inEpAddress, configuration, interface, USB_XFRTYPE_BULK, USB_DIR_IN,maxPacketSize,0,0, inoutPipeHandle);

2) 定義IRP callback:usbMSCIrpCallback(pVOID p)。

3) 構造USB_IRP outIrp請求包。

4) 提交outIrp:usbdTransfer (usbdHandle, outPipeHandle, &outIrp)。讀命令在outIrp.bfrList[0].pBfr域中。

5) 等待outIrp處理結束,結束調用usbMSCIrpCallback()釋放IRP同步信號量。

6) 構造USB_IRP inIrp請求包。

7) 提交inIrp:usbdTransfer (usbdHandle, inPipeHandle, &inIrp)。

8) 等待inIrp處理結束,讀取的數據在inIrp.bfrList[0].pBfr域中。

2.5 多個設備管理

驅動程序用LIST_HEAD 來存儲多個設備,每個接入的USB設備利用其LINK節點加入到LIST_HEAD鏈表當中;一個LINK節點包含三部分:linkFwd指針、linkBack指針和pStruct指針;其中pStruct指向一個待連接的設備結構體。當有一個設備創建完成時調用usbListLink()將該設備加入鏈表,刪除設備之前調用usbListUnlink()從鏈表中移出該設備。由于USB設備是用Node ID來唯一標識的,在查找設備的時需要利用usbListNext()來遍歷設備鏈表,直到某個設備的Node ID與特定設備的Node ID相匹配為止。在多個設備管理時,采用USBD_NODE_ID usbd_scan_id[DEVICE_NUM]數組來存放多個設備的Node ID,在對設備進行讀寫時只需提供設備的索引序號就可以直接得到設備Node ID,提高了對設備的訪問速度。

3 VxWorks下LM9833驅動程序實現

3.1 LM9833 USB接口簡介

LM9833掃描儀控制器在一個單獨的IC上可以提供一個完整的USB圖像掃描控制系統。它的USB接口提供4個USB端點(Control Endpoint,Interrupt Endpoint,Bulk In Endpoint和Bulk Out Endpoint),內部有00~7F個寄存器,其中00寄存器是存放一個8bits的圖象數據,其它分別為控制或狀態寄存器。通過向bulk out端點發送四字節的讀命令可以從bulk in端點讀取這些寄存器的值,也可以向bulk out端點發送四字節的寫命令加待寫數據完成寫寄存器。四字節命令依次表示:讀寫模式(1字節)、起始地址(1字節)、讀寫長度(2字節)。其中讀寫模式bit0為0表示寫,1表示讀;bit1為0表示非增模式,為1表示增模式,即讀寫寄存器完成之后寄存器地址加1。LM9833的工作過程就是通過讀寫這些寄存器來完成的。

3.2 設備描述符結構

typedef struct _usbScanDev

{

USBD_NODE_ID scanDevId; /* USBD node ID of the device */

UINT16 configuration; /* Configuration value */

UINT16 interface; /* Interface number */

UINT16 altSetting; /* Alternate setting of interface */

UINT16 outEpAddress; /* Bulk out EP address */

UINT16 inEpAddress; /* Bulk in EP address */

USBD_PIPE_HANDLE outPipe; /* Pipe handle for Bulk out EP */

USBD_PIPE_HANDLE inPipe; /* Pipe handle for Bulk in EP */

USB_IRP inIrp; /* IRP used for bulk-in data */

USB_IRP outIrp; /* IRP used for bulk-out data */

USB_IRP statusIrp; /* IRP used for reading status */

UINT8 * scanInData; /* Pointer for bulk-in data */

UINT8 * scanOutData; /* Pointer for bulk-out data */

BOOL connected; /* TRUE if USB_SCAN device connected*/

LINK scanDevLink; /* Link to other SCAN devices */

UINT8 CommandByte[4]; /* Which read/write command the device */

UINT16 actBytes; /* actual bytes will be transfered */

UINT8 direction; /* data transfer direction */

} USB_SCAN_DEV, *pUSB_SCAN_DEV;

設備描述符結構中包含了設備的一些重要信息和訪問該設備時的必須資源,如Node ID、IN/OUT管道、IN/OUT IRP等等。

3.3 注冊設備(LM9833)驅動程序

注冊驅動程序一般包含兩大步:與USBD建立連接和注冊attach callback。以下是注冊LM9833驅動程序的源代碼。

#define USB_SCAN_CLASS 0xff

#define USB_SCAN_SUB_CLASS0x00

#define USB_SCAN_DRIVE_PROTOCOL0xff

STATUS usbScanDevInit()

{……

if(usbdClientRegister ("SCAN_CLASS", &usbdHandle)!=OK||

usbdDynamicAttachRegister (usbdHandle, USB_SCAN_CLASS, USB_SCAN_SUB_CLASS,

USB_SCAN_DRIVE_PROTOCOL, usbScanDevAttachCallback) != OK)

……

}

usbScanDevInit()調用usbdClientRegister()向USBD注冊一個名為SCAN_CLASS的Client,同時調用usbdDynamicAttachRegister()向USBD注冊一個回調例程usbScanDevAttachCallback (),跟蹤該Client請求,當設備動態地接入或移出系統時會自動地調用該回調函數。一個Client在利用usbdDynamicAttachRegister()進行注冊時只對特定的class、subclass、protocol感興趣。在成功注冊Client后,USBD返回一個Client句柄(USBD_CLIENT_HANDLE),以后對USBD的調用都會用到這個句柄。Attach callback 如下。

LOCAL VOID usbScanDevAttachCallback

(

USBD_NODE_ID nodeId,

UINT16 attachAction,

UINT16 configuration,

UINT16 interface,

UINT16 deviceClass,

UINT16 deviceSubClass,

UINT16 deviceProtocol

)

該回調函數主要響應外部設備的動作,實現USB設備的動態接入和移除。

3.4 創建設備

創建設備函數如下:

LOCAL STATUS usbScanPhysDevCreate(USBD_NODE_ID nodeId, UINT16 configuration, UINT16 interface)

當接入設備時激活usbScanDevAttachCallback()操作,回調函數會根據接入(USBD_DYNA_ATTACH)動作調用usbScanPhysDevCreate()創建一個邏輯設備,在創建設備的同時,創建設備與USB主機之間通信的管道(pipe)。管道是建立在USB設備端點(endpoint)之上,是主機與設備之間數據傳輸的單向通道。設備與主機之間數據傳輸管道是建立在批量端點(bulk endpoint)之上,有BULK_IN和BULK_OUT兩個端點,從而建立雙向的數據通路。最后將該設備加入設備鏈表,進行多個設備的管理。創建設備流程如圖2所示。

圖2 創建設備流程

3.5 讀寫設備

對設備進行讀寫時,首先需要將讀寫函數轉換成設備能夠識別的命令,對于LM9833來說,需將讀寫函數轉換成LM9833所能識別的四字節讀寫命令,讀寫時將這四字節的命令置于IRP包數據域的最前端,這樣到數據到達設備時首先接收到的是四個字節的命令,LM9833會根據這四個字節的命令完成相應的功能。讀寫函數原型為:

STATUS usbScanRead/usbScanWrite

(

UINT dev, /* sequence number of the device */

UINT Addr, /* start address in register */

UINT8 *pBuffer, /* pBuffer to receive/send data from/to device*/

UINT Len, /* lenth of pBuffer */

BOOL bIncrement /* incremece of address in register or not */

)

LM9833的一個讀寫控制流程如圖3所示,查找設備流程如圖4所示。

圖3 LM9833讀寫控制流程

圖4 查找設備流程

設備命令組幀:

const unsigned int MODE_INC_READ = 0x03;

const unsigned int MODE_NOINC_READ = 0x01;

const unsigned int MODE_INC_WRITE = 0x02;

const unsigned int MODE_NOINC_WRITE = 0x00;

switch (Cmd)

{

case USB_SCAN_WRITE:/* bulk out */

pScanDev->CommandByte[0] = (bIncrement>0)? MODE_INC_WRITE : MODE_NOINC_WRITE;

pScanDev->CommandByte[1] = Addr+((bIncrement>0)? i : 0);

pScanDev->CommandByte[2] = (Len >> 8); /* length of the data to be written */

pScanDev->CommandByte[3] = (Len & 0xff);

memcpy(pScanDev->scanOutData, pScanDev->CommandByte, 4); /* 4 bytes Lm9833 command followed by write data */

memcpy(pScanDev->scanOutData + 4, pBuffer + i, Len);

pScanDev->actBytes = Len+4; /* actual length to be transfered*/

pScanDev->direction = USB_SCAN_DIR_OUT;

break;

case USB_SCAN_READ: /* bulk in */

篇6

引言

近年來電力行業為了快速部署變電站,采用了建造整體變電所的方法:在生產基地將變電站的內部設備安裝、調試完成,只留下與外界的接口,整體運到變電站所在地后進行安裝和簡單調試即可投入運行。其內部設備通過CAN總線進行通信,系統原有的監控軟件基于DOS系統,維護調試比較困難,因此想要尋求更方便、友好的系統支持。經過比較,嵌入式操作系統市場上風頭正勁的Windows CE .NET成為最終選擇。微軟的最新產品Windows CE.NET提供了端對端的開發、調試手段,可以不拆卸設備的情況下通過Telnet登錄到WindowsCE上進行調試和維護,其系統本身為嵌入式市場進行重新設計,包括創建一個基于WindowsCE的定制設備所需的一切。這樣就需要將原來DOS下的程序移植到WindowsCE.NET下,但是各個硬件廠商目前還沒有提供CAN通信卡在Windows CE.NET下的驅動,所以開發Windows CE.NET下的CAN卡驅動成為項目推行中的關鍵一環。

本文主要針對研華的雙口CAN卡PCM3680進行分析,介紹在WindowsCE.ENT系統下進行底層設備驅動開發的方法并提供CAN通信的實例。

1 CAN總線通信協議及CAN通信卡介紹

CAN總線是德國Bosch公司20世紀80年代初為解決現代汽車中眾多的控制與測試儀器之間的數據交換而開的一種串行數據通信協議。它是一種多主總線,廢除了傳統的站地址編碼,而代之以對通信數據塊進行編碼。這種方法使網絡內節點個數在理論上不受限制,擴展格式中的29位的標識碼便可以定義2 29個不同的數據塊。

在本項目中使用的是研華的PCM3680,這是一塊嵌入式PC104的雙口CAN總線通信卡;CAN控制器采用Philips的獨立CAN控制器SJA1000芯片;CAN收發器采用Philips的P82C250,可以同時操作兩個CAN網絡,提供高達1Mb/s的傳輸速度。PCM3680支持很寬的中斷范圍:中斷3、4、5、6、7、9、10、11、12、15,同時1000V的光電隔離提供系統高可靠性。在CAN卡通信中,要用到CAN控制器中的很多寄存器,各個寄存器的含義和作用可以參考控制芯片的說明書。圖1列出驅動程序設計中用到最主要的寄存器結構。

2 CAN卡驅動底層函數設計

本方案設計CAN驅動是放在Windows CE操作系統的內核下層,位于OEM adaptation layer(OAL)層的一個真正的驅動,而不是在主程序中的串口操作。在Windows CE的設備管理器可以看到CAN1和CAN2兩個端口,并且可以查看其工作的正常與否和對其進行配置。如:中斷號和I/O地址。

2.1 CAN卡寄存器讀寫函數

CAN卡的通信是通過操作CAN卡上的CAN控制器進行的。在CAN控制器中有很多寄存器,如控制寄存器、命令寄存器、狀態寄存器、中斷寄存器等,通過讀寫這些寄存器中的命令狀態字可以檢測和控制CAN卡的行為。在Windows CE.NET下,通過調用DOK中的API函數HalTranslateBusAddress,將CAN卡分配的物理地址映射為邏輯地址。這樣各個寄存器對應的就是CAN卡基地址的偏移地址,因此,對寄存器的讀寫就轉化為對內存地址的讀寫。下面是CAN卡寄存器的讀寫函數:

*在偏移量為off的地址讀取一個字節的數據inline BYTE CANR(LPCAN_HW_OPEN_INFO hCan,DWORD off)

{

return hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off];

*將一個字節數據寫到偏移量為off的地址中inline VOID CANW(LPCAN_HW_OPEN_INFO hCan,DWORD off,BYTE val)

{

hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off]=val;

}

參數LPCAN_HW_OPEN_INFO定義的是CAN卡的數據結構,其中成員lpMappeBaseAddr[0]表示的是映射后基地址,lpMappedBaseAddr[1]就是基地址+1的地址,對應CAN卡的寄存器是命令寄存器。通過上述兩個函數可操作CAN卡上的所有寄存器。

2.2 CAN卡初始化

CAN卡的控制器比較復雜,在通信前必須確認硬件信息正確性、初始化各寄存器。初始化函數的基本流程如圖3所示。

第一步,檢查端口號和硬件信息的正確性,主要是CAN卡中斷號是否有效。

第二卡,設置CAN卡默認參數:

CanCardConfigInfo CAN_DEFAULT_SETTING=

{0X00,0XFF,0X03,0X1C};/*設置默認波特率為125Kbps*/

DWORD dwThreadID =0;

PHYSICAL_ADDRESS phyAddr={hwInfo->dwIOBaseAddr *16,0 };

第三卡,用WinCE API函數LocalAlloc為CAN卡驅動中用到的數據結構分配緩沖區;通過HalTranslateBusAddress和MmMapIoSpace函數映射I/O地址,提供直接訪問設備的虛擬地址:

if(!HalTranslateBusAddress(Isa,0,phyAddr,0,&phyAddr))

goto _ExitInit;

hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr=

(LPBYTE)MmMapIoSpace(phyAddr,CANCARDADDRLEN,FALSE);

if(!hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr)

goto _ExitInit;

如果分配內存或映射邏輯地址失敗,則退出初始化程序,CAN卡初始化失敗。

第四步,初始化讀寫屬性、共享模式、讀超時時間和第二個CAN口的基地址。

第五步,創建CAN卡事件和數據接收事件:hCan->lpCanHWInfo->hCanEvent=CreateEvent(NULL,FALSE,FALSE,NULL);

hCan->lpCanHWInfo->hRecvMsgEvent=CreateEvent(NULL,FALSE,FALSE,NULL);

第六步,初始化中斷,如果CAN卡有復位請求就退出初始化程序。設置好中斷后啟動數據接收線程,設置線程優先級繼續線程處理;最后配置CAN卡參數,進入正常運行狀態。

2.3 CAN卡信息發送

CAN卡的信息發送分為兩個步驟。在對CAN卡基本信息進行檢查后,首先設置發送緩沖的ID號。CAN標準模式的ID號為11位,偏移地址10中存放的是ID號的高8位,偏移地址11的高3位存放的是ID號的低3位,剩下5位分別是RTR位(遠程傳送請求位)和數據長度。通過CANW函數將處理后的數據寫入到相應的偏移地址,設置完相應的地址數據后,通過循環將偏移地址12~19的數據采集回來存到數組中。然后,設置CAN卡的傳輸請求為允許并不斷偵測狀態寄存器的變化,當傳輸緩沖滿標志或傳輸結束標志為1時通出程序,完成一次數據采集。傳輸緩沖區的寄存器如表1所列。

表1

ID號10ID.10ID.9ID.8ID.7ID.6ID.5ID.4ID.3RTR,數據長度碼11ID.2ID.1ID.0RTRDLC.3DLC.2DLC.1DLC.0數據1~812~19數據數據數據數據數據數據數據數據表2

ID號20ID.10ID.9ID.8ID.7ID.6ID.5ID.4ID.3RTR,數據長度碼21ID.2ID.1ID.0RTRDLC.3DLC.2DLC.1DLC.0數據1~822~29數據數據數據數據數據數據數據數據CAN消息發送函數的實現如下:

BOOL CAN_SendMessage(LPCAN_HW_OPEN_INFO hCan,LPCanCardMessageBuflpMsg)

{

BOOL bSuc=FALSE;

ASSERT(hCan && lpMsg && lpMsg->dwMessageLen <=8); /*防錯處理*/

if(0= =(hCan->dwAccessCode & GENERIC_WRITE))

return FALSE;

:: EnterCriticalSection(&hCan->lpCanHWInfo->

TransmitCritSec); /*進入臨界區*/

BYTE byV=static_cast<BYTE>(1pMsg->dwMsgID>>3);

CANW(hCan,10,byV); /*設置ID值高8位*/

byV=static_cast<BYTE>=((lpMsg->dwMsgID & 7)<<5);

if(lpMsg->bRTR) byV|=0x10;

byV+=static_cast<BYTE>(lpMsg->dwMessageLen);

CANW(hCan,11,byV);/*設置ID值低3位、RTR及數據長度*/

for(UINT i=0;<lpMsg->dwMessageLen;++i)

{

CANW(hCan,12+i,lpMsg->byMsg[i]);

} /*采集數據*/

CANW(hCan,1,1);/*重置傳輸請求*/

while(TRUE)

{byV=CANR(hCan,2);

if(byV & 0X40) /*傳輸緩沖區滿,退出*/

{break;}

if(byV & 0X8){ /*傳輸結束,正確返回退出*/

bSuc = TRUE;

break;}

}

::LeaveCriticalSection(&hCan->lpCanHWInfo->TransmitCritSec); /*離開臨界區*/

return bSuc;

}

2.4 CAN卡信息接收

CAN卡的信息接收是發送的逆過程,當接收緩沖區標志為1時,表示緩沖區已滿可以接收數據,將數據接收到數組后釋放接收緩沖區,然后對接收到的數據進行分解并存儲到CAN卡信息緩沖區的結構體。接收緩沖區的寄存器結構如表2所列。

CAN消息接收函數的實現如下:

BOOL CAN_RecvRecvMessage(LPCAN_HW_OPEN_INFO

HCan,OUT LPCanCardMessageBuflpMsg)

{……

if(CANR(hCan,2)&1){ /*判斷接收緩沖區是否已滿*/

for(UINT i=0;i<10;++i)

recvBuf[i]=CANR(hCan,20+i);/*將數據暫存到臨時緩沖區*/

CANW(hCan,1,4); /*釋放接收緩沖區*/

LpMsg->dwMsgID=recvBuf[0]<<3; /*取出ID的高8位*/

BYTE byV =recvBuf[1];

LpMsg->dwMsgID+=byV >>5;/*取出ID低3位,然后和高8位合并*/

LpMsg->bRTR =byV &0x10?TRUE:/*返回RTR狀態*/

LpMsg->dwMessageLen = byV &0XF; /*返回數據長度*/

……

}

else

{++hCan->lpCanHWInfo->dwErrorMsgCount;}/*沒有收到數據,錯誤計數加1*/

::LeaveCriticalSection(&hCan->lpCanHWInfo->

ReceiveCritSec); /*離開臨界區*/

Return bSuc;

}

2.5 CAN卡事件處理

CAN卡事件處理函數是CAN卡驅動程序中很重要的部分。驅動設計要求具有消息通知的功能,當事件發生時及時捕獲事件并進行消息處理。

下面是事件處理函數的實現:

staric DWORD WINAPI CAN_EventHanle(LPVOID lpParam)

{

ASSERT(lpParam);

LPCAN_HW_OPEN_INFO hCan=(LPCAN_HW_OPEN_INFO)lpParam;

CanCardMessageBuf bufMsg;

while(TEUE)

{ /*循環等待CAN卡消息產生,然后進行處理*/

::WaitForSingleObject(hCan->lpCanHWInfo->hCanEvent,0XFFFFFFFF);

if(hCan->lpCanHWInfo->bKillCanThread) break; /*若CAN線程已關閉則中斷*/

if(CAN_RecvMessage(hCan,&hufMsg)){ /*正確接收數據后*/

CAN_RecvBufPush(hCan,&bufMsg);} /*將數據壓入緩沖*/

BYTE byV=CANR(hCan,3); /*將3號寄存器讀出然后立即寫入*/

CANW(hCan,3,byV);/*能夠獲取每次中斷*/

InterruptDone(hCan->lpCanHWInfo->lpCanObj->dwSysIrqt);

} /*本次中斷結束,等待下次中斷*/

return 0;

}

2.6 其它函數

為了提供更多的功能和更方便地使用CAN卡進行通信,在CAN卡驅動程序中還設計了一些函數如CAN_Config用CAN卡信息配置、CAN_RecvBufPop用于處理接收緩沖區、CAN_Reset用于復位CAN卡、CheckHWInfo用于硬件信息檢查等。這些函數提供了對CAN通信卡的設置、檢查等功能,在這里不再詳述了。

3 CAN卡驅動封裝設計

CAN卡底層驅動函數雖然功能完整,但是對于用戶使用比較復雜并且一般用戶不需要了解底層實現的機制。為了便于使用,最后對CAN卡的驅動進行了封裝,提供CanOpenFile、CanSendMsg等五個函數用于CAN總線的通信,以動態連接庫(DLL)的形式提供給用戶調用。封裝函數及功能如下:

*CanOpenFile;初始化并打開CAN卡的一個端口。

*CanCloseFile;關閉由CanOpenFile打開的CAN卡端口。

*CanRecvMsg;接收CAN卡數據,打開CAN卡時必須具有GENERIC_READ權限。

*CanSendMsg;通過CAN卡發送數據。打開CAN卡時必須具有GENERIC_WRITE權限。

*CanIOControl;設置或獲取CAN卡I/O參數支持的I/O控制包括:IOCTL_CAN_CONFIG,IOCTL_CAN_RESET,IOCTL_CAN_TIMEOUT,IOCTL_CAN_SENDREADY,IOCTL_CAN_RECVREADY。

下面是CanSendMsg函數實現的代碼:

BOOL CanSendMSg(

HANDLE hCan,

LPCanCardMessageBuflpMsg)

{

if(!hCan||INVALID_HANDLE_VALUE= =hCan||

!lpMsg||lpMsg->dwMessageLen>8)return FALSE;

return CAN_SendMessage(LPCAN_HW_OPEN_INFO)

hCan,lpMsg);

該函數就是通過封裝CAN卡的底層驅動函數SendMessage來實現的,這樣將功能集中的五個函數更方便了用戶使用。

結語

篇7

通信卡的硬件設計

1 通信卡的主要特點

通信卡的硬件設計目的是智能化通信:在卡上具有4個DMA通道及相應的數據緩沖存儲區。在數據的接收過程中,通信卡會自動接收幀數據,判別幀長度,在幀尾將接收到的幀數據提交系統。在發送數據過程中,系統只須把發送的數據提交給本卡,具體的發送過程由該卡自行完成,不因多路通信而使主機增加開銷。該卡有內/外時鐘兩種工作方式,近距離可省去調制解調器,波特率為600b/s-64Kb/s,提供2路符合RS-232/CCITT V.24和RS-422A標準的接口信號。

2 通信卡的電路設計

通信卡組成框圖如圖1所示。其主要由DMA控制器、總線競爭仲裁器、串行通信控制器、數據緩沖存儲器SRAM、存儲器I/O映像和物理地址產生器、總線接口及防護、波特率產生器、接口電路等單元電路組成。

DMA控制器作為通信卡的主設備,控制卡上的數據接收和發送(來自通信控制器和CPU),并負責仲裁優先權。由于在進行數據通信時,允許主機CPU訪問本卡SRAM,且主機對其中某一路發控制命令時,不影響其余三路通信,這樣將會使主機CPU與本卡DMA競爭本卡總線控制權。而總線上沒有給出主機CPU指令排隊狀態序列,故不能直接設計多主競爭,因而在本卡總線上用門陣列設計了一個狀態機,不斷地監視總線爭用情況,完成本卡總線競爭、仲裁功能。完成HDLC規程的串行通信的器件是INTEL 8274多規程串行控制器,它能完成2個獨立的串行接收/發送全雙工通信。為了使4個信道在一幀數據的發送或接收過程中,主機不干預,故將發送的一幀數據在發送開始前由CPU用批命令放入卡上的SRAM中,同樣,在接收過程中,卡上DMA將接收到的數據放入SRAM中,等一幀接收完成后,再用批命令取出,放入系統存儲器中??ㄉ蟂RAM不占用主機內存地址,采用I/O映像,該適配器插入主機之后,主機通過系統I/O地址對其訪問,這由地址產生器完成。總線接口包括數據收發器,數據開關電路,讀、寫及中斷等控制電路,地址譯碼等。波特率產生器提供了一個可編程的時鐘信號發生器,用戶可自行設置通信速率,供工作于內時鐘方式時使用。接口電路提供符合RS-232/C CITT 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模型

通信卡的驅動程序是利用Windows XP的DDK軟件開發的標準的核心態設備驅動程序。它使用統一的“文件”形式,用戶可以通過代表通信卡設備的文件名,在WIN32子系統中用文件操作函數來訪問。該設備驅動和程序可以根據用戶的需要,設置為自動加載,或手動加載,也可以動態的加載該驅動程序。通信卡的驅動程序設計成為支持同步I/O模型,也可以為異步I/O模型。

2 發送數據I/O例程設計

在用戶態提交發送任務到核心態,由I/O管理程序負責調用驅動程序,驅動程序發送IRP交給硬件,假若當前發送器不忙,則具體的發送操作全部由發送器自行完成,而驅動程序則返回已經一個本幀可以發送的標志。具體的發送完成結果則可以在發送任務完成后查詢得到。可是,如果程序向當前設備發送器提交發送任務時,該發送器正在處理上一幀,那么則有兩種方法處理。

①立即方式:立即返回一個錯誤,當前設備忙,不能發送。

②阻塞方式:I/O管理器程序會調度相應的異步處理例程,將當前的發送任務放進任務隊列中,返回一個標志:I/O掛起,當前設備忙,發送任務提交任務隊列。驅動程序會在發送器空閑時,提交任務隊列中的發送任務給發送器。完成發送任務后,將相關文件句柄設為有信號狀態,通知本次發送任務完成。

3 接收數據I/O例程

接收數據例程采用客戶/服務器的模式設計。由于用戶的接收請求和硬件的接收并不是同步的,所以在設計中,為避免丟失數據,考慮創造一個專門的接收線程。這樣,同步用戶請求、接收線程、硬件層之間的通信就必須仔細地設計。圖2示意了用戶態接收請求、接收線程以及硬件層之間的通信同步。

①硬件層與接收線程之間通信

硬件層與接收線程之間通信的同步是通過同步事件對象來實現的。同步事件對象通常處于無信號狀態,只有當成功地接收到一幀時,才將該事件置為有信號狀態。接收線長久等待同步事件對象,在沒有收到數據時,因同步事件對象處于無信號狀態而阻塞。當硬件檢測到數據時,實時中斷服務程序負責將同步事件對象置為有信號狀態,接收線程就會釋放阻塞。將通信卡SRAM上的接收數據讀進接收線程緩沖區隊列,然后將同步事件對象置為無信號狀態,接收線程再次阻塞,等待接收下一幀數據。

②用戶層和接收線程之間的通信

當用戶提交接收任務時,由驅動程序的調度程序讀取接收線程的緩沖區隊列,并將標志置為“空”,同時將緩沖隊列事件置為無信號狀態,并返回,如果緩沖區是空,則

?立即方式:立即返回無數據。

?阻塞方式:阻塞直到有數據隊列進入。接收隊列的每個緩沖區都對應一個通知事件,如果接收線程將SRAM中的數據讀進隊列,就將相應的通知事件置為有信號狀態,用戶請求就等待該通知事件,只要有數據在隊列中,就讀取返回,否則被阻塞。

4 硬中斷服務程序設計

通信卡在全雙工的通信中具有實時性,而且在較高的波特率,硬中斷非常多。為了防止高優先級中斷過多地搶占CPU時間,設計中采用了實時中斷服務程序和延遲過程調用的方法。

在Windows XP系統中,每個內核函數和過程都運行于特定的優先級。較高優先級的函數或事件可以搶占較低優先級,反之則不然。實時中斷服務程序ISR運行于DIRQL級,具有較高的優先級,它只能被更高級的硬中斷所搶占,不會對同級或較低優先級的硬中斷的響應。所以,在實時中斷服務程序中,只做盡量少的必須工作,即讀出中斷向量,而將大量的數據傳送及處理等工作交給延遲過程DPC去完成。因為DPC過程運行于DISPATCH_LEVEL級,是相對較低的優先級,它可以被任何級的硬中斷所搶占。這樣,既保證了硬中斷的及時響應,又提高了程序的性能。

5 驅動程序人口例程

Windows XP為每個核心態的驅動程序提供了一個默認的標準入口點DriverEntry()。設計中,考慮到該例程運行于PASSIVE_LEVE級,系統只運行該例程一次就拋棄了,所以在驅動程序中用到的重要數據、對象等都不能保存在DriverEntry()例程中,必須在初始化過程中分配一塊NoPaged內存來保存。通信卡的驅動程序的DriverEntry()例程主要完成如下功能。

讀取Registry的硬件配置信息,聲明I/O地址、中斷等資源;創建代表通信卡的設備名MPSC,該名字對WIN32子系統是可見的;設置調度例程入口點;分配一塊NoPaged的內存,存儲重要信息;連接硬中斷,設置中斷服務程序,初始化線程、事件、信號燈、DPC等內核對象,返回狀態STATUS_SUCCESS。

如果在以上過程中遇到錯誤,則需要做以下工作:斷開硬中斷;釋放硬件資源;將相關的錯誤信息打包,并記錄;返回錯誤信息。

6 設計驅動程序中需要注意的問題

由于通信卡在應用中具有一定的實時性,為了克服中斷的不確定性。提高系統的性能,開發了Windows XP系統所有驅動程序中最難的異步驅動程序。在系統的內核開發,異步模型I/O操作中,內核對象的同步十分復雜,細微的差錯都會導致系統徹底崩潰。在設計驅動程序中需要注意以下問題。

?在程序中用到的內核對象:事件、信號燈、線程以及連鎖等,都必須將其存儲在Nopaged內存中,否則,會造成系統崩潰。

篇8

關鍵詞:嵌入式系統;linux;驅動程序

引言

Linux是一個遵循POSIX標準的免費操作系統。具有BSD和SYSV的擴展特性。與其他操作系統相比,嵌入式Linux系統以其可應用于多種硬件平臺、內核高效穩定、源碼開放、軟件豐富、網絡通信和文件管理機制完善等優良特性而正被作為研究熱點,越來越多的研究人員采用Linux平臺來開發自己的產品。Linux設備驅動程序在Linux內核源代碼中占有很大比例,從2.0、2.2到2.4版本的內核,源代碼的長度日益增加,其實主要是設備驅動程序在增加。

設備驅動程序的編寫

設備驅動程序是linux內核的一部分,是操作系統內核和機器硬件之間的接口,它由一組函數和一些私有數據組成,是連接應用程序與具體硬件的橋梁。Linux的一個基本特點是它對硬件設備的管理抽象化,系統中的每一個設備都用一個特殊的文件來表示。所有的硬件設備都像普通的文件一樣看待,使用與操作系統相同的標準系統來進行打開、讀寫和關閉。

在Linux操作系統下有3類主要的設備文件類型:塊設備、字符設備、網絡設備。字符設備是指存取時沒有緩存的設備??上裎募粯釉L問字符設備,字符設備驅動程序負責實現這些行為。系統的控制臺和并口就是字符設備的例子,它們可以很好地用“流”來描述。塊設備是文件系統的宿主,如磁盤。Linux允許像字符設備那樣讀取塊設備――允許一次傳輸任意數目的字節。結果是,字符設備和塊設備讀取數方式一致。而網絡設備不同于字符設備和塊設備,它面向的上一層不是文件系統而是網絡協議層,是通過BSD套接口訪問數據。與設備相對應的是三類設備驅動程序,字符設備驅動程序、塊設備驅動程序、網絡設備驅動程序。

字符設備驅動程序、塊設備驅動程序與網絡設備驅動程序的結構體是不同的。

在linux源代碼linux/include/linux/fs.h中定義了字符設備和塊設備驅動程序中必須使用的file_operations結構,每個設備驅動都實現這個接口所定義的部分或全部函數。隨著內核的不斷升級,file_operations結構也越來越大,不同的版本的內核會稍有不同。

應用程序只有通過對設備文件的open、release、read、write、ioctl等才能訪問字符設備和塊設備。用戶自己定義好file_operations結構后,編寫出設備實際所需要的各操作函數,對于不需要的操作函數用NULL初始化,這些操作函數將被注冊到內核,當應用程序對設備相應的設備文件進行文件操作時,內核會找到相應的操作函數,并進行調用。如果操作函數使用NULL,操作函數就進行默認處理。

對于字符設備而言,llseek(),read(),write(),ioctl(),open(),release()這些函數是不可缺的;對十塊設備,open(),release(),ioctl(),check_media_change(),revalidate()是不可缺少的。

網絡設備結構體net_device定義在include\linuxhletdevice.h里,如下所示:

定義好net_device結構體后,根據實際情況編寫操作函數,其中hard_start_xmit()函數是用來發送數據的,set mac address()是進行網絡參數設置的。

當linux初始化時將調用初始化函數intdevice_init(),該函數包括以下內容:

注冊所用設備。linux用設備號來標識字符設備和塊設備。設備號分為主設備號和從設備號,最終形成設備接點。設備節點在訪問字符設備和塊設備的設備驅動程序時將使用。通常主設備號標識設備對應的驅動程序,大多數設備是“一個主設備號對應一個驅動程序”,如:虛擬控制臺和串口終端由驅動程序4管理。次設備號由內核使用,用于確定設備文件所指的設備。字符設備和塊設備注冊時必須先定義好設備號。

字符設備注冊函數如下:

int register_chrdev(unsigned int major,constchar*name,struct file_oprations*fops);其中major是主設備號。

由于對網絡設備驅動程序的訪問不需要設備節點,它的注冊函數如下:

int register_netdev(struct net_device*dev)

注冊設備所用的中斷。中斷在現代計算機結構中有重要的地位,操作系統必須提供程序響應中斷的能力。一般是把一個中斷處理程序注冊到系統中去。操作系統在硬件中斷發生后調用驅動程序的處理程序。

注冊中斷所用的函數如下:其中,irq是中斷向量;handler是中斷處理函數;flags是中斷處理中的掩碼;devices是設備名;dev_id是在中斷共享使用的id。

當linux不使用該設備時,就要調用清除函

編寫服務子程序

服務于I/O請求的子程序,又稱為驅動程序的上半部分。調用這部分是由于系統調用的結果。這部分程序在執行的時候,系統仍認為是和進行調用的進程屬于同一個進程,只是用戶態變成了核心態,具有進行此系統調用的用戶程序的運行環境,因此可以在其中調用sleep等與進程運行環境有關的函數。

中斷服務子程序,又稱為驅動程序的下半部分。在Linux系統中,并不是直接從中斷向量表中調用設備驅動程序的中斷服務子程序,而是由Linux系統來接收硬件中斷,再由系統調用中斷服務子程序。中斷可以產生在任何一個進程運行的時候,因此在中斷服務程序被調用的時候,不能依賴于任何進程的狀態,也就不能調用任何與進程運行環境相關的函數。因為設備驅動程序一般支持同一類型的若干設備,所以一般在系統調用中斷服務程序的時候,都帶有一個或多個參數,以唯一標識請求服務的設備。

設備驅動程序的使用

直接將驅動程序編譯進linux內核

將設備驅動程序復制到linux/drivers相關的子目錄下,比如字符設備驅動程序就放在linux/drivers/char下。

修改linux/drivers相關的子目錄的Makefile,

如obj-$(config_dev_driver)+=dev_driver.o,這樣在編譯內核時將會編譯dev_driver.c,生成dev_driver.o.

對內核進行重新編譯時,進行相關的配置,比如要使用AT91RM9200的UART,就要如下配置:

Character devices->Serial drivers.>AT91RM9200 serial port suppot

將驅動程序編譯成驅動模塊

在設備驅動程序中要有兩個重要函數:

module_init(dev-init),module_exit(dev_exit)

利用相應的交叉編譯器以及編譯命令將驅動程序dev_driver.c編譯成dev_driver.o這樣的動態驅動模塊。利用insmod命令給系統安裝驅動模塊,如果在/dev目錄下沒有相應的設備文件,就可以使用mknod創建一個設備文件。利用rmmod命令卸載驅動模塊,設備文件的刪除可以用rm命令。

篇9

A/D轉換是單片機數據采集系統的重要組成部分,實時內核下A/D驅動程序的實現過程主取決于A/D轉換器的轉換時間。本文首先比較和分析μC/OS-II下A/D采樣數據的三種方法;其次介紹C8051F015單片機A/D模數轉換器配置及特點;最后,在μC/OS-II內核移植到8位單片機C8051F015的基礎上,介紹編寫A/D驅動程序的一般思想和方法。

1 μC/OS-II實時內核下的A/D讀方法

實時內核下,驅動程序采用什么方法讀取A/D采樣數據是首先考慮的問題。許多因素將影響讀取A/D,如A/D的轉換時間、模擬值的轉換頻率、輸入通道數等,但最主要的取決于A/D的轉換時間。典型的A/D轉換典型的A/D轉換電路由模擬多路復用器(MUX)、放大器和模數轉換器(ADC)三部分組成。下面描述讀取A/D的三種方法。

    圖1所示的是第1種讀取方法。假設A/D轉換器的轉換時間較慢(5ms以上)。應用程序調用圖1所示的驅動程序,并傳遞要讀取的通道。驅動程序通過MUX選擇要讀取的模擬通道(①)開始讀。有,延時幾μs以便使信號通過MUX傳遞,并之穩定下來。接著,ADC被觸發開始轉換(②)。然后驅動程序延時一段時間以完成轉換(③_。延時時間必須比ADC轉換時間長。最后驅動程序讀取ADC轉換結果(④)。并將轉換結果返回到應用程序(⑤)。

圖2所示的是第2種讀取方法。當模擬轉換完成后,ADC產生的個中斷信號。若ADC轉換完成,ISR給信號量發一個信號(⑤),通知驅動程序,ADC已經完成轉換。如果ADC在規定的時限內沒有完成轉換。信號量超過(③),則驅動程序不再等待下去。驅動程序和中斷服務子程序(ISR)的偽代碼如下:

ADRd(ChannelNumber)

{

選擇要讀取的模擬輸入通道;

等待AMUX輸出穩定;

啟動ADC轉換;

等待來自ADC轉換結束中斷產生的信號量;

if(超時){

*eer=信號錯誤;

return;

}else{

讀取ADC轉換結果并將其返回到應用程序;

}

}

    ADCoversion Complete ISR {

保存全部CPU寄存器; /*將CPU的PSW、ACC、B、DPL、DPH及Rn入棧*/

通知內核進入ISR(調用OSIntEnter()或OSIntNesting直接加1);

發送ADC轉換完成信號; /*利用μC/OS-II內核的OSSemPost()*/

通知內核退出ISR(調用OSIntExit());

恢復所有CPU寄存器;/*將CPU的PSW、ACC、B、DPL、DPH及Rn出棧*/

執行中斷返回指令(即RETI);

}

在這種方法里,要求ISR執行時間與調用等待信號的時間之和為A/D轉換時間。

如果A/D轉換時間小于處理中斷時間與等待信號所需的時間之和,則可以用第三種方法。如圖3所示,前兩步(①②同以上兩種方法)結束后,驅動程序接著在一個軟件循環中等待(③)ADC直到完成轉換。在循環等待時,驅動程序檢測ADC的狀態(BUSY)信號。如果等待時間超過設定的定時值(軟件定時),則結束等待循環(循環等超時)。如果在循環等待中,檢測到ADC發出轉換結束的信號(BUSY)時,驅動程序讀取ADC轉換結果(④)并將結果返回到應用程序(⑤)。驅動程序偽代碼如下:

ADRd(ChannelNumber){

選擇要讀取的模擬輸入通道;

等待AMUX輸出穩定;

啟動ADC轉換;

啟動超時定時器;

while(ADC Busy & Counter 0);/*循環檢測*/

if(Counter==0){

*err=信號錯誤;

return;

}else{

讀取ADC轉換結果并將其返回到應用程序;

}

}

A、D轉換速度快,這種驅動程序的實現是最好的。

2 C8051F015單片機的A/D轉換器

2.1 C8051C015單片機

C8051C015的美國Cygnal公司新推出的高速SOC型C8051Fxxx系列單片機。它的內核CIP-51與MCS-51的指令集完全兼容,CIP-51的系統時鐘頻率在0~25MHz。C8051Fxxx系列單片機采用流水線結構,與標準的8051相比,指令執行速度有很大的提高。CIP-51內核的指令執行時間是以系統時鐘為單位,70%的指令執行時間為1個或2個系統時鐘周期。C8051F015具有32KB的內存、2304B的RAM(片內256B、片外2048B)。CIP-51內核具有標準8052的所有外設部件,片上還集成有9通道10位A/D轉換接口電路、SMBus/I2C、SPI串行接口。

2.2 C8051F015的A/D轉換電路

C8051F015的A/D轉換電路包括1個9通道可配置模擬多路開關AMUX(8路用于外部模擬輸入、1路用于芯片環境溫度的測量)、1個可編程增益放大器PGA和1個100ksps 10位分辨率的逐次逼近型ADC。A/D中還集成了跟蹤保持電路和可編程窗口檢測器。

ADC有4種啟動方式:軟件命令、定時器2溢出、定時器3溢出及外部信號輸入。寄存器ADC0CN是配置啟動和跟蹤方式的控制寄存器。每次轉換結束時,ADC0CH的ADBUSY(忙標志)的下降沿觸發中斷,也可用軟件查詢這個狀態位。

2.3 ADC轉換速度

C8051Fxxx系列單片機中ADC的速率都是可編程設置的。表1給出了所需最小分頻系數與SYSCLK(系統時鐘)的關系(ADC0CF為ADC配置寄存器)。

表1 ADC時鐘分頻系數與SYSCLK頻率的關系

SYSCLK頻率/MHzADC時鐘分頻系數ADC0CF的ADCSC2~1時鐘頻率<2.510002.5~520015~10401010~208(復位值)011時鐘頻率>20161xx在C8051F015單片機中,ADC的轉換時鐘周期至少在400ns,轉換時鐘應不大于2MHz。一般在啟動ADC之前都要處于跟蹤方式,而ADC一次轉換完成要用16個系統時鐘。另外,在轉換之前還要加上3個系統時鐘的跟蹤/保持捕獲時間,所以完成一次轉換需19個ADC轉換時鐘(9.5μs)。

圖1中的方法簡單,轉換時間在ms級以上,一般用于變化慢的模擬輸入信號,不適用于C8051F015。圖2中的方法,為了減少μC/OS-II內核調用ISR所用時間,ISR一般都用于匯編語言編寫。從程序1中ISR偽代碼可以看出,盡管ISR用匯編語言編寫。代碼效率高,但μC/OS-II調用ISR的時間與調用等待信號時間之和大于A/D的轉換時間,所以CPU用于ISR和循環檢測的開銷大。

圖3所示的方法顯然適合于C8051F015單片機,其優點是:可以獲得快速的轉換時間;不需要增加一個復雜的ISR;轉換時信號改變時間更短;CPU的開銷小;循環檢測程序可被中斷,為中斷信號服務。

圖4 A/D驅動程序模塊流程圖

3 A/D驅動程序的編寫

外設驅動程序是實時內核和硬件之間的接口,是連接底層硬件和內核的紐帶。編寫驅動程序模塊應滿足以下主要功能:①對設備初始化;②把數據從內核傳送到硬件從硬件讀取數據;③讀取應用程序傳送給設備的數據和回送應用程序請求的數據;④監測和處理設備出現的異常。

A/D轉換電路作為一個模擬輸入模塊,μC/OS-II內核應把它作為一個獨立的任務(以下稱為ADTask())來調用。A/D驅動程序模塊流程如圖4所示。ADInit()初始化所有的模擬輸入通道、硬件ADC以及應用程序調用A/D模塊的參量,并且ADInit()創建任務ADTask()。ADTb1[]是一個模擬輸入通道信息、ADC硬件狀態等參數配置以及轉換結果存儲表。ADUpdate()負責讀取所有模擬輸入通道,訪問ADRd()并傳遞給它一個通道數。ADRd()負責通過多路復用器選擇合適的模擬輸入,啟動并等待ADC轉換,以及返回ADC轉換結果到ADUpdate()。

在μC/OS-II這時內核下各原型函數、數據結構和常量的定義如下:

INT16S ADRd(INT8U ch);

/*定義如何讀取A/D,A/D必須通過AIRd()來驅動*/

void ADUpdate(void);

/*一定時間內更新輸入通道*/

void ADInit(void);

/*A/D模塊初始化代碼,包括初始化所有內部變量(通過ADInit()初始化ADTb[]),初始化硬件A/D(通過ADInitI())及創建任務ADTask()*/

void ADTask (void data);

/*由ADInit()創建,負責更新輸入通道(調用ADUpdate ())*/

void ADInitI (void);

/*初始化硬件A/D*/

AD_TaskPrio:設置任務ADTask()的優先級。

AD_TaskStkSize:設置分配給任務ADTask()的堆棧大小。

AD_MaxNummber:AMUX的輸入通道數。

AD_TaskDly:設定更新通道的間隔時間。

AD ADTbl[AD_MaxNummber]:AD類型的數組(AD是定義的數據結構)。

4 結論

對于A/D轉換器接口電路驅動程序的編寫歸納出以下幾點:

①在決定采用具體的驅動方案之前,分析接口電路的特點,尤其是了解A/D的轉換速度;

②對于轉換速度快的A/D轉換器,可能出現CPU的處理速度與A/D轉換速度不匹配,一般的A/D中不帶有FIFO緩沖區,須有內存中開辟緩沖區;

篇10

第一節windows nt網絡結構

§1.1.1 windows nt網絡體系結構

windows nt的網絡體系結構是基于國際標準化(iso)制定的標準模型──開放式系統互連(open system interconnection:osi)參考模型分層建立的,這種方式有利于隨時擴展其它功能和服務。

windows nt網絡模型開始于mac子層,網卡驅動程序就駐留在其中。它通過相關的網卡把windows nt與網絡連接起來,圖中的多個網卡表明在一臺運行windows nt的計算機上能使用多種網卡。

這一網絡體系結構包括兩個重要接口──ndis接口與傳輸驅動

程序接口(tdi)。這兩個接口把兩個層隔離開來,辦法是相鄰的部件只允許按單一的標準來寫,不允許多重標準。例如一個網卡驅動程序(在ndis接口的下面)就不需要特地按每個傳輸協議來寫它的代碼塊,恰恰相反,該驅動程序是寫給ndis接口的,它通過符合ndis的相應傳輸協議來請求服務。這些接口包含在windows nt的網絡體系結構中,以容納可移植、可互換的模塊。

在兩個接口之間,是傳輸協議。它在網絡中起著組織者的作用。一個傳輸協議規定了數據以何種方式呈遞給下一個接收層,以及如何對數據相應地進行打包。它通過ndis把數據傳給網卡驅動程序,并通過tdi把數據傳給轉發程序(redirector)

tdi之上是轉發程序,它把本地的網絡資源申請轉送給網絡。

為了能和其他廠商的網絡互連,windows nt允許有多個轉發程序。對于每一個轉發程序windows nt計算機必須也有一個相應的供應者(provider)(由網絡廠商提供)。多供應者路由選擇程序決定適當的供應者,然后借助于供應者,對應用請求到相應的轉發程序做出選擇。windows nt支持兩種類型的網絡驅動程序

傳輸驅動程序

實現數據鏈路層中的邏輯鏈路控制子層協議和傳輸層協議。向 下與ndis接口,向上與tdi接口。

網卡驅動程序

實現對物理層的管理和數據鏈路層中介質訪問控制子層協議,通過ndis向下管理物理網卡,向上與傳輸驅動程序通信。

§1.1.3 windows nt網卡驅動程序

windows nt環境下的網卡驅動程序也分為兩種:

miniport網卡驅動程序:miniport驅動程序只須實現與網絡硬件相關的操作(包括發送和接收)。而所有底層網卡驅動程序的通用操作(如同步),一般由ndis接口程序來實現。

full網卡驅動程序:full網卡驅動程序必須實現所有硬件相關和同步、排隊等操作。例如full網卡驅動程序為了響應數據接收,需要保持本身的捆綁信息,而miniport就可以由ndis接口庫來實現。

在windows nt的早期版本中,full網卡驅動程序要求開發者實現許多底層操作,來處理多處理器的核心問題以及處理器、線程的同步,這樣不同的開發者在大量重復著許多相同的工作。

而miniport網卡驅動程序允許開發者僅僅寫一些與網絡硬件相關的代碼即可,而那些通用的函數由ndis接口庫來實現,這樣開發出來的驅動程序減少了不必要的工作。

第二節miniport驅動程序的結構

ndis接口規范了網卡驅動程序的實現,同時也對tdi驅動程序的實現提出了一定的要求,在nt中,ndis約束下的網卡驅動程序、tdi驅動程序和系統的關系如下圖所示:

圖2.0 ndis約束下的網卡驅動程序、tdi驅動程序和系統的關系

miniport驅動程序包括驅動程序對象、驅動程序源代碼和ndis接口庫代碼。windows nt ddk提供ndis.h作為miniport驅動程序的主要頭文件,定義了miniport驅動程序的入口點、ndis接口庫函數和通用數據結構。

上邊緣函數的作用是網卡驅動與ndis接口庫進行通信,而下邊緣函數是tdi協議驅動程序與ndis通信的手段。ndis用一個叫做邏輯網卡的軟件對象來描述系統中的每塊網卡,而邏輯網卡與windows nt設備對象的通信由i/o子系統來管理,描述網卡的設備對象包括相關的網絡信息如名字、網絡地址和網卡內存基地址等,它還包含與硬件相關的驅動程序狀態數據(捆綁數目,捆綁句柄,包過濾數據庫等)。ndis分配一個句柄到miniportinitialize這個上邊緣函數的一個結構中,然后miniport網卡驅動程序將在以后提供這個句柄來給ndis調用,這個結構一直被ndis保持,并且對miniport驅動程序不透明。 當miniport網卡驅動程序初始化一塊網卡時,它創立自己的內部數據結構來描述網卡,記錄需要它管理的與設備相關的狀態信息。當miniport網卡驅動程序調用ndismsetatttibutes或ndismsetattributesex兩ndis庫函數時,它傳遞一個句柄給這數據結構。這樣,當調用miniport驅動程序入口點時,它就傳遞這個句柄來驗證驅動程序所對應的網卡的正確性。這個數據結構為miniport網卡驅動程序所擁有并維護。miniport nic驅動程序還需要維護一組對象,這些對象是系統定義的對象標識符(object idetifier:oid)來標識,以描述驅動程序的性能和當前狀態信息。為查詢這些信息,上層驅動程序調用ndisrequest向ndis接口庫指示oid。oid表示了調用所需的信息類型,如miniport驅動程序所支持的lookahead緩沖區大小等。ndis接到上層驅動程序的查詢請求,將oid傳遞給上邊緣函數miniportqueryinformation實現對oid的查詢,如果上層驅動程序請求改變狀態信息則調用miniportsetinformation實現對oid的設置。典型的miniport nic驅動程序必須有一些函數來通過ndis接口實現上層驅動程序與硬件的通信。這些函數稱為上邊緣服務函數。

這些上邊緣服務函數由驅動程序的開發者根據驅動程序面向的特定低層網絡類型和硬件以及相應環境,可以有選擇地實現,但必須保證驅動程序最基本的功能,這些基本功能包括初始化、發送、中斷處理、重置、參數查詢與設置和報文接收。

miniportinitialize:操作系統根據系統配置信息,檢測出網卡已安裝時,由ndis接口在初始化時調用,主要完成低層網絡類型確定,對應于物理網卡的邏輯網卡初始化,中斷信息注冊,網卡與主機通訊方式的確認。i/o端口的申請與注冊,內存映像,mib的初始化,物理網卡的驗證與初始化等。

miniportreconfigure:支持網卡參數動態變化,和miniportinitilize一樣由ndis接口以初始化級別調度執行(不能屏蔽中斷,必須由驅動程序承認并清除在此期間產生的中斷),支持即插即用和軟配置的網卡在動態改變參數時,必須提供此函數。

miniportqueryinformation:查詢網卡的狀態以及網卡驅動程序的操作或統計參數,如是否支持組通訊、網卡的物理速率是否支持回環、是否支持直接拷貝等,這些參數以oid方式統一管理。

miniportsetinformation:ndis接口或協議驅動程序通過調用此接口改變驅動程序維護的oid庫,一些操作參數的改變也將同時改變驅動程序狀態,例如組地址的設置。

miniportreset:包括網卡硬件重置和驅動程序軟件重置,軟件重置包括驅動程序狀態重置,以及一些相關的參數重置,還需考慮有些參數的恢復,重置時不必完成所有正在活躍的外部請求,但必須釋放已占用的外部資源。

miniporthalt:掛起網卡并釋放該網卡驅動程序占用的所有資源,在此期間不屏蔽中斷。

miniportisr:高優先級的中斷處理程序,進行的工作包括初始中斷處理類型,決定是否進行中斷轉交,對卡上中斷進行處理 等,該服務類型只在以下情況被調用:

ndis接口調用miniportinitialize和miniporthalt兩函數時。

.中斷處理類型設為每此中斷處理過程都調用時。

為使系統能及時響應所有硬件中斷,高優先級的硬件中斷處理程序應盡可能的減少運行時間,防止長時間的屏蔽低優先級中斷,避免造程中斷丟失。

miniporthandleinterrupt:由中斷延時處理程序在中斷延時處理時進行調用。ndis排隊所有的延時處理,該服務主要處理發送完成、報文接收、描述符用盡、溢出、網卡異常等中斷。

miniportsend:ndis收到上層發送請求時經過若干協議處理再向下調用此服務過程,發送的packet已含有llc和mac頭,該服務過程進行邊界對齊、packet約束重整、描述符映射和報文發送、以及發送資源和packet緩沖隊列管理。

miniporttransferdata:多個已和網卡捆綁的協議驅動程序在接收到報文到達指示后,向網卡驅動程序發出傳送請求以拷貝各自所需的報文數據部分,網卡驅動程序根據各協議驅動程序對單個packet是否進行多次拷貝,以決定是否暫存只允許單次拷貝的packet等。

miniportcheckhandle:ndis每秒調用此服務函數一次,驅動程序發現網卡異常時報告給ndis由ndis調用miniportreset進行硬件重恢復。

miniportenableintrrupt:中斷使能。

miniportdisableinterrupt:中斷屏蔽。

另外,每個網卡驅動程序必須有一個初始化入口點,由driver entry函數實現,它和系統相關,由操作系統在裝入驅動程序時調用,主要完成初始化ndis wrapper,再由wrapper初始生成驅動程序管理塊并完成相應各種初始化工作,登錄網卡驅動程序所有上邊緣服務入口點,同時寫入ndis版本信息。ndis接口庫包括在ndis.sys中,它是一個核態函數庫,有一套抽象的函數,無論協議驅動程序還是nic驅動程序都連接到這個庫中,以實現上下層之間的操作。

第二章fddi網卡驅動程序的加載和運行

第一節 網卡驅動程序的安裝

windows nt網卡驅動程序安裝的目的是實現網卡相應硬件信息和驅動程序在windows nt注冊庫中的注冊,使windows nt能夠正確識別網卡,了解所必需的軟硬件信息并能在windows nt啟動時加載相應驅動程序。

網卡驅動程序安裝時,首先在主群組的控制面板中選擇“網絡”,然后添加網卡,指定相應信息文件──oemsetup.inf的路徑,以完成以下兩個必要的操作:

復制驅動程序到相應的系統目錄(windows nt根目錄system32drivers)中;

在windows nt注冊庫中存入相應軟硬件信息。

下面主要以fddi網卡為例介紹安裝驅動程序所必需的工作:

§2.1.1網卡一般硬件參數

對于fddi網卡,必須在編寫其oemsetup.inf文件時確定以下硬件參數:

總線類型:pci(5)……括號中的數字5表示pci總線在ndis中的總線類型代碼;

廠商代號:0x5588……系統加載時確定網卡的標記,也是編程時確定pci槽號的標識;

cfid: 0x01;

介質類型:光纖(3) ……括號中的數字表示光纖在ndis中的介質類型代碼;

是否支持全雙工:支持。

對于其它的硬件信息在此inf配置信息文件中可有可無,如若配置,則可在驅動程序的編寫時利用這些信息,方便編程,同時有利于其它應用對其參數的確定和使用。網卡驅動程序的安裝通常將創建登錄表中的四個不同子鍵:

software registrion鍵,對應于驅動程序,存在于hkey_local_machinesoftwarecompany productnameversion中。我們的fddi網卡驅動程序所對應的是hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;

網卡的軟件登錄鍵,存在于hkey_local_machinesoftwaremicrosoft windows ntnt3.51networkcardsyhfddi1;

驅動程序的服務登錄鍵,存在于hkey_local_machinesystemcurrentcontrolsetservices

網卡的服務登錄鍵,存在于hkey_local_machinesystemcurrentcontrolsetservices

對于每一個網絡部件,一個名為netrules的特殊子鍵在鄰近的驅動程序或網卡登錄子鍵里創建,netrules標識網絡部件為網絡整體的一部分。

fddi網卡驅動程序對應的標準軟件登錄表項將出現在以下路徑:

hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;

驅動程序對應的標準項的值為:

description =yhfddi/pci adapter controller

install date =……

……

refcount =0x01

servicename =yhfddi

softwaretype =driver

title =yhfddi/pci adapter controller

而且在yhfddi驅動程序相關的netrules子鍵下,這些值項為:

bindable =yhfddi driver yhfddi adapter non exclusiver

bindform =“yhfddisys”yes no container

class = reg_multi_sz “yhfddi driver basic”

infname =oemnad1.inf

type =yhfddisys ndisdriver yhfddidriver

use =driver

yhfddi網卡在如下路徑的networkcards子鍵里介紹:

hkey_local_machinesoftwaremicrosoft

windows ntnt3.51networkcardsyhfddi1;

網卡的標準項包括以下這些值:

description =yhfddi/pci adapter controller

install date =……

manufacturer =net612

productname =yhfddi

servicename =yhfddi01

title =[01]yhfddi/pci adapter controller

§2.1.3編寫inf信息配置文件

gui inf描述語言被windows nt用以書寫系統所有部件的配置文件,當然也可以用以書寫網絡系統各部件的配置文件,該配置文件描述了網絡部件安裝、配置、刪除的執行過程。當網絡部件進行初始安裝或二次安裝(通常通過ncpa進行)時,安裝程序讀取部件對應的配置文件,進行解釋執行。gui inf描述語言由節、命令、邏輯操作、變量規范、流程控制以及一套調用dll或外部程序的機制組成,其中,節是配置文件的主體,節可分為install節(類似于函數),shell節(也類似于函數,但可調用insall和shell節),detect節(不包含命令),一個配置文件一般由若干不同類型的節組成。驅動程序的開發者根據需要可以在配置文件中編寫相應代碼,使得用戶和系統之間能進行交互,并且由用戶決定一些配置參數。

nt網卡配置文件有其一套規范,驅動程序開發者必須按規范編寫配置文件,一般來說,一個配置文件至少應該提供下面三個節:

安裝入口點:[identify]shell節。該節主要功能是給出安裝部件的類型名,系統通過它識別該部件屬于哪一大類(display,mouse,scsi,network等)中的哪一類(網絡adapter,driver,transport,service,network和netprovidor),同時,還需要給出映像文件和配置文件所在的源介質及標識。

[returnoption]shell節。系統執行安裝identify節后,執行該節。它主要功能是檢查所需安裝的部件是否支持的硬件平臺和語言,并給出網卡名(有些配置文件支持多類網卡,此時必須讓用戶進行選擇,并獲得選擇結果)。

[installoption]shell節。該節是配置文件得主體,也是上次安裝完后再次進行配置、刪除、更新的入口點。主要功能是拷貝映像文件和配置文件,生成配置的各種選項,創建該部件在注冊庫中對應的各種登錄子樹并更新重寫。

第二節 驅動程序的加載過程

§2.2.1 windows nt的啟動過程