驅(qū)動程序范文

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

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

篇1

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

3、屬性中選“硬件”,

4、硬件里選“設(shè)備管理器”,

5、設(shè)備管理器中點開“端口”,

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

7、選“屬性”

8、屬性里選“驅(qū)動程序

9、驅(qū)動程序里選“驅(qū)動程序詳細(xì)信息”

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

篇2

這歸結(jié)于優(yōu)化的功效,很多玩家都可以有針對性地對游戲進行優(yōu)化設(shè)置,調(diào)整系統(tǒng)、優(yōu)化資源,同時對游戲進行設(shè)置上的更改,尋找最佳的平衡點。

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

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

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

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

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

NVIDIA 讓秘密大白于天下

相比之下,NVIDIA的優(yōu)化設(shè)置更為科學(xué),不僅有預(yù)置的優(yōu)化方案,也有適合高級玩家的細(xì)節(jié)調(diào)整。

先說簡單的方法,在NVIDIA的ForceWare驅(qū)動程序中提供了很多游戲、應(yīng)用程序的優(yōu)化設(shè)置方案,當(dāng)你想運行某個游戲前,只要在驅(qū)動控制面板中選中相應(yīng)的優(yōu)化方案就可以了。驅(qū)動中的方案會不定期進行調(diào)整、添加,即便很多新的游戲,也會在短期內(nèi)擁有相應(yīng)的預(yù)置優(yōu)化方案。

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

篇3

關(guān)鍵詞:USB協(xié)議;Linux驅(qū)動;USB Device驅(qū)動

中圖分類號:TP316文獻標(biāo)識碼: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

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

1 USB體系結(jié)構(gòu)及協(xié)議

1.1 USB硬件系統(tǒng)結(jié)構(gòu)

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

1.2 USB數(shù)據(jù)傳輸通道

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

1.3 USB總線枚舉

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

2 Linux USB 驅(qū)動程序

在Linux系統(tǒng)中,USB驅(qū)動程序可以分為USB Host驅(qū)動程序和USB Device驅(qū)動程序。Linux USB Host驅(qū)動程序和USB Device驅(qū)動程序總體架構(gòu)如圖1所示。

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

Linux系統(tǒng)中, USB Device驅(qū)動分為UDC驅(qū)動、Gadget API、Gadget驅(qū)動三個層次結(jié)構(gòu)。UDC驅(qū)動處USB Device控制器硬件之上,該驅(qū)動程序控制USB控制器硬件工作,同時向上層提供操作USB控制器硬件的回調(diào)函數(shù)。處在中間層的是Gadget API層,該API向下層和上層提供統(tǒng)一的編程接函數(shù)的封裝。Gadget驅(qū)動程序完成設(shè)備功能的實現(xiàn)。通過編寫不同Gadget驅(qū)動程序可以使設(shè)備具有不同的功能。

3 S3C2440 USB Device驅(qū)動

3.1 S3C2440 USB接口特性

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

1) 完全兼容USB1.1的協(xié)議。設(shè)備全速運行時可達(dá)到了12Mb/s。

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

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

3.2 S3C2440 USB Device驅(qū)動程序設(shè)計

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

Linux gadget驅(qū)動程序主要涉及到2個重要的結(jié)構(gòu)體usb_gadget_driver和struct file_operations結(jié)構(gòu)。其中usb_gadget_driver結(jié)構(gòu)體包括bind、setup、disconnect等一些函數(shù)。Linux Gadget提供usb_gadget_register_driver函數(shù)對Gaget驅(qū)動進行注冊。當(dāng)Gadget驅(qū)動被注冊后,Linux內(nèi)核就會調(diào)用結(jié)構(gòu)體usb_gadget_driver中的bind函數(shù)把Gadget驅(qū)動與UDA驅(qū)動進行綁定,這樣就可以在Gadget驅(qū)動中使用UDA提供的統(tǒng)一接口函數(shù)。

bind函數(shù)中需要完成以下工作:

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

2) 通過usb_ep_alloc_request函數(shù)為Gadget驅(qū)動分配一個請求。

3) 通過調(diào)用register_chrdev_region注冊設(shè)備驅(qū)動程序。

Bind函數(shù)完成這后當(dāng)有USB Host 向USB設(shè)備發(fā)出請求時,Linux系統(tǒng)將調(diào)用setup函數(shù)來響應(yīng)請求。Setup函數(shù)把設(shè)備的設(shè)備描述符、配置描述符、接口描述符以及以后需要使用的幾個端點描述符發(fā)送給USB Host,這些配置信息的發(fā)送都是通過usb_ep_queue函數(shù)來完的。

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

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

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

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

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

4 結(jié)束語

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

參考文獻:

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

[2] 薛園園.USB應(yīng)用開發(fā)技術(shù)大全[M].北京:人民郵電出版社,2007.

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

[4] 于明,范書瑞,曾祥燁.ARM9嵌人式系統(tǒng)設(shè)計與開發(fā)教程[M].北京:電子工業(yè)出版社,2006.

篇4

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

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

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

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

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

篇5

關(guān)鍵詞:VxWorks;USB設(shè)備驅(qū)動;管道;回調(diào)

中圖分類號:TP316文獻標(biāo)識碼: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驅(qū)動概述

VxWorks是WindRiver公司開發(fā)的具有工業(yè)領(lǐng)導(dǎo)地位的高性能實時操作系統(tǒng)(Real Time Operation System, RTOS)內(nèi)核。VxWorks5.5實現(xiàn)了USB1.1協(xié)議棧。圖1提供一個VxWorks下USB主驅(qū)動棧的簡單結(jié)構(gòu)。

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

2 VxWorks下USB設(shè)備驅(qū)動詳解

2.1 驅(qū)動程序提供的函數(shù)

2.1.1 向應(yīng)用程序提供的接口函數(shù)

設(shè)備驅(qū)動程序的主要作用是向上層應(yīng)用程序屏蔽硬件,向上層應(yīng)用程序提供統(tǒng)一的接口函數(shù),驅(qū)動程序一般需要實現(xiàn)的函數(shù)如表1所示。

圖1 USB主驅(qū)動棧結(jié)構(gòu)

表1 驅(qū)動程序提供的接口

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

usbMSCDevCreate();這是一個創(chuàng)建設(shè)備例程,當(dāng)有設(shè)備接入時,回調(diào)函數(shù)usbMSCDevAttachCallback()調(diào)用該例程創(chuàng)建一個邏輯設(shè)備,當(dāng)這個例程被調(diào)用時必須在系統(tǒng)中存在一個實際的USB物理設(shè)備。

usbMSCDevDestroy();從系統(tǒng)中刪除設(shè)備。首先釋放設(shè)備占有的資源,從設(shè)備鏈表中移除該設(shè)備,同時調(diào)用usbdPipeDestroy()銷毀該設(shè)備與主機之間的通信管道,最后釋放設(shè)備結(jié)構(gòu)體。

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

2.1.2 兩個重要的回調(diào)函數(shù)

在編寫USB設(shè)備驅(qū)動程序時,除了上述接口函數(shù)外,還需要編寫另外兩個重要的回調(diào)函數(shù):usbMSCDevAttachCallback()和usbMSCIrpCallback()。usbMSCDevAttachCallback()用于跟蹤設(shè)備的請求實現(xiàn)動態(tài)接入或刪除;usbMSCIrpCallback()是一個IRP callback,當(dāng)每一個IRP執(zhí)行完成之后調(diào)用該回調(diào)函數(shù),實現(xiàn)IRP之間同步。

2.2 設(shè)備標(biāo)識

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

2.3 回調(diào)(Callback)

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

2.4 數(shù)據(jù)傳輸

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

1) 創(chuàng)建設(shè)備時創(chuàng)建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) 構(gòu)造USB_IRP outIrp請求包。

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

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

6) 構(gòu)造USB_IRP inIrp請求包。

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

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

2.5 多個設(shè)備管理

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

3 VxWorks下LM9833驅(qū)動程序?qū)崿F(xiàn)

3.1 LM9833 USB接口簡介

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

3.2 設(shè)備描述符結(jié)構(gòu)

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;

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

3.3 注冊設(shè)備(LM9833)驅(qū)動程序

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

#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()調(diào)用usbdClientRegister()向USBD注冊一個名為SCAN_CLASS的Client,同時調(diào)用usbdDynamicAttachRegister()向USBD注冊一個回調(diào)例程usbScanDevAttachCallback (),跟蹤該Client請求,當(dāng)設(shè)備動態(tài)地接入或移出系統(tǒng)時會自動地調(diào)用該回調(diào)函數(shù)。一個Client在利用usbdDynamicAttachRegister()進行注冊時只對特定的class、subclass、protocol感興趣。在成功注冊Client后,USBD返回一個Client句柄(USBD_CLIENT_HANDLE),以后對USBD的調(diào)用都會用到這個句柄。Attach callback 如下。

LOCAL VOID usbScanDevAttachCallback

(

USBD_NODE_ID nodeId,

UINT16 attachAction,

UINT16 configuration,

UINT16 interface,

UINT16 deviceClass,

UINT16 deviceSubClass,

UINT16 deviceProtocol

)

該回調(diào)函數(shù)主要響應(yīng)外部設(shè)備的動作,實現(xiàn)USB設(shè)備的動態(tài)接入和移除。

3.4 創(chuàng)建設(shè)備

創(chuàng)建設(shè)備函數(shù)如下:

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

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

圖2 創(chuàng)建設(shè)備流程

3.5 讀寫設(shè)備

對設(shè)備進行讀寫時,首先需要將讀寫函數(shù)轉(zhuǎn)換成設(shè)備能夠識別的命令,對于LM9833來說,需將讀寫函數(shù)轉(zhuǎn)換成LM9833所能識別的四字節(jié)讀寫命令,讀寫時將這四字節(jié)的命令置于IRP包數(shù)據(jù)域的最前端,這樣到數(shù)據(jù)到達(dá)設(shè)備時首先接收到的是四個字節(jié)的命令,LM9833會根據(jù)這四個字節(jié)的命令完成相應(yīng)的功能。讀寫函數(shù)原型為:

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所示,查找設(shè)備流程如圖4所示。

圖3 LM9833讀寫控制流程

圖4 查找設(shè)備流程

設(shè)備命令組幀:

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

引言

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

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

1 CAN總線通信協(xié)議及CAN通信卡介紹

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

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

2 CAN卡驅(qū)動底層函數(shù)設(shè)計

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

2.1 CAN卡寄存器讀寫函數(shù)

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

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

{

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

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

{

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

}

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

2.2 CAN卡初始化

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

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

第二卡,設(shè)置CAN卡默認(rèn)參數(shù):

CanCardConfigInfo CAN_DEFAULT_SETTING=

{0X00,0XFF,0X03,0X1C};/*設(shè)置默認(rèn)波特率為125Kbps*/

DWORD dwThreadID =0;

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

第三卡,用WinCE API函數(shù)LocalAlloc為CAN卡驅(qū)動中用到的數(shù)據(jù)結(jié)構(gòu)分配緩沖區(qū);通過HalTranslateBusAddress和MmMapIoSpace函數(shù)映射I/O地址,提供直接訪問設(shè)備的虛擬地址:

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;

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

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

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

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

第六步,初始化中斷,如果CAN卡有復(fù)位請求就退出初始化程序。設(shè)置好中斷后啟動數(shù)據(jù)接收線程,設(shè)置線程優(yōu)先級繼續(xù)線程處理;最后配置CAN卡參數(shù),進入正常運行狀態(tài)。

2.3 CAN卡信息發(fā)送

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

表1

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

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

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); /*進入臨界區(qū)*/

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

CANW(hCan,10,byV); /*設(shè)置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);/*設(shè)置ID值低3位、RTR及數(shù)據(jù)長度*/

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

{

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

} /*采集數(shù)據(jù)*/

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

while(TRUE)

{byV=CANR(hCan,2);

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

{break;}

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

bSuc = TRUE;

break;}

}

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

return bSuc;

}

2.4 CAN卡信息接收

CAN卡的信息接收是發(fā)送的逆過程,當(dāng)接收緩沖區(qū)標(biāo)志為1時,表示緩沖區(qū)已滿可以接收數(shù)據(jù),將數(shù)據(jù)接收到數(shù)組后釋放接收緩沖區(qū),然后對接收到的數(shù)據(jù)進行分解并存儲到CAN卡信息緩沖區(qū)的結(jié)構(gòu)體。接收緩沖區(qū)的寄存器結(jié)構(gòu)如表2所列。

CAN消息接收函數(shù)的實現(xiàn)如下:

BOOL CAN_RecvRecvMessage(LPCAN_HW_OPEN_INFO

HCan,OUT LPCanCardMessageBuflpMsg)

{……

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

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

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

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

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

BYTE byV =recvBuf[1];

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

LpMsg->bRTR =byV &0x10?TRUE:/*返回RTR狀態(tài)*/

LpMsg->dwMessageLen = byV &0XF; /*返回數(shù)據(jù)長度*/

……

}

else

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

::LeaveCriticalSection(&hCan->lpCanHWInfo->

ReceiveCritSec); /*離開臨界區(qū)*/

Return bSuc;

}

2.5 CAN卡事件處理

CAN卡事件處理函數(shù)是CAN卡驅(qū)動程序中很重要的部分。驅(qū)動設(shè)計要求具有消息通知的功能,當(dāng)事件發(fā)生時及時捕獲事件并進行消息處理。

下面是事件處理函數(shù)的實現(xiàn):

staric DWORD WINAPI CAN_EventHanle(LPVOID lpParam)

{

ASSERT(lpParam);

LPCAN_HW_OPEN_INFO hCan=(LPCAN_HW_OPEN_INFO)lpParam;

CanCardMessageBuf bufMsg;

while(TEUE)

{ /*循環(huán)等待CAN卡消息產(chǎn)生,然后進行處理*/

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

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

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

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

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

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

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

} /*本次中斷結(jié)束,等待下次中斷*/

return 0;

}

2.6 其它函數(shù)

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

3 CAN卡驅(qū)動封裝設(shè)計

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

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

*CanCloseFile;關(guān)閉由CanOpenFile打開的CAN卡端口。

*CanRecvMsg;接收CAN卡數(shù)據(jù),打開CAN卡時必須具有GENERIC_READ權(quán)限。

*CanSendMsg;通過CAN卡發(fā)送數(shù)據(jù)。打開CAN卡時必須具有GENERIC_WRITE權(quán)限。

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

下面是CanSendMsg函數(shù)實現(xiàn)的代碼:

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);

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

結(jié)語

篇7

通信卡的硬件設(shè)計

1 通信卡的主要特點

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

2 通信卡的電路設(shè)計

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

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

3 通信流程設(shè)計

如果要發(fā)送一幀數(shù)據(jù),CPU用批命令將數(shù)據(jù)放到本卡SRAM中,然后設(shè)置相應(yīng)的發(fā)送DMA通道。DMA通道是非自動重裝方式,啟動8274控制器發(fā)送,然后CPU就不需要管理,由卡上硬件自動發(fā)送。

如果需要接收數(shù)據(jù),啟動接收通道。接收通路自動搜索輸入信號,搜索到數(shù)據(jù)幀時,由卡上DMA控制器來管理,將接收的數(shù)據(jù)放人本卡SRAM中,并向CPU請求中斷,讀出數(shù)據(jù)。

4 總線競爭設(shè)計

由于同時可進行四路通信,且CPU可隨時對某一路發(fā)控制命令或訪問卡上SRAM存儲器,就將出現(xiàn)CPU與本卡主設(shè)備DMA爭用本卡總線的狀況。由于ISA總線沒能給出CPU指令排隊狀態(tài)序列,這給總線仲裁帶來了困難,而本卡的總線競爭、仲裁是由可編程邏輯器件設(shè)計的狀態(tài)機來完成的。狀態(tài)機使用一個4MHz信號作為時鐘,共設(shè)3種狀態(tài):

①CPU控制狀態(tài)。

②DMA控制狀態(tài)。

③空閑狀態(tài),CPU及DMA均未能得到控制權(quán)。

當(dāng)狀態(tài)機檢測到無CPU及DMA申請總線使用權(quán)時,就進入空閑狀態(tài),而一旦CPU或DMA請求總線,狀態(tài)機立即將總線使用權(quán)交給CPU或DMA。如果正在CPU控制狀態(tài)期間,DMA申請總線使用權(quán),狀態(tài)機仍然判定CPU控制總線,讓DMA處于等待,直到檢測CPU指令完成,狀態(tài)機才轉(zhuǎn)為DMA控制狀態(tài)。如果在DMA控制狀態(tài)時,CPU申請總線使用權(quán),狀態(tài)機仍然判定DMA控制總線,讓CPU處于等待,直至DMA字節(jié)傳送完,狀態(tài)機轉(zhuǎn)為CPU控制狀態(tài)。CPU及DMA對總線的使用權(quán)是單個指令或字節(jié)傳送,不設(shè)置總線封鎖,因而CPU、DMA可頻繁交換使用權(quán),不會出現(xiàn)等待時間過長的現(xiàn)象。

通信卡的驅(qū)動程序設(shè)計

1 設(shè)備驅(qū)動程序的I/O模型

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

2 發(fā)送數(shù)據(jù)I/O例程設(shè)計

在用戶態(tài)提交發(fā)送任務(wù)到核心態(tài),由I/O管理程序負(fù)責(zé)調(diào)用驅(qū)動程序,驅(qū)動程序發(fā)送IRP交給硬件,假若當(dāng)前發(fā)送器不忙,則具體的發(fā)送操作全部由發(fā)送器自行完成,而驅(qū)動程序則返回已經(jīng)一個本幀可以發(fā)送的標(biāo)志。具體的發(fā)送完成結(jié)果則可以在發(fā)送任務(wù)完成后查詢得到??墒牵绻绦蛳虍?dāng)前設(shè)備發(fā)送器提交發(fā)送任務(wù)時,該發(fā)送器正在處理上一幀,那么則有兩種方法處理。

①立即方式:立即返回一個錯誤,當(dāng)前設(shè)備忙,不能發(fā)送。

②阻塞方式:I/O管理器程序會調(diào)度相應(yīng)的異步處理例程,將當(dāng)前的發(fā)送任務(wù)放進任務(wù)隊列中,返回一個標(biāo)志:I/O掛起,當(dāng)前設(shè)備忙,發(fā)送任務(wù)提交任務(wù)隊列。驅(qū)動程序會在發(fā)送器空閑時,提交任務(wù)隊列中的發(fā)送任務(wù)給發(fā)送器。完成發(fā)送任務(wù)后,將相關(guān)文件句柄設(shè)為有信號狀態(tài),通知本次發(fā)送任務(wù)完成。

3 接收數(shù)據(jù)I/O例程

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

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

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

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

當(dāng)用戶提交接收任務(wù)時,由驅(qū)動程序的調(diào)度程序讀取接收線程的緩沖區(qū)隊列,并將標(biāo)志置為“空”,同時將緩沖隊列事件置為無信號狀態(tài),并返回,如果緩沖區(qū)是空,則

?立即方式:立即返回?zé)o數(shù)據(jù)。

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

4 硬中斷服務(wù)程序設(shè)計

通信卡在全雙工的通信中具有實時性,而且在較高的波特率,硬中斷非常多。為了防止高優(yōu)先級中斷過多地?fù)屨糃PU時間,設(shè)計中采用了實時中斷服務(wù)程序和延遲過程調(diào)用的方法。

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

5 驅(qū)動程序人口例程

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

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

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

6 設(shè)計驅(qū)動程序中需要注意的問題

由于通信卡在應(yīng)用中具有一定的實時性,為了克服中斷的不確定性。提高系統(tǒng)的性能,開發(fā)了Windows XP系統(tǒng)所有驅(qū)動程序中最難的異步驅(qū)動程序。在系統(tǒng)的內(nèi)核開發(fā),異步模型I/O操作中,內(nèi)核對象的同步十分復(fù)雜,細(xì)微的差錯都會導(dǎo)致系統(tǒng)徹底崩潰。在設(shè)計驅(qū)動程序中需要注意以下問題。

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

篇8

關(guān)鍵詞:嵌入式系統(tǒng);linux;驅(qū)動程序

引言

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

設(shè)備驅(qū)動程序的編寫

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

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

字符設(shè)備驅(qū)動程序、塊設(shè)備驅(qū)動程序與網(wǎng)絡(luò)設(shè)備驅(qū)動程序的結(jié)構(gòu)體是不同的。

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

應(yīng)用程序只有通過對設(shè)備文件的open、release、read、write、ioctl等才能訪問字符設(shè)備和塊設(shè)備。用戶自己定義好file_operations結(jié)構(gòu)后,編寫出設(shè)備實際所需要的各操作函數(shù),對于不需要的操作函數(shù)用NULL初始化,這些操作函數(shù)將被注冊到內(nèi)核,當(dāng)應(yīng)用程序?qū)υO(shè)備相應(yīng)的設(shè)備文件進行文件操作時,內(nèi)核會找到相應(yīng)的操作函數(shù),并進行調(diào)用。如果操作函數(shù)使用NULL,操作函數(shù)就進行默認(rèn)處理。

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

網(wǎng)絡(luò)設(shè)備結(jié)構(gòu)體net_device定義在include\linuxhletdevice.h里,如下所示:

定義好net_device結(jié)構(gòu)體后,根據(jù)實際情況編寫操作函數(shù),其中hard_start_xmit()函數(shù)是用來發(fā)送數(shù)據(jù)的,set mac address()是進行網(wǎng)絡(luò)參數(shù)設(shè)置的。

當(dāng)linux初始化時將調(diào)用初始化函數(shù)intdevice_init(),該函數(shù)包括以下內(nèi)容:

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

字符設(shè)備注冊函數(shù)如下:

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

由于對網(wǎng)絡(luò)設(shè)備驅(qū)動程序的訪問不需要設(shè)備節(jié)點,它的注冊函數(shù)如下:

int register_netdev(struct net_device*dev)

注冊設(shè)備所用的中斷。中斷在現(xiàn)代計算機結(jié)構(gòu)中有重要的地位,操作系統(tǒng)必須提供程序響應(yīng)中斷的能力。一般是把一個中斷處理程序注冊到系統(tǒng)中去。操作系統(tǒng)在硬件中斷發(fā)生后調(diào)用驅(qū)動程序的處理程序。

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

當(dāng)linux不使用該設(shè)備時,就要調(diào)用清除函

編寫服務(wù)子程序

服務(wù)于I/O請求的子程序,又稱為驅(qū)動程序的上半部分。調(diào)用這部分是由于系統(tǒng)調(diào)用的結(jié)果。這部分程序在執(zhí)行的時候,系統(tǒng)仍認(rèn)為是和進行調(diào)用的進程屬于同一個進程,只是用戶態(tài)變成了核心態(tài),具有進行此系統(tǒng)調(diào)用的用戶程序的運行環(huán)境,因此可以在其中調(diào)用sleep等與進程運行環(huán)境有關(guān)的函數(shù)。

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

設(shè)備驅(qū)動程序的使用

直接將驅(qū)動程序編譯進linux內(nèi)核

將設(shè)備驅(qū)動程序復(fù)制到linux/drivers相關(guān)的子目錄下,比如字符設(shè)備驅(qū)動程序就放在linux/drivers/char下。

修改linux/drivers相關(guān)的子目錄的Makefile,

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

對內(nèi)核進行重新編譯時,進行相關(guān)的配置,比如要使用AT91RM9200的UART,就要如下配置:

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

將驅(qū)動程序編譯成驅(qū)動模塊

在設(shè)備驅(qū)動程序中要有兩個重要函數(shù):

module_init(dev-init),module_exit(dev_exit)

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

篇9

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

1 μC/OS-II實時內(nèi)核下的A/D讀方法

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

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

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

ADRd(ChannelNumber)

{

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

等待AMUX輸出穩(wěn)定;

啟動ADC轉(zhuǎn)換;

等待來自ADC轉(zhuǎn)換結(jié)束中斷產(chǎn)生的信號量;

if(超時){

*eer=信號錯誤;

return;

}else{

讀取ADC轉(zhuǎn)換結(jié)果并將其返回到應(yīng)用程序;

}

}

    ADCoversion Complete ISR {

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

通知內(nèi)核進入ISR(調(diào)用OSIntEnter()或OSIntNesting直接加1);

發(fā)送ADC轉(zhuǎn)換完成信號; /*利用μC/OS-II內(nèi)核的OSSemPost()*/

通知內(nèi)核退出ISR(調(diào)用OSIntExit());

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

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

}

在這種方法里,要求ISR執(zhí)行時間與調(diào)用等待信號的時間之和為A/D轉(zhuǎn)換時間。

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

ADRd(ChannelNumber){

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

等待AMUX輸出穩(wěn)定;

啟動ADC轉(zhuǎn)換;

啟動超時定時器;

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

if(Counter==0){

*err=信號錯誤;

return;

}else{

讀取ADC轉(zhuǎn)換結(jié)果并將其返回到應(yīng)用程序;

}

}

A、D轉(zhuǎn)換速度快,這種驅(qū)動程序的實現(xiàn)是最好的。

2 C8051F015單片機的A/D轉(zhuǎn)換器

2.1 C8051C015單片機

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

2.2 C8051F015的A/D轉(zhuǎn)換電路

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

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

2.3 ADC轉(zhuǎn)換速度

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

表1 ADC時鐘分頻系數(shù)與SYSCLK頻率的關(guān)系

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

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

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

圖4 A/D驅(qū)動程序模塊流程圖

3 A/D驅(qū)動程序的編寫

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

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

在μC/OS-II這時內(nèi)核下各原型函數(shù)、數(shù)據(jù)結(jié)構(gòu)和常量的定義如下:

INT16S ADRd(INT8U ch);

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

void ADUpdate(void);

/*一定時間內(nèi)更新輸入通道*/

void ADInit(void);

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

void ADTask (void data);

/*由ADInit()創(chuàng)建,負(fù)責(zé)更新輸入通道(調(diào)用ADUpdate ())*/

void ADInitI (void);

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

AD_TaskPrio:設(shè)置任務(wù)ADTask()的優(yōu)先級。

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

AD_MaxNummber:AMUX的輸入通道數(shù)。

AD_TaskDly:設(shè)定更新通道的間隔時間。

AD ADTbl[AD_MaxNummber]:AD類型的數(shù)組(AD是定義的數(shù)據(jù)結(jié)構(gòu))。

4 結(jié)論

對于A/D轉(zhuǎn)換器接口電路驅(qū)動程序的編寫歸納出以下幾點:

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

②對于轉(zhuǎn)換速度快的A/D轉(zhuǎn)換器,可能出現(xiàn)CPU的處理速度與A/D轉(zhuǎn)換速度不匹配,一般的A/D中不帶有FIFO緩沖區(qū),須有內(nèi)存中開辟緩沖區(qū);

篇10

第一節(jié)windows nt網(wǎng)絡(luò)結(jié)構(gòu)

§1.1.1 windows nt網(wǎng)絡(luò)體系結(jié)構(gòu)

windows nt的網(wǎng)絡(luò)體系結(jié)構(gòu)是基于國際標(biāo)準(zhǔn)化(iso)制定的標(biāo)準(zhǔn)模型──開放式系統(tǒng)互連(open system interconnection:osi)參考模型分層建立的,這種方式有利于隨時擴展其它功能和服務(wù)。

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

這一網(wǎng)絡(luò)體系結(jié)構(gòu)包括兩個重要接口──ndis接口與傳輸驅(qū)動

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

在兩個接口之間,是傳輸協(xié)議。它在網(wǎng)絡(luò)中起著組織者的作用。一個傳輸協(xié)議規(guī)定了數(shù)據(jù)以何種方式呈遞給下一個接收層,以及如何對數(shù)據(jù)相應(yīng)地進行打包。它通過ndis把數(shù)據(jù)傳給網(wǎng)卡驅(qū)動程序,并通過tdi把數(shù)據(jù)傳給轉(zhuǎn)發(fā)程序(redirector)

tdi之上是轉(zhuǎn)發(fā)程序,它把本地的網(wǎng)絡(luò)資源申請轉(zhuǎn)送給網(wǎng)絡(luò)。

為了能和其他廠商的網(wǎng)絡(luò)互連,windows nt允許有多個轉(zhuǎn)發(fā)程序。對于每一個轉(zhuǎn)發(fā)程序windows nt計算機必須也有一個相應(yīng)的供應(yīng)者(provider)(由網(wǎng)絡(luò)廠商提供)。多供應(yīng)者路由選擇程序決定適當(dāng)?shù)墓?yīng)者,然后借助于供應(yīng)者,對應(yīng)用請求到相應(yīng)的轉(zhuǎn)發(fā)程序做出選擇。windows nt支持兩種類型的網(wǎng)絡(luò)驅(qū)動程序

傳輸驅(qū)動程序

實現(xiàn)數(shù)據(jù)鏈路層中的邏輯鏈路控制子層協(xié)議和傳輸層協(xié)議。向 下與ndis接口,向上與tdi接口。

網(wǎng)卡驅(qū)動程序

實現(xiàn)對物理層的管理和數(shù)據(jù)鏈路層中介質(zhì)訪問控制子層協(xié)議,通過ndis向下管理物理網(wǎng)卡,向上與傳輸驅(qū)動程序通信。

§1.1.3 windows nt網(wǎng)卡驅(qū)動程序

windows nt環(huán)境下的網(wǎng)卡驅(qū)動程序也分為兩種:

miniport網(wǎng)卡驅(qū)動程序:miniport驅(qū)動程序只須實現(xiàn)與網(wǎng)絡(luò)硬件相關(guān)的操作(包括發(fā)送和接收)。而所有底層網(wǎng)卡驅(qū)動程序的通用操作(如同步),一般由ndis接口程序來實現(xiàn)。

full網(wǎng)卡驅(qū)動程序:full網(wǎng)卡驅(qū)動程序必須實現(xiàn)所有硬件相關(guān)和同步、排隊等操作。例如full網(wǎng)卡驅(qū)動程序為了響應(yīng)數(shù)據(jù)接收,需要保持本身的捆綁信息,而miniport就可以由ndis接口庫來實現(xiàn)。

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

而miniport網(wǎng)卡驅(qū)動程序允許開發(fā)者僅僅寫一些與網(wǎng)絡(luò)硬件相關(guān)的代碼即可,而那些通用的函數(shù)由ndis接口庫來實現(xiàn),這樣開發(fā)出來的驅(qū)動程序減少了不必要的工作。

第二節(jié)miniport驅(qū)動程序的結(jié)構(gòu)

ndis接口規(guī)范了網(wǎng)卡驅(qū)動程序的實現(xiàn),同時也對tdi驅(qū)動程序的實現(xiàn)提出了一定的要求,在nt中,ndis約束下的網(wǎng)卡驅(qū)動程序、tdi驅(qū)動程序和系統(tǒng)的關(guān)系如下圖所示:

圖2.0 ndis約束下的網(wǎng)卡驅(qū)動程序、tdi驅(qū)動程序和系統(tǒng)的關(guān)系

miniport驅(qū)動程序包括驅(qū)動程序?qū)ο?、?qū)動程序源代碼和ndis接口庫代碼。windows nt ddk提供ndis.h作為miniport驅(qū)動程序的主要頭文件,定義了miniport驅(qū)動程序的入口點、ndis接口庫函數(shù)和通用數(shù)據(jù)結(jié)構(gòu)。

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

這些上邊緣服務(wù)函數(shù)由驅(qū)動程序的開發(fā)者根據(jù)驅(qū)動程序面向的特定低層網(wǎng)絡(luò)類型和硬件以及相應(yīng)環(huán)境,可以有選擇地實現(xiàn),但必須保證驅(qū)動程序最基本的功能,這些基本功能包括初始化、發(fā)送、中斷處理、重置、參數(shù)查詢與設(shè)置和報文接收。

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

miniportreconfigure:支持網(wǎng)卡參數(shù)動態(tài)變化,和miniportinitilize一樣由ndis接口以初始化級別調(diào)度執(zhí)行(不能屏蔽中斷,必須由驅(qū)動程序承認(rèn)并清除在此期間產(chǎn)生的中斷),支持即插即用和軟配置的網(wǎng)卡在動態(tài)改變參數(shù)時,必須提供此函數(shù)。

miniportqueryinformation:查詢網(wǎng)卡的狀態(tài)以及網(wǎng)卡驅(qū)動程序的操作或統(tǒng)計參數(shù),如是否支持組通訊、網(wǎng)卡的物理速率是否支持回環(huán)、是否支持直接拷貝等,這些參數(shù)以oid方式統(tǒng)一管理。

miniportsetinformation:ndis接口或協(xié)議驅(qū)動程序通過調(diào)用此接口改變驅(qū)動程序維護的oid庫,一些操作參數(shù)的改變也將同時改變驅(qū)動程序狀態(tài),例如組地址的設(shè)置。

miniportreset:包括網(wǎng)卡硬件重置和驅(qū)動程序軟件重置,軟件重置包括驅(qū)動程序狀態(tài)重置,以及一些相關(guān)的參數(shù)重置,還需考慮有些參數(shù)的恢復(fù),重置時不必完成所有正在活躍的外部請求,但必須釋放已占用的外部資源。

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

miniportisr:高優(yōu)先級的中斷處理程序,進行的工作包括初始中斷處理類型,決定是否進行中斷轉(zhuǎn)交,對卡上中斷進行處理 等,該服務(wù)類型只在以下情況被調(diào)用:

ndis接口調(diào)用miniportinitialize和miniporthalt兩函數(shù)時。

.中斷處理類型設(shè)為每此中斷處理過程都調(diào)用時。

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

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

miniportsend:ndis收到上層發(fā)送請求時經(jīng)過若干協(xié)議處理再向下調(diào)用此服務(wù)過程,發(fā)送的packet已含有l(wèi)lc和mac頭,該服務(wù)過程進行邊界對齊、packet約束重整、描述符映射和報文發(fā)送、以及發(fā)送資源和packet緩沖隊列管理。

miniporttransferdata:多個已和網(wǎng)卡捆綁的協(xié)議驅(qū)動程序在接收到報文到達(dá)指示后,向網(wǎng)卡驅(qū)動程序發(fā)出傳送請求以拷貝各自所需的報文數(shù)據(jù)部分,網(wǎng)卡驅(qū)動程序根據(jù)各協(xié)議驅(qū)動程序?qū)蝹€packet是否進行多次拷貝,以決定是否暫存只允許單次拷貝的packet等。

miniportcheckhandle:ndis每秒調(diào)用此服務(wù)函數(shù)一次,驅(qū)動程序發(fā)現(xiàn)網(wǎng)卡異常時報告給ndis由ndis調(diào)用miniportreset進行硬件重恢復(fù)。

miniportenableintrrupt:中斷使能。

miniportdisableinterrupt:中斷屏蔽。

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

第二章fddi網(wǎng)卡驅(qū)動程序的加載和運行

第一節(jié) 網(wǎng)卡驅(qū)動程序的安裝

windows nt網(wǎng)卡驅(qū)動程序安裝的目的是實現(xiàn)網(wǎng)卡相應(yīng)硬件信息和驅(qū)動程序在windows nt注冊庫中的注冊,使windows nt能夠正確識別網(wǎng)卡,了解所必需的軟硬件信息并能在windows nt啟動時加載相應(yīng)驅(qū)動程序。

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

復(fù)制驅(qū)動程序到相應(yīng)的系統(tǒng)目錄(windows nt根目錄system32drivers)中;

在windows nt注冊庫中存入相應(yīng)軟硬件信息。

下面主要以fddi網(wǎng)卡為例介紹安裝驅(qū)動程序所必需的工作:

§2.1.1網(wǎng)卡一般硬件參數(shù)

對于fddi網(wǎng)卡,必須在編寫其oemsetup.inf文件時確定以下硬件參數(shù):

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

廠商代號:0x5588……系統(tǒng)加載時確定網(wǎng)卡的標(biāo)記,也是編程時確定pci槽號的標(biāo)識;

cfid: 0x01;

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

是否支持全雙工:支持。

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

software registrion鍵,對應(yīng)于驅(qū)動程序,存在于hkey_local_machinesoftwarecompany productnameversion中。我們的fddi網(wǎng)卡驅(qū)動程序所對應(yīng)的是hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;

網(wǎng)卡的軟件登錄鍵,存在于hkey_local_machinesoftwaremicrosoft windows ntnt3.51networkcardsyhfddi1;

驅(qū)動程序的服務(wù)登錄鍵,存在于hkey_local_machinesystemcurrentcontrolsetservices

網(wǎng)卡的服務(wù)登錄鍵,存在于hkey_local_machinesystemcurrentcontrolsetservices

對于每一個網(wǎng)絡(luò)部件,一個名為netrules的特殊子鍵在鄰近的驅(qū)動程序或網(wǎng)卡登錄子鍵里創(chuàng)建,netrules標(biāo)識網(wǎng)絡(luò)部件為網(wǎng)絡(luò)整體的一部分。

fddi網(wǎng)卡驅(qū)動程序?qū)?yīng)的標(biāo)準(zhǔn)軟件登錄表項將出現(xiàn)在以下路徑:

hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;

驅(qū)動程序?qū)?yīng)的標(biāo)準(zhǔn)項的值為:

description =yhfddi/pci adapter controller

install date =……

……

refcount =0x01

servicename =yhfddi

softwaretype =driver

title =yhfddi/pci adapter controller

而且在yhfddi驅(qū)動程序相關(guān)的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網(wǎng)卡在如下路徑的networkcards子鍵里介紹:

hkey_local_machinesoftwaremicrosoft

windows ntnt3.51networkcardsyhfddi1;

網(wǎng)卡的標(biāo)準(zhǔn)項包括以下這些值:

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用以書寫系統(tǒng)所有部件的配置文件,當(dāng)然也可以用以書寫網(wǎng)絡(luò)系統(tǒng)各部件的配置文件,該配置文件描述了網(wǎng)絡(luò)部件安裝、配置、刪除的執(zhí)行過程。當(dāng)網(wǎng)絡(luò)部件進行初始安裝或二次安裝(通常通過ncpa進行)時,安裝程序讀取部件對應(yīng)的配置文件,進行解釋執(zhí)行。gui inf描述語言由節(jié)、命令、邏輯操作、變量規(guī)范、流程控制以及一套調(diào)用dll或外部程序的機制組成,其中,節(jié)是配置文件的主體,節(jié)可分為install節(jié)(類似于函數(shù)),shell節(jié)(也類似于函數(shù),但可調(diào)用insall和shell節(jié)),detect節(jié)(不包含命令),一個配置文件一般由若干不同類型的節(jié)組成。驅(qū)動程序的開發(fā)者根據(jù)需要可以在配置文件中編寫相應(yīng)代碼,使得用戶和系統(tǒng)之間能進行交互,并且由用戶決定一些配置參數(shù)。

nt網(wǎng)卡配置文件有其一套規(guī)范,驅(qū)動程序開發(fā)者必須按規(guī)范編寫配置文件,一般來說,一個配置文件至少應(yīng)該提供下面三個節(jié):

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

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

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

第二節(jié) 驅(qū)動程序的加載過程

§2.2.1 windows nt的啟動過程