驅動程序范文
時(shi)間:2023-04-09 11:54:56
導語:如何(he)才能寫好(hao)一篇(pian)驅動程序,這就需要搜(sou)集整(zheng)理(li)更(geng)多的資料和文獻,歡迎(ying)閱讀由(you)公(gong)務員之家整(zheng)理(li)的十篇(pian)范文,供你借鑒。
篇1
2、下拉菜單(dan)中選“屬性”,
3、屬(shu)性中選“硬件”,
4、硬件(jian)里(li)選“設備(bei)管理器”,
5、設(she)備管理器中點開“端(duan)口”,
6、端口(kou)里右鍵點“打印機端口(kou)”
7、選“屬性”
8、屬性里選“驅動程序”
9、驅(qu)(qu)動(dong)程(cheng)序(xu)里選(xuan)“驅(qu)(qu)動(dong)程(cheng)序(xu)詳細(xi)信息”
10、此(ci)時(shi)在驅動(dong)文(wen)件窗口里顯示的就(jiu)是驅動(dong)文(wen)件所在位置及名稱。
篇2
這歸結于優化(hua)的(de)功(gong)效,很多(duo)玩家都可(ke)以有針(zhen)對性地(di)對游戲(xi)進行(xing)優化(hua)設置,調(diao)整系統、優化(hua)資源,同時對游戲(xi)進行(xing)設置上的(de)更改(gai),尋找最佳的(de)平衡點(dian)。
現(xian)在(zai),我們來嘗試針(zhen)對NVIDIA及(ji)ATI兩種主流顯卡品牌的(de)驅動(dong)程序進行優(you)化(hua)說明,來看(kan)看(kan)它們有(you)什么秘密吧!
ATI 提高《Doom》運行速度有技巧(qiao)
如果(guo)你想玩《Doom》一類采用(yong)(yong)OpenGL的(de)游(you)戲,尤(you)其是當你的(de)電腦使(shi)用(yong)(yong)ATI顯卡時,你必定會感到很煩惱(nao)。OpenGl性能不強使(shi)得ATI的(de)顯卡在以《Doom》為首(shou)的(de)OpenGL游(you)戲中一向(xiang)表現不佳(jia)。因(yin)此,針對OpenGL部分的(de)調節非常必要(yao),盡可能提高(gao)這方面的(de)性能是優(you)化ATI顯卡驅動程序的(de)重要(yao)方向(xiang)之一。
切(qie)換到ATI催化劑驅動(dong)程序的(de)OpenGL選(xuan)項卡上,選(xuan)中“主要設置”的(de)“自(zi)定義設置”,然(ran)后進行細節(jie)調整。將“紋理(li)選(xuan)項”和“Mipmap”的(de)拉桿向左拉到“性能”上,這樣可以(yi)保證在(zai)不(bu)明顯降低(di)畫面質(zhi)量的(de)情況下使OpenGL游戲速度得到保證,同(tong)(tong)時將“等待垂直同(tong)(tong)步信號(hao)”調整成(cheng)“始終為關”。
要想將ATI顯卡(ka)的(de)(de)潛(qian)力進行(xing)(xing)最大化的(de)(de)挖掘,還(huan)要進行(xing)(xing)自定義(yi)(yi)設(she)置(zhi)。勾選“使(shi)用(yong)自定義(yi)(yi)設(she)置(zhi)”項(xiang)后,再點擊“自定義(yi)(yi)”按(an)鈕就(jiu)可(ke)切換(huan)到(dao)自定義(yi)(yi)設(she)置(zhi)頁面。在其中“消除(chu)混疊”其實就(jiu)是(shi)(shi)指全屏抗(kang)鋸齒,在這里,如果你的(de)(de)顯卡(ka)是(shi)(shi)低于(yu)X1000系列的(de)(de),那(nei)么最好選擇2×或(huo)者干脆關閉。但是(shi)(shi),最高級的(de)(de)顯卡(ka)也不(bu)要妄想開(kai)啟6×,這時根本無法體驗游戲樂趣(qu)了(le)。
NVIDIA 讓秘密大(da)白于天下
相(xiang)比之下,NVIDIA的優(you)化(hua)設置(zhi)更為科學,不僅(jin)有預(yu)置(zhi)的優(you)化(hua)方案,也有適合高(gao)級玩家(jia)的細節調(diao)整。
先說簡單的(de)(de)(de)方(fang)(fang)法,在NVIDIA的(de)(de)(de)ForceWare驅(qu)動(dong)程(cheng)序(xu)中提供了很多游(you)戲(xi)、應用程(cheng)序(xu)的(de)(de)(de)優(you)化(hua)設置方(fang)(fang)案,當你想運行某個游(you)戲(xi)前,只(zhi)要在驅(qu)動(dong)控制(zhi)面板中選中相應的(de)(de)(de)優(you)化(hua)方(fang)(fang)案就可以了。驅(qu)動(dong)中的(de)(de)(de)方(fang)(fang)案會(hui)不定(ding)期進(jin)行調整、添加(jia),即(ji)便很多新的(de)(de)(de)游(you)戲(xi),也會(hui)在短期內(nei)擁有相應的(de)(de)(de)預(yu)置優(you)化(hua)方(fang)(fang)案。
當然,還(huan)是有很多玩家不會滿足于(yu)預(yu)置方案,自主(zhu)優化是另外一種選(xuan)擇。其中最(zui)能(neng)影響(xiang)性能(neng)及(ji)兼(jian)容性的(de)選(xuan)項莫過(guo)于(yu)“Anisotropic filtering”,即各向異性過(guo)濾了。這個(ge)選(xuan)項在開啟(qi)時會讓(rang)畫(hua)面(mian)更(geng)(geng)加(jia)精細,但(dan)是,它還(huan)帶來了性能(neng)大幅度下降、兼(jian)容性不佳的(de)“副作用”,所以,如果(guo)你的(de)顯卡并不是非常新,但(dan)又想玩新游戲(xi),不如把這個(ge)選(xuan)項關閉,以獲得更(geng)(geng)好的(de)運(yun)行速(su)度。
篇3
關鍵(jian)詞:USB協議;Linux驅動;USB Device驅動
中圖分類號:TP316文獻標識(shi)碼: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
嵌入(ru)式(shi)(shi)產(chan)品通(tong)過的(de)USB接口(kou)品可以(yi)很方(fang)便與(yu)PC的(de)USB進行通(tong)信(xin)以(yi)完成數據的(de)傳(chuan)輸與(yu)交(jiao)互。ARM嵌入(ru)式(shi)(shi)處(chu)(chu)理器性以(yi)其性能(neng)高、功(gong)耗低而(er)被(bei)廣泛地應用(yong)于消費電(dian)子(zi)、工(gong)業控制等眾多(duo)領域。以(yi)ARM內核(he)為核(he)心集(ji)成了USB功(gong)能(neng)的(de)處(chu)(chu)理器使(shi)得產(chan)品更簡潔、更靈(ling)活(huo)、更方(fang)便。S3C2440集(ji)成了ARM920T內核(he),帶(dai)MMU功(gong)能(neng),可運(yun)行linux操作系統(tong),同時帶(dai)有兩(liang)個USB Host一個USB Device控制器,因此在此基礎上完成Linux 下(xia)的(de)USB Device驅動程序(xu)有著重要(yao)的(de)意義(yi)。本(ben)文(wen)是(shi)以(yi)此處(chu)(chu)理器為核(he)心的(de)嵌入(ru)式(shi)(shi)智(zhi)能(neng)終端的(de)Linux下(xia)的(de)USB Device驅動程序(xu)設計。
1 USB體系結構及協議
1.1 USB硬(ying)件系統(tong)結構
USB接口是由+5V電(dian)源(yuan)線(xian)(xian)(xian)、電(dian)源(yuan)地線(xian)(xian)(xian)、信號(hao)線(xian)(xian)(xian)D+、信號(hao)線(xian)(xian)(xian)D-四根電(dian)纜線(xian)(xian)(xian)組成接口。其中+5V電(dian)源(yuan)是向設備(bei)(bei)提(ti)供(gong)電(dian)源(yuan),信號(hao)線(xian)(xian)(xian)作用是傳(chuan)輸(shu)(shu)數據, 為了提(ti)高信號(hao)傳(chuan)輸(shu)(shu)的抗干擾能力這(zhe)兩根數據線(xian)(xian)(xian)采用差(cha)分傳(chuan)輸(shu)(shu)。主機可以通(tong)過D+和(he)D-線(xian)(xian)(xian)的電(dian)平(ping)高低(di)來確設備(bei)(bei)是高速設備(bei)(bei)還是全速設備(bei)(bei)。
1.2 USB數據傳輸通道
USB主機與(yu)USB設備由很多端(duan)點構成(cheng),它們之間通過端(duan)點進行通訊。通過設置與(yu)些端(duan)點相對應的寄存器,可(ke)以為這些端(duan)點分(fen)配唯一的地址(由端(duan)點號和傳輸(shu)(shu)方(fang)向組成(cheng))。USB總線支持(chi)四種傳輸(shu)(shu)類型(xing),他們分(fen)別是(shi)控制傳輸(shu)(shu)、同步傳輸(shu)(shu)、中斷傳輸(shu)(shu)、批量傳輸(shu)(shu)。端(duan)點O只支持(chi)控制傳輸(shu)(shu)。
1.3 USB總線枚舉
USB總線枚舉(ju)就是當USB設(she)備(bei)連接到(dao)USB主(zhu)機時,主(zhu)機通(tong)過缺省管道(dao)以(yi)控制傳輸方式來獲取USB設(she)備(bei)發來的(de)設(she)備(bei)描(miao)述(shu)符、配置描(miao)述(shu)符、接口描(miao)述(shu)符、端(duan)點描(miao)述(shu)符信息,并根據這(zhe)些描(miao)述(shu)相(xiang)關內容(rong)對USB設(she)備(bei)進行相(xiang)應(ying)的(de)配置。
2 Linux USB 驅動程序
在Linux系統(tong)中,USB驅(qu)(qu)(qu)動程(cheng)序可(ke)以(yi)分為USB Host驅(qu)(qu)(qu)動程(cheng)序和USB Device驅(qu)(qu)(qu)動程(cheng)序。Linux USB Host驅(qu)(qu)(qu)動程(cheng)序和USB Device驅(qu)(qu)(qu)動程(cheng)序總(zong)體架構如圖1所示(shi)。
從圖1可以(yi)知,在Linux USB Host中(zhong),USB控(kong)(kong)制(zhi)器(qi)驅(qu)動(dong)(dong)(dong)是運行(xing)在USB 控(kong)(kong)制(zhi)器(qi)硬件上面的(de)的(de)驅(qu)動(dong)(dong)(dong)動(dong)(dong)(dong)程(cheng)(cheng)序(xu)。該(gai)驅(qu)動(dong)(dong)(dong)實現(xian)了對USB 控(kong)(kong)制(zhi)器(qi)硬件進行(xing)控(kong)(kong)制(zhi),一般稱(cheng)為USB固件驅(qu)動(dong)(dong)(dong)程(cheng)(cheng)序(xu)。USB設備(bei)驅(qu)動(dong)(dong)(dong)處(chu)于USB驅(qu)動(dong)(dong)(dong)的(de)最(zui)頂層(ceng),它主(zhu)要實現(xian)USB設備(bei)如何與(yu)主(zhu)機進行(xing)通(tong)信。處(chu)在USB主(zhu)機控(kong)(kong)制(zhi)器(qi)驅(qu)動(dong)(dong)(dong)與(yu)USB設備(bei)驅(qu)動(dong)(dong)(dong)之(zhi)間的(de)是USB核心(xin)層(ceng),起到驅(qu)動(dong)(dong)(dong)程(cheng)(cheng)序(xu)橋梁的(de)作用,該(gai)核心(xin)層(ceng)為USB主(zhu)機USB主(zhu)機控(kong)(kong)制(zhi)器(qi)驅(qu)動(dong)(dong)(dong)提供編(bian)程(cheng)(cheng)接口。
Linux系統中, USB Device驅動分為UDC驅動、Gadget API、Gadget驅動三個(ge)層(ceng)(ceng)次結構。UDC驅動處USB Device控(kong)制(zhi)(zhi)器(qi)硬件(jian)之上(shang),該驅動程(cheng)(cheng)序控(kong)制(zhi)(zhi)USB控(kong)制(zhi)(zhi)器(qi)硬件(jian)工作,同時向上(shang)層(ceng)(ceng)提(ti)供操作USB控(kong)制(zhi)(zhi)器(qi)硬件(jian)的回(hui)調函數(shu)。處在中間層(ceng)(ceng)的是Gadget API層(ceng)(ceng),該API向下層(ceng)(ceng)和(he)上(shang)層(ceng)(ceng)提(ti)供統一(yi)的編(bian)(bian)程(cheng)(cheng)接函數(shu)的封裝。Gadget驅動程(cheng)(cheng)序完成設備(bei)功能的實現。通過(guo)編(bian)(bian)寫(xie)不同Gadget驅動程(cheng)(cheng)序可以使設備(bei)具有不同的功能。
3 S3C2440 USB Device驅(qu)動
3.1 S3C2440 USB接口特(te)性
S3C2440嵌入式微(wei)處(chu)理器集成了一個設備(bei)控(kong)制器。該設備(bei)控(kong)制器具(ju)有以(yi)下特征:
1) 完(wan)全兼容USB1.1的協(xie)議(yi)。設(she)備全速運行時可(ke)達(da)到了12Mb/s。
2) 支持控制、中斷和批(pi)量(liang)傳(chuan)(chuan)輸,批(pi)量(liang)傳(chuan)(chuan)輸支持DMA接口。
3) 自(zi)帶5個的端(duan)(duan)點。端(duan)(duan)點EP0帶有(you)16byte的FIFO,該(gai)端(duan)(duan)點為雙(shuang)向的控制(zhi)端(duan)(duan)點,其余4個端(duan)(duan)點都帶有(you)128字節(jie)輸(shu)(shu)入/輸(shu)(shu)出的FIFO(異步雙(shuang)端(duan)(duan)口RAM)的,支(zhi)持(chi)中(zhong)斷或(huo)DMA批(pi)量傳輸(shu)(shu)。
3.2 S3C2440 USB Device驅動(dong)程序設計
一個完整(zheng)的(de)(de)(de)S3C2440 USB Device驅(qu)(qu)動(dong)(dong)程序由(you)S3C2440_UDA驅(qu)(qu)動(dong)(dong)和gadget驅(qu)(qu)動(dong)(dong)兩部分(fen)構成。S3C2440_UDA驅(qu)(qu)動(dong)(dong)是(shi)用(yong)來控制(zhi)S3C2440的(de)(de)(de)USB Device硬件(jian)控制(zhi)器器,并把對硬件(jian)控制(zhi)操作抽(chou)象為函(han)數接口(kou)供上層調用(yong)。USB gedget驅(qu)(qu)動(dong)(dong)程序運行在(zai)S3C2440_UDA驅(qu)(qu)動(dong)(dong)程序之上的(de)(de)(de),不同(tong)的(de)(de)(de)gedget驅(qu)(qu)動(dong)(dong)程序使該設(she)備具有不同(tong)的(de)(de)(de)功能。
Linux gadget驅動(dong)程序主要涉及(ji)到2個重要的(de)結構體(ti)usb_gadget_driver和struct file_operations結構。其中(zhong)usb_gadget_driver結構體(ti)包括bind、setup、disconnect等一(yi)些函數(shu)。Linux Gadget提供(gong)usb_gadget_register_driver函數(shu)對Gaget驅動(dong)進(jin)行注冊。當Gadget驅動(dong)被注冊后,Linux內(nei)核就會調用結構體(ti)usb_gadget_driver中(zhong)的(de)bind函數(shu)把(ba)Gadget驅動(dong)與UDA驅動(dong)進(jin)行綁定,這樣就可以在Gadget驅動(dong)中(zhong)使用UDA提供(gong)的(de)統一(yi)接口函數(shu)。
bind函(han)數(shu)中需(xu)要完成(cheng)以下(xia)工作:
1) 使用usb_ep_autoconfig函數申請以后用到(dao)的(de)傳輸端點。
2) 通過usb_ep_alloc_request函數(shu)為(wei)Gadget驅動(dong)分(fen)配一(yi)個請求。
3) 通過調(diao)用register_chrdev_region注冊設備驅動程序。
Bind函數(shu)完成這后當有USB Host 向USB設備發(fa)(fa)出請(qing)求時,Linux系統將調用(yong)setup函數(shu)來(lai)響應請(qing)求。Setup函數(shu)把設備的(de)設備描(miao)述(shu)符(fu)、配置描(miao)述(shu)符(fu)、接(jie)口描(miao)述(shu)符(fu)以及以后需要使用(yong)的(de)幾個端點描(miao)述(shu)符(fu)發(fa)(fa)送給(gei)USB Host,這些(xie)配置信(xin)息的(de)發(fa)(fa)送都(dou)是(shi)通(tong)過usb_ep_queue函數(shu)來(lai)完的(de)。
struct file_operations結(jie)(jie)構(gou)(gou)(gou)包(bao)含有open、read、write等函數。通過(guo)該結(jie)(jie)構(gou)(gou)(gou)體定義(yi)的變量被(bei)register_chrdev_region函數注(zhu)冊(ce)后該設備(bei)就可以像(xiang)字(zi)符設備(bei)那樣使有了。該結(jie)(jie)構(gou)(gou)(gou)中的一(yi)些函數完成的功能(neng)如(ru)下:
1) open函(han)數通過init_waitqueue_head完成等待隊列初始化。
2) read函(han)(han)數通(tong)(tong)過alloc_ep_req函(han)(han)數分配一個(ge)讀(du)請(qing)求(qiu)(qiu)變量,并為該變量中的complete設(she)置一個(ge)請(qing)求(qiu)(qiu)完成(cheng)函(han)(han)數,調(diao)用(yong)usb_ep_queue函(han)(han)數向(xiang)端(duan)點提(ti)交I/O讀(du)請(qing)求(qiu)(qiu)。當內核從USB Device讀(du)到數據時就會(hui)調(diao)有剛才的完成(cheng)函(han)(han)數。在(zai)完成(cheng)讀(du)數據之前(qian)可以通(tong)(tong)過add_wait_queue和(he)schedule()函(han)(han)數讓(rang)進(jin)程掛(gua)起(qi)(qi),在(zai)完成(cheng)函(han)(han)數中喚(huan)醒掛(gua)起(qi)(qi)的進(jin)程。
3) write函數(shu)(shu)通(tong)過(guo)alloc_ep_req函數(shu)(shu)分(fen)配(pei)一個寫(xie)(xie)請(qing)求變(bian)量,并(bing)為該變(bian)量中(zhong)的complete設置一個請(qing)求,調用usb_ep_queue函數(shu)(shu)向(xiang)端點提交I/O寫(xie)(xie)請(qing)求。當內核向(xiang)USB Device寫(xie)(xie)完數(shu)(shu)據時就會調有剛才的完成(cheng)函數(shu)(shu)。在完成(cheng)寫(xie)(xie)數(shu)(shu)據之前可以通(tong)過(guo)add_wait_queue和chedule()函數(shu)(shu)讓進程掛(gua)起,在完成(cheng)函數(shu)(shu)中(zhong)喚醒掛(gua)起的進程。
至(zhi)此(ci)整(zheng)個驅動(dong)程序就設計(ji)完成了,圖2為USB Host 與 USB Device 通信測試效果。
4 結束語
USB Device 為(wei)眾多電子產(chan)品提供了(le)一(yi)個(ge)與(yu)PC信息交互的更好的方案。本文通過(guo)對USB協議介(jie)紹,以及對Linux下USB驅(qu)(qu)動(dong)程(cheng)序進行分析,在此基礎(chu)上實現(xian)了(le)USB Device驅(qu)(qu)動(dong)程(cheng)序進行設計(ji)(ji)。實踐表明該設計(ji)(ji)是可行的。
參考文獻:
[1] 馮(feng)國進.嵌入式Linux驅動程序設計從入門到精(jing)通[M]北京:清華大學出版(ban)社,2008.
[2] 薛園園.USB應用開發(fa)技術大(da)全[M].北京:人民郵電出版社(she),2007.
[3] 劉少峰,韋克平(ping).USB軟件系統的開發[J].計算機應用研究,2002,19(30).
[4] 于(yu)明,范書瑞,曾祥燁(ye).ARM9嵌人式系統(tong)設(she)計與開發教程(cheng)[M].北京:電子(zi)工業出版社,2006.
篇4
首先找到我(wo)們電(dian)腦上(shang)的此(ci)電(dian)腦或者計算機,鼠標右擊彈出菜(cai)單(dan)選(xuan)擇管(guan)理(li)。
進入管(guan)(guan)理的頁面之后我們找到設備管(guan)(guan)理器。
在(zai)設備管理器下我(wo)(wo)們找到一(yi)個手(shou)機驅動(dong)的(de)標識,如果這里安(an)裝(zhuang)過了我(wo)(wo)們只需要自動(dong)更新一(yi)下即可(ke),
如果沒(mei)有(you)安裝的(de)話我們(men)使(shi)用(yong)數據線連接電(dian)腦查看(kan)我們(men)的(de)磁(ci)盤有(you)沒(mei)有(you)手機磁(ci)盤。
都沒(mei)有的話我們(men)需要找到手(shou)(shou)機(ji)品牌官網,輸(shu)入自己的手(shou)(shou)機(ji)型號。
篇5
關鍵(jian)詞:VxWorks;USB設備驅(qu)動;管道(dao);回調(diao)
中圖分類號:TP316文獻標(biao)識碼:A文章(zhang)編號: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公司(si)開發(fa)的(de)具有工(gong)業領導地(di)位的(de)高(gao)性(xing)能實(shi)時操作系統(Real Time Operation System, RTOS)內核。VxWorks5.5實(shi)現了USB1.1協(xie)議棧。圖1提供一個VxWorks下USB主驅動棧的(de)簡單結構(gou)。
在(zai)(zai)棧的(de)(de)(de)最(zui)低層是(shi)USB主控(kong)制(zhi)(zhi)(zhi)器(qi)(USB Host Controller, HC),這(zhe)是(shi)主系(xi)統中(zhong)控(kong)制(zhi)(zhi)(zhi)每一個(ge)USB設(she)備的(de)(de)(de)硬件。在(zai)(zai)主控(kong)制(zhi)(zhi)(zhi)器(qi)上(shang)層是(shi)一個(ge)與(yu)硬件獨立(li)的(de)(de)(de)主控(kong)制(zhi)(zhi)(zhi)器(qi)驅動(USB Host Controller Driver,HCD)。USBD是(shi)在(zai)(zai)HCD之上(shang)的(de)(de)(de)與(yu)硬件獨立(li)的(de)(de)(de)模(mo)塊,USBD管理(li)(li)每一個(ge)與(yu)主機相連的(de)(de)(de)設(she)備,向高層提(ti)供可與(yu)USB設(she)備通信的(de)(de)(de)路徑,USBD實現(xian)了USB總(zong)線(xian)枚舉、總(zong)線(xian)帶寬分配、傳輸控(kong)制(zhi)(zhi)(zhi)等操(cao)作。在(zai)(zai)棧的(de)(de)(de)頂層是(shi)USB Client 模(mo)塊,一般是(shi)特定的(de)(de)(de)USB Class Driver,負責管理(li)(li)與(yu)USB主機連接的(de)(de)(de)不同類型(xing)的(de)(de)(de)設(she)備。用戶自(zi)己的(de)(de)(de)USB設(she)備驅動程序(xu)通常(chang)是(shi)在(zai)(zai)USBD這(zhe)一層上(shang)完成。
2 VxWorks下USB設備驅動(dong)詳解
2.1 驅動程序提(ti)供(gong)的函數
2.1.1 向應用(yong)程(cheng)序提供(gong)的接(jie)口函數
設備驅動程(cheng)序的(de)(de)主要作用是向(xiang)上層應用程(cheng)序屏蔽硬件,向(xiang)上層應用程(cheng)序提供(gong)統一的(de)(de)接口(kou)函數,驅動程(cheng)序一般(ban)需要實現的(de)(de)函數如(ru)表(biao)1所示。
圖(tu)1 USB主驅動棧結構
表1 驅(qu)動程序提供的(de)接口
usbMSCDevInit();這(zhe)是一(yi)個通用(yong)的初始化(hua)例(li)程(cheng),可(ke)以在BSP中調(diao)用(yong),也可(ke)以由應用(yong)程(cheng)序(xu)(xu)來(lai)調(diao)用(yong),但只能被調(diao)用(yong)一(yi)次,該例(li)程(cheng)初始化(hua)必須的數(shu)據(ju)結構,并向USBD注冊驅動(dong)程(cheng)序(xu)(xu)。USB設備與USB主控(kong)制(zhi)器之(zhi)間的所有(you)操作都通過USBD來(lai)完成(cheng),因此在調(diao)用(yong)usbMSCDevInit()之(zhi)前必須確(que)定USBD已(yi)經(jing)初始化(hua),在使用(yong)USB設備之(zhi)前也要(yao)確(que)保(bao)USB主控(kong)制(zhi)器已(yi)經(jing)掛接(jie)到USBD。
usbMSCDevCreate();這(zhe)是一個創(chuang)建設(she)備例(li)程(cheng),當有設(she)備接入時,回(hui)調函數usbMSCDevAttachCallback()調用(yong)該例(li)程(cheng)創(chuang)建一個邏輯設(she)備,當這(zhe)個例(li)程(cheng)被調用(yong)時必(bi)須在(zai)系(xi)統(tong)中存在(zai)一個實際的USB物理設(she)備。
usbMSCDevDestroy();從系統中刪除設備(bei)。首(shou)先釋放(fang)設備(bei)占有的資源,從設備(bei)鏈表中移除該設備(bei),同(tong)時調用usbdPipeDestroy()銷毀該設備(bei)與主機之間的通(tong)信管道,最(zui)后釋放(fang)設備(bei)結構體。
usbMSCDevShutDown();該例程(cheng)(cheng)卸載已(yi)注(zhu)冊的設備驅動程(cheng)(cheng)序,并回收(shou)所有已(yi)分配資(zi)源,包(bao)括刪除設備、回收(shou)信號量等。
2.1.2 兩個重(zhong)要的回調函數
在編寫(xie)USB設備驅(qu)動程序時,除了上(shang)述接(jie)口函數(shu)外,還需(xu)要編寫(xie)另外兩個重要的回(hui)調函數(shu):usbMSCDevAttachCallback()和usbMSCIrpCallback()。usbMSCDevAttachCallback()用于(yu)跟蹤設備的請(qing)求實現動態(tai)接(jie)入或刪除;usbMSCIrpCallback()是一(yi)個IRP callback,當每一(yi)個IRP執行完(wan)成(cheng)之后調用該回(hui)調函數(shu),實現IRP之間同步。
2.2 設備標識
在VxWorks中USB設(she)(she)(she)備(bei)(bei)(bei)用(yong)USBD_NODE_ID來(lai)(lai)唯一(yi)區別(bie),它是USBD用(yong)來(lai)(lai)跟蹤一(yi)個特定設(she)(she)(she)備(bei)(bei)(bei)的(de)(de)句柄,它與(yu)USB設(she)(she)(she)備(bei)(bei)(bei)的(de)(de)真正USB地址無關(guan)。這表明Client并不關(guan)心設(she)(she)(she)備(bei)(bei)(bei)是物理上與(yu)哪一(yi)個USB主控制器(qi)連(lian)接,應(ying)用(yong)為(wei)每個設(she)(she)(she)備(bei)(bei)(bei)抽象一(yi)個Node ID,使Client可以不用(yong)考慮(lv)物理設(she)(she)(she)備(bei)(bei)(bei)的(de)(de)連(lian)接細(xi)節以及(ji)USB地址分(fen)配。當一(yi)個Client通知有一(yi)個設(she)(she)(she)備(bei)(bei)(bei)連(lian)接或斷開時(shi),USBD經常(chang)通過(guo)Node Id來(lai)(lai)定位設(she)(she)(she)備(bei)(bei)(bei)。同樣,當USB設(she)(she)(she)備(bei)(bei)(bei)與(yu)USBD通信時(shi),它必須(xu)向USBD傳遞該(gai)設(she)(she)(she)備(bei)(bei)(bei)的(de)(de)Node Id。Node ID通常(chang)作為(wei)設(she)(she)(she)備(bei)(bei)(bei)結構體的(de)(de)一(yi)個重要成員。
2.3 回調(diao)(Callback)
USB操作(zuo)是嚴格遵守時(shi)序(xu)(xu)的,WindRiver USBD采用回(hui)調(diao)(diao)機制來解決(jue)時(shi)序(xu)(xu)問(wen)題。例如在(zai)USBD識別一(yi)(yi)(yi)個(ge)動態連(lian)接(jie)(jie)事件之后會激活一(yi)(yi)(yi)個(ge)動態attach callback操作(zuo),這是一(yi)(yi)(yi)個(ge)注冊(ce)到USBD的回(hui)調(diao)(diao)例程,回(hui)調(diao)(diao)函數會判斷當前(qian)的操作(zuo),如果是接(jie)(jie)入(USBD_DYNA_ATTACH),就會調(diao)(diao)用usbMSCDevCreate()來在(zai)當前(qian)的USB句(ju)柄上創建一(yi)(yi)(yi)個(ge)邏輯設(she)備(bei)結構體;如果是移出(USBD_DYNA_REMOVE)就會調(diao)(diao)用usbMSCDevDestroy()來刪除(chu)設(she)備(bei)。同(tong)樣,當USBD處理完成一(yi)(yi)(yi)個(ge)USB IRP之后,Client的一(yi)(yi)(yi)個(ge)IRP callback被激活,該回(hui)調(diao)(diao)例程是由Irp.userCallback域(yu)來指定。在(zai)IRP callback中(zhong)釋(shi)放IRP同(tong)步信號量。
2.4 數據傳輸
USB設備(bei)與(yu)主機(ji)(ji)之間是通過(guo)USB管(guan)道(dao)(dao)(dao)(dao)進行(xing)通信的(de)(de)。一(yi)旦Client配置完(wan)一(yi)個設備(bei),就(jiu)可以(yi)(yi)利用(yong)(yong)(yong)USBD提供的(de)(de)管(guan)道(dao)(dao)(dao)(dao)(pipe)傳輸(shu)功能與(yu)設備(bei)進行(xing)數(shu)據(ju)交換(huan)。管(guan)道(dao)(dao)(dao)(dao)是建(jian)(jian)立在(zai)USBD Client與(yu)設備(bei)特(te)定的(de)(de)endpoint之間的(de)(de)單向通道(dao)(dao)(dao)(dao)。調用(yong)(yong)(yong)usbdPipeCreate()函數(shu)創建(jian)(jian)一(yi)個管(guan)道(dao)(dao)(dao)(dao)后(hou)返回一(yi)個管(guan)道(dao)(dao)(dao)(dao)句(ju)柄(bing)USBD_PIPE_HANDLE,以(yi)(yi)后(hou)所(suo)有(you)的(de)(de)讀(du)寫操(cao)作都分別(bie)在(zai)各(ge)自(zi)的(de)(de)管(guan)道(dao)(dao)(dao)(dao)句(ju)柄(bing)上進行(xing)。管(guan)道(dao)(dao)(dao)(dao)在(zai)剛創建(jian)(jian)完(wan)后(hou)是處(chu)于(yu)終止(zhi)的(de)(de)狀態(tai),為了能有(you)效(xiao)使用(yong)(yong)(yong)它們,還必須(xu)用(yong)(yong)(yong)usbdFeatureClear()來清除該(gai)終止(zhi)狀態(tai)。每一(yi)個管(guan)道(dao)(dao)(dao)(dao)有(you)以(yi)(yi)下性質:USBD_NODE_ID、端點地址,管(guan)道(dao)(dao)(dao)(dao)類(lei)型(xing)、數(shu)據(ju)流方向、包的(de)(de)最(zui)大有(you)效(xiao)載荷(he)量、帶(dai)寬需求(qiu)等。對于(yu)塊傳輸(shu)沒有(you)帶(dai)寬限制(zhi)。VxWorks的(de)(de)USB驅(qu)動程序(xu)的(de)(de)各(ge)層驅(qu)動程序(xu)間通過(guo)IRP機(ji)(ji)制(zhi)進行(xing)通信,當有(you)數(shu)據(ju)傳輸(shu)請(qing)求(qiu)發生時,上層向下傳遞IRP。USBD得(de)到請(qing)求(qiu)后(hou),調用(yong)(yong)(yong)HCD接口,將IRP轉化為usb的(de)(de)傳輸(shu)。這就(jiu)需要提供一(yi)個特(te)殊(shu)的(de)(de)回調函數(shu)usbMSCIrpCallback(),當塊傳輸(shu)結(jie)束時調用(yong)(yong)(yong)該(gai)回調函數(shu)。以(yi)(yi)下是讀(du)設備(bei)的(de)(de)具體過(guo)程。
1) 創建(jian)設(she)備(bei)時創建(jian)out和in管道(dao):
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) 提交(jiao)outIrp:usbdTransfer (usbdHandle, outPipeHandle, &outIrp)。讀命令在outIrp.bfrList[0].pBfr域中。
5) 等待outIrp處理結束,結束調用usbMSCIrpCallback()釋放IRP同(tong)步(bu)信(xin)號量。
6) 構造USB_IRP inIrp請求包。
7) 提(ti)交inIrp:usbdTransfer (usbdHandle, inPipeHandle, &inIrp)。
8) 等待inIrp處理結束(shu),讀取的數據(ju)在inIrp.bfrList[0].pBfr域中。
2.5 多(duo)個(ge)設備管理
驅動程序(xu)用LIST_HEAD 來存儲多個(ge)(ge)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei),每(mei)個(ge)(ge)接入(ru)(ru)的(de)(de)USB設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)利用其(qi)(qi)LINK節點加(jia)入(ru)(ru)到LIST_HEAD鏈表(biao)(biao)(biao)當(dang)中;一(yi)個(ge)(ge)LINK節點包含三部分:linkFwd指針(zhen)、linkBack指針(zhen)和pStruct指針(zhen);其(qi)(qi)中pStruct指向(xiang)一(yi)個(ge)(ge)待連接的(de)(de)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)結(jie)構體。當(dang)有一(yi)個(ge)(ge)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)創(chuang)建完成時(shi)(shi)調(diao)用usbListLink()將該(gai)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)加(jia)入(ru)(ru)鏈表(biao)(biao)(biao),刪除設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)之前調(diao)用usbListUnlink()從鏈表(biao)(biao)(biao)中移出該(gai)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)。由(you)于USB設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)是用Node ID來唯一(yi)標識的(de)(de),在查找設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)的(de)(de)時(shi)(shi)需要利用usbListNext()來遍歷設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)鏈表(biao)(biao)(biao),直到某個(ge)(ge)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)的(de)(de)Node ID與特定(ding)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)的(de)(de)Node ID相匹配為止。在多個(ge)(ge)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)管理(li)時(shi)(shi),采(cai)用USBD_NODE_ID usbd_scan_id[DEVICE_NUM]數組來存放(fang)多個(ge)(ge)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)的(de)(de)Node ID,在對設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)進(jin)行(xing)讀寫時(shi)(shi)只需提供設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)的(de)(de)索(suo)引序(xu)號就可以(yi)直接得(de)到設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)Node ID,提高(gao)了對設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)的(de)(de)訪問速度。
3 VxWorks下(xia)LM9833驅動(dong)程(cheng)序(xu)實(shi)現
3.1 LM9833 USB接口(kou)簡介
LM9833掃描(miao)儀控制(zhi)(zhi)器(qi)在一(yi)個(ge)單獨的(de)(de)IC上可以提(ti)供一(yi)個(ge)完(wan)整的(de)(de)USB圖(tu)(tu)像掃描(miao)控制(zhi)(zhi)系統。它的(de)(de)USB接口提(ti)供4個(ge)USB端(duan)點(dian)(Control Endpoint,Interrupt Endpoint,Bulk In Endpoint和Bulk Out Endpoint),內部(bu)有00~7F個(ge)寄(ji)存器(qi),其(qi)(qi)中00寄(ji)存器(qi)是存放一(yi)個(ge)8bits的(de)(de)圖(tu)(tu)象數據(ju),其(qi)(qi)它分別(bie)為(wei)控制(zhi)(zhi)或狀(zhuang)態寄(ji)存器(qi)。通過向bulk out端(duan)點(dian)發送四(si)字(zi)(zi)節的(de)(de)讀(du)命(ming)令可以從bulk in端(duan)點(dian)讀(du)取這些寄(ji)存器(qi)的(de)(de)值,也可以向bulk out端(duan)點(dian)發送四(si)字(zi)(zi)節的(de)(de)寫(xie)命(ming)令加(jia)待寫(xie)數據(ju)完(wan)成寫(xie)寄(ji)存器(qi)。四(si)字(zi)(zi)節命(ming)令依次表示(shi):讀(du)寫(xie)模(mo)式(1字(zi)(zi)節)、起始地址(zhi)(1字(zi)(zi)節)、讀(du)寫(xie)長度(du)(2字(zi)(zi)節)。其(qi)(qi)中讀(du)寫(xie)模(mo)式bit0為(wei)0表示(shi)寫(xie),1表示(shi)讀(du);bit1為(wei)0表示(shi)非(fei)增模(mo)式,為(wei)1表示(shi)增模(mo)式,即讀(du)寫(xie)寄(ji)存器(qi)完(wan)成之后寄(ji)存器(qi)地址(zhi)加(jia)1。LM9833的(de)(de)工作過程就是通過讀(du)寫(xie)這些寄(ji)存器(qi)來完(wan)成的(de)(de)。
3.2 設備描述(shu)符結(jie)構(gou)
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;
設備描述符(fu)結構中包含了設備的一些重要信(xin)息(xi)和訪問該設備時的必(bi)須資源,如Node ID、IN/OUT管(guan)道(dao)、IN/OUT IRP等等。
3.3 注冊設備(bei)(LM9833)驅動程(cheng)序
注(zhu)冊驅動程序一般包(bao)含兩大步:與USBD建立連接和注(zhu)冊attach callback。以下是注(zhu)冊LM9833驅動程序的源(yuan)代(dai)碼。
#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()調(diao)(diao)(diao)用(yong)usbdClientRegister()向USBD注冊一個(ge)(ge)名為(wei)SCAN_CLASS的Client,同時調(diao)(diao)(diao)用(yong)usbdDynamicAttachRegister()向USBD注冊一個(ge)(ge)回(hui)調(diao)(diao)(diao)例程(cheng)usbScanDevAttachCallback (),跟蹤該Client請求,當設備動(dong)態地接入或移出系統時會自動(dong)地調(diao)(diao)(diao)用(yong)該回(hui)調(diao)(diao)(diao)函數。一個(ge)(ge)Client在利用(yong)usbdDynamicAttachRegister()進行注冊時只(zhi)對特定(ding)的class、subclass、protocol感興趣(qu)。在成功注冊Client后,USBD返回(hui)一個(ge)(ge)Client句柄(bing)(USBD_CLIENT_HANDLE),以后對USBD的調(diao)(diao)(diao)用(yong)都會用(yong)到這個(ge)(ge)句柄(bing)。Attach callback 如下。
LOCAL VOID usbScanDevAttachCallback
(
USBD_NODE_ID nodeId,
UINT16 attachAction,
UINT16 configuration,
UINT16 interface,
UINT16 deviceClass,
UINT16 deviceSubClass,
UINT16 deviceProtocol
)
該回調函數主(zhu)要(yao)響應外部設(she)備(bei)的動作,實現USB設(she)備(bei)的動態(tai)接入和移除。
3.4 創建設備
創建設備(bei)函數(shu)如(ru)下:
LOCAL STATUS usbScanPhysDevCreate(USBD_NODE_ID nodeId, UINT16 configuration, UINT16 interface)
當接(jie)入設(she)(she)(she)備(bei)(bei)時激活usbScanDevAttachCallback()操作(zuo),回調函數會根(gen)據(ju)接(jie)入(USBD_DYNA_ATTACH)動作(zuo)調用usbScanPhysDevCreate()創(chuang)(chuang)建一個(ge)邏輯設(she)(she)(she)備(bei)(bei),在創(chuang)(chuang)建設(she)(she)(she)備(bei)(bei)的(de)同時,創(chuang)(chuang)建設(she)(she)(she)備(bei)(bei)與USB主(zhu)機(ji)之(zhi)(zhi)間(jian)通(tong)信的(de)管(guan)道(dao)(dao)(pipe)。管(guan)道(dao)(dao)是(shi)建立在USB設(she)(she)(she)備(bei)(bei)端(duan)點(dian)(endpoint)之(zhi)(zhi)上,是(shi)主(zhu)機(ji)與設(she)(she)(she)備(bei)(bei)之(zhi)(zhi)間(jian)數據(ju)傳輸(shu)的(de)單(dan)向通(tong)道(dao)(dao)。設(she)(she)(she)備(bei)(bei)與主(zhu)機(ji)之(zhi)(zhi)間(jian)數據(ju)傳輸(shu)管(guan)道(dao)(dao)是(shi)建立在批量(liang)端(duan)點(dian)(bulk endpoint)之(zhi)(zhi)上,有BULK_IN和BULK_OUT兩個(ge)端(duan)點(dian),從而建立雙向的(de)數據(ju)通(tong)路(lu)。最(zui)后將該設(she)(she)(she)備(bei)(bei)加入設(she)(she)(she)備(bei)(bei)鏈表,進行多個(ge)設(she)(she)(she)備(bei)(bei)的(de)管(guan)理。創(chuang)(chuang)建設(she)(she)(she)備(bei)(bei)流程如圖2所示。
圖2 創(chuang)建設(she)備流程
3.5 讀寫設備
對設備(bei)進行讀(du)(du)寫時,首(shou)先(xian)需要將讀(du)(du)寫函(han)數轉換(huan)成設備(bei)能夠識別(bie)的(de)(de)(de)命(ming)令(ling),對于(yu)LM9833來說,需將讀(du)(du)寫函(han)數轉換(huan)成LM9833所(suo)能識別(bie)的(de)(de)(de)四(si)(si)字(zi)(zi)節(jie)讀(du)(du)寫命(ming)令(ling),讀(du)(du)寫時將這(zhe)四(si)(si)字(zi)(zi)節(jie)的(de)(de)(de)命(ming)令(ling)置于(yu)IRP包數據(ju)(ju)域的(de)(de)(de)最前端,這(zhe)樣(yang)到數據(ju)(ju)到達設備(bei)時首(shou)先(xian)接(jie)收到的(de)(de)(de)是四(si)(si)個字(zi)(zi)節(jie)的(de)(de)(de)命(ming)令(ling),LM9833會根(gen)據(ju)(ju)這(zhe)四(si)(si)個字(zi)(zi)節(jie)的(de)(de)(de)命(ming)令(ling)完成相(xiang)應的(de)(de)(de)功能。讀(du)(du)寫函(han)數原型(xing)為:
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的一個讀寫控制流程(cheng)(cheng)如(ru)圖3所示(shi),查(cha)找設備流程(cheng)(cheng)如(ru)圖4所示(shi)。
圖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
引言
近年來(lai)電(dian)(dian)力(li)行(xing)(xing)業為(wei)(wei)了(le)快速部(bu)(bu)署變電(dian)(dian)站(zhan),采用了(le)建造整(zheng)體(ti)變電(dian)(dian)所(suo)(suo)的(de)(de)(de)(de)(de)方(fang)法:在生產基(ji)地將變電(dian)(dian)站(zhan)的(de)(de)(de)(de)(de)內部(bu)(bu)設(she)(she)(she)(she)備安裝、調(diao)(diao)試(shi)(shi)(shi)完(wan)成,只留(liu)下(xia)(xia)與外界的(de)(de)(de)(de)(de)接口(kou),整(zheng)體(ti)運到變電(dian)(dian)站(zhan)所(suo)(suo)在地后進行(xing)(xing)安裝和簡(jian)單調(diao)(diao)試(shi)(shi)(shi)即可(ke)投入運行(xing)(xing)。其內部(bu)(bu)設(she)(she)(she)(she)備通過CAN總線進行(xing)(xing)通信,系統原有的(de)(de)(de)(de)(de)監控(kong)軟件基(ji)于DOS系統,維護調(diao)(diao)試(shi)(shi)(shi)比較(jiao)困難(nan),因此想要(yao)尋求更(geng)方(fang)便(bian)、友好的(de)(de)(de)(de)(de)系統支持(chi)。經過比較(jiao),嵌入式操作(zuo)系統市場上風頭正勁的(de)(de)(de)(de)(de)Windows CE .NET成為(wei)(wei)最(zui)終選(xuan)擇。微軟的(de)(de)(de)(de)(de)最(zui)新產品Windows CE.NET提(ti)供(gong)了(le)端(duan)對端(duan)的(de)(de)(de)(de)(de)開發、調(diao)(diao)試(shi)(shi)(shi)手段,可(ke)以(yi)不拆卸設(she)(she)(she)(she)備的(de)(de)(de)(de)(de)情況下(xia)(xia)通過Telnet登錄到WindowsCE上進行(xing)(xing)調(diao)(diao)試(shi)(shi)(shi)和維護,其系統本身為(wei)(wei)嵌入式市場進行(xing)(xing)重新設(she)(she)(she)(she)計,包括創建一個基(ji)于WindowsCE的(de)(de)(de)(de)(de)定制(zhi)設(she)(she)(she)(she)備所(suo)(suo)需(xu)(xu)的(de)(de)(de)(de)(de)一切。這樣就需(xu)(xu)要(yao)將原來(lai)DOS下(xia)(xia)的(de)(de)(de)(de)(de)程序移植(zhi)到WindowsCE.NET下(xia)(xia),但(dan)是各個硬件廠商目前(qian)還沒有提(ti)供(gong)CAN通信卡在Windows CE.NET下(xia)(xia)的(de)(de)(de)(de)(de)驅(qu)動,所(suo)(suo)以(yi)開發Windows CE.NET下(xia)(xia)的(de)(de)(de)(de)(de)CAN卡驅(qu)動成為(wei)(wei)項目推行(xing)(xing)中的(de)(de)(de)(de)(de)關鍵(jian)一環。
本文主要(yao)針對研華的(de)雙口CAN卡PCM3680進行分(fen)析,介紹在WindowsCE.ENT系統下進行底層設備驅動開發(fa)的(de)方法(fa)并提供CAN通信(xin)的(de)實例。
1 CAN總(zong)線(xian)通信協議(yi)及CAN通信卡介紹
CAN總(zong)線是德國(guo)Bosch公司(si)20世(shi)紀80年代初為解(jie)決現(xian)代汽車中(zhong)眾多的(de)控制與(yu)測試儀器之間的(de)數(shu)(shu)(shu)據(ju)交換而開的(de)一種(zhong)串行數(shu)(shu)(shu)據(ju)通信協議。它是一種(zhong)多主總(zong)線,廢(fei)除了傳統的(de)站地址編碼,而代之以對通信數(shu)(shu)(shu)據(ju)塊(kuai)進行編碼。這種(zhong)方法使網絡內節點個數(shu)(shu)(shu)在理(li)論(lun)上不(bu)受限制,擴(kuo)展格式(shi)中(zhong)的(de)29位的(de)標識碼便可以定(ding)義2 29個不(bu)同的(de)數(shu)(shu)(shu)據(ju)塊(kuai)。
在(zai)本項目中(zhong)(zhong)使用(yong)(yong)(yong)的(de)(de)(de)(de)是研華的(de)(de)(de)(de)PCM3680,這是一塊嵌(qian)入式PC104的(de)(de)(de)(de)雙(shuang)口(kou)CAN總線通信卡(ka);CAN控制器采用(yong)(yong)(yong)Philips的(de)(de)(de)(de)獨立CAN控制器SJA1000芯片;CAN收發器采用(yong)(yong)(yong)Philips的(de)(de)(de)(de)P82C250,可以(yi)同時操(cao)作兩個CAN網絡,提(ti)供(gong)(gong)高達1Mb/s的(de)(de)(de)(de)傳輸速度。PCM3680支持很寬的(de)(de)(de)(de)中(zhong)(zhong)斷范圍:中(zhong)(zhong)斷3、4、5、6、7、9、10、11、12、15,同時1000V的(de)(de)(de)(de)光電隔離提(ti)供(gong)(gong)系統高可靠(kao)性(xing)。在(zai)CAN卡(ka)通信中(zhong)(zhong),要用(yong)(yong)(yong)到CAN控制器中(zhong)(zhong)的(de)(de)(de)(de)很多寄存器,各個寄存器的(de)(de)(de)(de)含義和(he)作用(yong)(yong)(yong)可以(yi)參考控制芯片的(de)(de)(de)(de)說明書。圖1列出驅動程序設計中(zhong)(zhong)用(yong)(yong)(yong)到最主(zhu)要的(de)(de)(de)(de)寄存器結構(gou)。
2 CAN卡驅動底層(ceng)函(han)數設(she)計
本方案設計(ji)CAN驅動是(shi)(shi)放在Windows CE操作系統(tong)的內(nei)核(he)下(xia)層,位(wei)于OEM adaptation layer(OAL)層的一個真正(zheng)的驅動,而不是(shi)(shi)在主程序中的串口操作。在Windows CE的設備管理器可以(yi)看到CAN1和(he)CAN2兩個端口,并且可以(yi)查看其(qi)(qi)工作的正(zheng)常與否和(he)對其(qi)(qi)進行配置。如:中斷號和(he)I/O地(di)址。
2.1 CAN卡寄存器讀(du)寫(xie)函(han)數
CAN卡的(de)(de)通(tong)(tong)信是(shi)通(tong)(tong)過操作(zuo)CAN卡上的(de)(de)CAN控(kong)制(zhi)器(qi)(qi)(qi)(qi)(qi)進(jin)行的(de)(de)。在(zai)CAN控(kong)制(zhi)器(qi)(qi)(qi)(qi)(qi)中(zhong)有很多寄(ji)(ji)(ji)存(cun)(cun)器(qi)(qi)(qi)(qi)(qi),如控(kong)制(zhi)寄(ji)(ji)(ji)存(cun)(cun)器(qi)(qi)(qi)(qi)(qi)、命令寄(ji)(ji)(ji)存(cun)(cun)器(qi)(qi)(qi)(qi)(qi)、狀態寄(ji)(ji)(ji)存(cun)(cun)器(qi)(qi)(qi)(qi)(qi)、中(zhong)斷(duan)寄(ji)(ji)(ji)存(cun)(cun)器(qi)(qi)(qi)(qi)(qi)等,通(tong)(tong)過讀寫這些(xie)寄(ji)(ji)(ji)存(cun)(cun)器(qi)(qi)(qi)(qi)(qi)中(zhong)的(de)(de)命令狀態字可以檢(jian)測和控(kong)制(zhi)CAN卡的(de)(de)行為。在(zai)Windows CE.NET下,通(tong)(tong)過調(diao)用(yong)DOK中(zhong)的(de)(de)API函(han)數HalTranslateBusAddress,將CAN卡分配的(de)(de)物(wu)理地(di)址映射為邏輯地(di)址。這樣(yang)各(ge)個(ge)寄(ji)(ji)(ji)存(cun)(cun)器(qi)(qi)(qi)(qi)(qi)對應的(de)(de)就(jiu)是(shi)CAN卡基地(di)址的(de)(de)偏移地(di)址,因此,對寄(ji)(ji)(ji)存(cun)(cun)器(qi)(qi)(qi)(qi)(qi)的(de)(de)讀寫就(jiu)轉化(hua)為對內存(cun)(cun)地(di)址的(de)(de)讀寫。下面是(shi)CAN卡寄(ji)(ji)(ji)存(cun)(cun)器(qi)(qi)(qi)(qi)(qi)的(de)(de)讀寫函(han)數:
*在偏移量為off的(de)地(di)址讀取(qu)一個字節(jie)的(de)數據inline BYTE CANR(LPCAN_HW_OPEN_INFO hCan,DWORD off)
{
return hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off];
*將一個字節數據(ju)寫到偏移量(liang)為off的地址中inline VOID CANW(LPCAN_HW_OPEN_INFO hCan,DWORD off,BYTE val)
{
hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off]=val;
}
參數LPCAN_HW_OPEN_INFO定義的(de)是CAN卡的(de)數據結構,其中成員lpMappeBaseAddr[0]表示的(de)是映射后基(ji)地址,lpMappedBaseAddr[1]就(jiu)是基(ji)地址+1的(de)地址,對應CAN卡的(de)寄存(cun)器是命令(ling)寄存(cun)器。通(tong)過上述兩個函數可操作CAN卡上的(de)所有寄存(cun)器。
2.2 CAN卡(ka)初始化
CAN卡(ka)的控制(zhi)器比較復雜,在通信前必須確認硬件信息正確性、初(chu)(chu)始(shi)化各寄存器。初(chu)(chu)始(shi)化函數的基本流程(cheng)如圖3所示。
第一步,檢(jian)查端(duan)口號和硬件信息的正確性,主要是(shi)CAN卡(ka)中斷號是(shi)否有效(xiao)。
第二(er)卡,設置CAN卡默認參數:
CanCardConfigInfo CAN_DEFAULT_SETTING=
{0X00,0XFF,0X03,0X1C};/*設置默認波(bo)特率為(wei)125Kbps*/
DWORD dwThreadID =0;
PHYSICAL_ADDRESS phyAddr={hwInfo->dwIOBaseAddr *16,0 };
第(di)三卡(ka)(ka),用WinCE API函(han)數LocalAlloc為CAN卡(ka)(ka)驅動中用到的數據結構分(fen)配緩沖區;通過HalTranslateBusAddress和MmMapIoSpace函(han)數映射I/O地址,提供直(zhi)接訪問(wen)設備的虛擬地址:
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;
如(ru)果分配內存或映射邏輯(ji)地址失敗,則退出(chu)初始(shi)化(hua)程序,CAN卡初始(shi)化(hua)失敗。
第四步,初始化(hua)讀寫屬性、共享模式(shi)、讀超(chao)時(shi)時(shi)間和(he)第二個CAN口的基地(di)址。
第五步(bu),創建CAN卡事(shi)件(jian)和數據(ju)接收事(shi)件(jian):hCan->lpCanHWInfo->hCanEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
hCan->lpCanHWInfo->hRecvMsgEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
第(di)六步,初始化中斷,如果(guo)CAN卡(ka)(ka)有(you)復位請(qing)求就退出初始化程(cheng)(cheng)序(xu)。設置好中斷后(hou)啟動數(shu)(shu)據接收線程(cheng)(cheng),設置線程(cheng)(cheng)優先級繼續線程(cheng)(cheng)處(chu)理;最(zui)后(hou)配置CAN卡(ka)(ka)參數(shu)(shu),進入(ru)正常運行狀(zhuang)態(tai)。
2.3 CAN卡信息發送
CAN卡的(de)(de)(de)(de)信息發(fa)送分為(wei)(wei)兩個步驟(zou)。在對CAN卡基本信息進行(xing)檢查(cha)后(hou),首先設(she)置發(fa)送緩沖(chong)的(de)(de)(de)(de)ID號(hao)(hao)(hao)(hao)。CAN標準(zhun)模式的(de)(de)(de)(de)ID號(hao)(hao)(hao)(hao)為(wei)(wei)11位(wei),偏(pian)移地(di)址10中(zhong)存(cun)放的(de)(de)(de)(de)是(shi)ID號(hao)(hao)(hao)(hao)的(de)(de)(de)(de)高(gao)(gao)8位(wei),偏(pian)移地(di)址11的(de)(de)(de)(de)高(gao)(gao)3位(wei)存(cun)放的(de)(de)(de)(de)是(shi)ID號(hao)(hao)(hao)(hao)的(de)(de)(de)(de)低3位(wei),剩(sheng)下5位(wei)分別是(shi)RTR位(wei)(遠程傳送請求位(wei))和(he)數(shu)(shu)據(ju)長(chang)度。通(tong)過CANW函(han)數(shu)(shu)將(jiang)處(chu)理后(hou)的(de)(de)(de)(de)數(shu)(shu)據(ju)寫入到(dao)相應的(de)(de)(de)(de)偏(pian)移地(di)址,設(she)置完(wan)相應的(de)(de)(de)(de)地(di)址數(shu)(shu)據(ju)后(hou),通(tong)過循環將(jiang)偏(pian)移地(di)址12~19的(de)(de)(de)(de)數(shu)(shu)據(ju)采(cai)集回來存(cun)到(dao)數(shu)(shu)組中(zhong)。然后(hou),設(she)置CAN卡的(de)(de)(de)(de)傳輸(shu)請求為(wei)(wei)允許并不斷(duan)偵(zhen)測狀態寄存(cun)器的(de)(de)(de)(de)變化,當(dang)傳輸(shu)緩沖(chong)滿標志(zhi)或傳輸(shu)結束標志(zhi)為(wei)(wei)1時通(tong)出程序,完(wan)成一次數(shu)(shu)據(ju)采(cai)集。傳輸(shu)緩沖(chong)區的(de)(de)(de)(de)寄存(cun)器如(ru)表1所(suo)列。
表1
ID號(hao)10ID.10ID.9ID.8ID.7ID.6ID.5ID.4ID.3RTR,數(shu)(shu)(shu)據(ju)(ju)(ju)(ju)長度(du)碼11ID.2ID.1ID.0RTRDLC.3DLC.2DLC.1DLC.0數(shu)(shu)(shu)據(ju)(ju)(ju)(ju)1~812~19數(shu)(shu)(shu)據(ju)(ju)(ju)(ju)數(shu)(shu)(shu)據(ju)(ju)(ju)(ju)數(shu)(shu)(shu)據(ju)(ju)(ju)(ju)數(shu)(shu)(shu)據(ju)(ju)(ju)(ju)數(shu)(shu)(shu)據(ju)(ju)(ju)(ju)數(shu)(shu)(shu)據(ju)(ju)(ju)(ju)數(shu)(shu)(shu)據(ju)(ju)(ju)(ju)數(shu)(shu)(shu)據(ju)(ju)(ju)(ju)表2
ID號20ID.10ID.9ID.8ID.7ID.6ID.5ID.4ID.3RTR,數(shu)(shu)據長度碼21ID.2ID.1ID.0RTRDLC.3DLC.2DLC.1DLC.0數(shu)(shu)據1~822~29數(shu)(shu)據數(shu)(shu)據數(shu)(shu)據數(shu)(shu)據數(shu)(shu)據數(shu)(shu)據數(shu)(shu)據數(shu)(shu)據CAN消息發送函數(shu)(shu)的實現如下:
BOOL CAN_SendMessage(LPCAN_HW_OPEN_INFO hCan,LPCanCardMessageBuflpMsg)
{
BOOL bSuc=FALSE;
ASSERT(hCan && lpMsg && lpMsg->dwMessageLen <=8); /*防錯處(chu)理*/
if(0= =(hCan->dwAccessCode & GENERIC_WRITE))
return FALSE;
:: EnterCriticalSection(&hCan->lpCanHWInfo->
TransmitCritSec); /*進(jin)入(ru)臨(lin)界區*/
BYTE byV=static_cast<BYTE>(1pMsg->dwMsgID>>3);
CANW(hCan,10,byV); /*設置ID值(zhi)高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]);
} /*采(cai)集數據*/
CANW(hCan,1,1);/*重置傳輸請求*/
while(TRUE)
{byV=CANR(hCan,2);
if(byV & 0X40) /*傳輸緩沖區(qu)滿,退出*/
{break;}
if(byV & 0X8){ /*傳輸結束,正確返(fan)回退出*/
bSuc = TRUE;
break;}
}
::LeaveCriticalSection(&hCan->lpCanHWInfo->TransmitCritSec); /*離(li)開臨界區*/
return bSuc;
}
2.4 CAN卡信(xin)息接收(shou)
CAN卡(ka)的信(xin)息接(jie)收(shou)是(shi)發送的逆過程(cheng),當接(jie)收(shou)緩(huan)(huan)沖區(qu)標志為1時,表(biao)示緩(huan)(huan)沖區(qu)已滿可以接(jie)收(shou)數據(ju),將數據(ju)接(jie)收(shou)到(dao)數組后釋放接(jie)收(shou)緩(huan)(huan)沖區(qu),然后對接(jie)收(shou)到(dao)的數據(ju)進行(xing)分(fen)解并(bing)存儲到(dao)CAN卡(ka)信(xin)息緩(huan)(huan)沖區(qu)的結(jie)構(gou)(gou)體。接(jie)收(shou)緩(huan)(huan)沖區(qu)的寄存器結(jie)構(gou)(gou)如(ru)表(biao)2所列。
CAN消息接收函數的實(shi)現(xian)如下:
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);/*將數據(ju)暫存到臨時緩沖區*/
CANW(hCan,1,4); /*釋放接收緩(huan)沖區*/
LpMsg->dwMsgID=recvBuf[0]<<3; /*取出ID的高8位*/
BYTE byV =recvBuf[1];
LpMsg->dwMsgID+=byV >>5;/*取出ID低(di)3位,然后(hou)和高(gao)8位合并*/
LpMsg->bRTR =byV &0x10?TRUE:/*返回RTR狀態*/
LpMsg->dwMessageLen = byV &0XF; /*返(fan)回(hui)數據長度(du)*/
……
}
else
{++hCan->lpCanHWInfo->dwErrorMsgCount;}/*沒有(you)收到數據,錯誤計數加1*/
::LeaveCriticalSection(&hCan->lpCanHWInfo->
ReceiveCritSec); /*離開臨界區(qu)*/
Return bSuc;
}
2.5 CAN卡(ka)事件處理
CAN卡事(shi)件處理函數是CAN卡驅動程序中很重要的部分。驅動設計要求具(ju)有(you)消(xiao)息通知的功能,當事(shi)件發(fa)生時(shi)及時(shi)捕獲事(shi)件并進行消(xiao)息處理。
下面是事件處理函(han)數的實現(xian):
staric DWORD WINAPI CAN_EventHanle(LPVOID lpParam)
{
ASSERT(lpParam);
LPCAN_HW_OPEN_INFO hCan=(LPCAN_HW_OPEN_INFO)lpParam;
CanCardMessageBuf bufMsg;
while(TEUE)
{ /*循環等待(dai)CAN卡消息產(chan)生,然(ran)后進行處理*/
::WaitForSingleObject(hCan->lpCanHWInfo->hCanEvent,0XFFFFFFFF);
if(hCan->lpCanHWInfo->bKillCanThread) break; /*若(ruo)CAN線(xian)程(cheng)已關閉(bi)則中斷*/
if(CAN_RecvMessage(hCan,&hufMsg)){ /*正確(que)接收數據(ju)后*/
CAN_RecvBufPush(hCan,&bufMsg);} /*將數據壓(ya)入(ru)緩沖*/
BYTE byV=CANR(hCan,3); /*將3號(hao)寄存(cun)器讀出(chu)然后(hou)立即寫入*/
CANW(hCan,3,byV);/*能夠獲(huo)取每(mei)次(ci)中斷*/
InterruptDone(hCan->lpCanHWInfo->lpCanObj->dwSysIrqt);
} /*本次中(zhong)斷(duan)(duan)結束,等待下次中(zhong)斷(duan)(duan)*/
return 0;
}
2.6 其它函數
為了(le)(le)提供(gong)更(geng)多的(de)功能(neng)和更(geng)方便地使(shi)用(yong)(yong)CAN卡(ka)(ka)進行通信(xin),在CAN卡(ka)(ka)驅(qu)動程序中還設計了(le)(le)一(yi)些函數如(ru)CAN_Config用(yong)(yong)CAN卡(ka)(ka)信(xin)息配置(zhi)、CAN_RecvBufPop用(yong)(yong)于(yu)處(chu)理接收緩沖區、CAN_Reset用(yong)(yong)于(yu)復位CAN卡(ka)(ka)、CheckHWInfo用(yong)(yong)于(yu)硬(ying)件信(xin)息檢查(cha)等。這些函數提供(gong)了(le)(le)對CAN通信(xin)卡(ka)(ka)的(de)設置(zhi)、檢查(cha)等功能(neng),在這里(li)不(bu)再詳述了(le)(le)。
3 CAN卡驅(qu)動封裝設計
CAN卡底層(ceng)驅動(dong)函數雖然功(gong)能(neng)完整,但是對(dui)于用(yong)(yong)(yong)戶使(shi)用(yong)(yong)(yong)比較復雜(za)并且一般用(yong)(yong)(yong)戶不需要了(le)解(jie)底層(ceng)實(shi)現的(de)(de)機制。為了(le)便于使(shi)用(yong)(yong)(yong),最后對(dui)CAN卡的(de)(de)驅動(dong)進(jin)行了(le)封(feng)裝(zhuang),提供(gong)CanOpenFile、CanSendMsg等五個函數用(yong)(yong)(yong)于CAN總線的(de)(de)通(tong)信,以動(dong)態(tai)連接庫(DLL)的(de)(de)形式提供(gong)給用(yong)(yong)(yong)戶調用(yong)(yong)(yong)。封(feng)裝(zhuang)函數及功(gong)能(neng)如下:
*CanOpenFile;初始化并打開CAN卡的一個端口。
*CanCloseFile;關閉由CanOpenFile打開的CAN卡端口(kou)。
*CanRecvMsg;接收CAN卡數據(ju),打開CAN卡時必(bi)須(xu)具有GENERIC_READ權(quan)限(xian)。
*CanSendMsg;通過CAN卡(ka)發(fa)送數據。打開CAN卡(ka)時(shi)必須具有GENERIC_WRITE權限。
*CanIOControl;設置(zhi)或獲(huo)取CAN卡I/O參(can)數(shu)支持的I/O控制包括:IOCTL_CAN_CONFIG,IOCTL_CAN_RESET,IOCTL_CAN_TIMEOUT,IOCTL_CAN_SENDREADY,IOCTL_CAN_RECVREADY。
下面是CanSendMsg函(han)數實(shi)現的代碼:
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);
該(gai)函數(shu)就是通過封(feng)裝(zhuang)CAN卡的底層驅動函數(shu)SendMessage來(lai)實現的,這樣將功(gong)能集(ji)中的五個函數(shu)更方便(bian)了用(yong)戶(hu)使用(yong)。
結語
篇7
通信卡的硬件設計
1 通信卡(ka)的主要特點
通(tong)(tong)信卡(ka)(ka)(ka)的(de)(de)硬(ying)件設(she)計目的(de)(de)是智能化通(tong)(tong)信:在卡(ka)(ka)(ka)上具有4個DMA通(tong)(tong)道及相應的(de)(de)數(shu)(shu)據(ju)緩沖存儲區(qu)。在數(shu)(shu)據(ju)的(de)(de)接(jie)(jie)收(shou)過(guo)(guo)程中,通(tong)(tong)信卡(ka)(ka)(ka)會自(zi)動接(jie)(jie)收(shou)幀數(shu)(shu)據(ju),判別幀長(chang)度,在幀尾(wei)將接(jie)(jie)收(shou)到的(de)(de)幀數(shu)(shu)據(ju)提(ti)交系(xi)統。在發送(song)數(shu)(shu)據(ju)過(guo)(guo)程中,系(xi)統只須把發送(song)的(de)(de)數(shu)(shu)據(ju)提(ti)交給本卡(ka)(ka)(ka),具體的(de)(de)發送(song)過(guo)(guo)程由該(gai)卡(ka)(ka)(ka)自(zi)行完成,不因多路(lu)通(tong)(tong)信而(er)使主(zhu)機增加(jia)開銷(xiao)。該(gai)卡(ka)(ka)(ka)有內/外時鐘兩(liang)種(zhong)工作方式,近距離(li)可(ke)省去調制(zhi)解(jie)調器(qi),波(bo)特率為600b/s-64Kb/s,提(ti)供2路(lu)符合RS-232/CCITT V.24和RS-422A標準的(de)(de)接(jie)(jie)口(kou)信號(hao)。
2 通(tong)信卡的電路設計
通(tong)信卡組(zu)成(cheng)框圖如圖1所示。其主要(yao)由(you)DMA控(kong)制器(qi)、總線(xian)競爭仲裁器(qi)、串行通(tong)信控(kong)制器(qi)、數(shu)據緩沖存儲器(qi)SRAM、存儲器(qi)I/O映像(xiang)和物理地址產(chan)生(sheng)器(qi)、總線(xian)接(jie)(jie)口(kou)及防護(hu)、波特率(lv)產(chan)生(sheng)器(qi)、接(jie)(jie)口(kou)電(dian)路(lu)等單元電(dian)路(lu)組(zu)成(cheng)。
DMA控制(zhi)器(qi)(qi)(qi)作為通(tong)信(xin)(xin)卡(ka)(ka)(ka)(ka)的(de)(de)(de)主(zhu)(zhu)設備(bei),控制(zhi)卡(ka)(ka)(ka)(ka)上的(de)(de)(de)數據(ju)接(jie)收和發(fa)(fa)(fa)送(song)(song)(來自通(tong)信(xin)(xin)控制(zhi)器(qi)(qi)(qi)和CPU),并(bing)負責仲(zhong)裁(cai)優先權。由于在(zai)(zai)進(jin)行數據(ju)通(tong)信(xin)(xin)時(shi),允(yun)許主(zhu)(zhu)機(ji)(ji)(ji)(ji)(ji)CPU訪問(wen)本卡(ka)(ka)(ka)(ka)SRAM,且主(zhu)(zhu)機(ji)(ji)(ji)(ji)(ji)對其中(zhong)(zhong)某一路發(fa)(fa)(fa)控制(zhi)命令時(shi),不(bu)影響(xiang)其余三路通(tong)信(xin)(xin),這(zhe)樣將(jiang)會使(shi)主(zhu)(zhu)機(ji)(ji)(ji)(ji)(ji)CPU與本卡(ka)(ka)(ka)(ka)DMA競爭本卡(ka)(ka)(ka)(ka)總(zong)線(xian)控制(zhi)權。而總(zong)線(xian)上沒有給出主(zhu)(zhu)機(ji)(ji)(ji)(ji)(ji)CPU指(zhi)令排(pai)隊(dui)狀(zhuang)(zhuang)態序列,故不(bu)能(neng)(neng)直(zhi)接(jie)設計多主(zhu)(zhu)競爭,因而在(zai)(zai)本卡(ka)(ka)(ka)(ka)總(zong)線(xian)上用(yong)門陣列設計了(le)一個(ge)狀(zhuang)(zhuang)態機(ji)(ji)(ji)(ji)(ji),不(bu)斷(duan)地監(jian)視總(zong)線(xian)爭用(yong)情(qing)況(kuang),完成本卡(ka)(ka)(ka)(ka)總(zong)線(xian)競爭、仲(zhong)裁(cai)功能(neng)(neng)。完成HDLC規程(cheng)的(de)(de)(de)串行通(tong)信(xin)(xin)的(de)(de)(de)器(qi)(qi)(qi)件是INTEL 8274多規程(cheng)串行控制(zhi)器(qi)(qi)(qi),它能(neng)(neng)完成2個(ge)獨立(li)的(de)(de)(de)串行接(jie)收/發(fa)(fa)(fa)送(song)(song)全雙工(gong)通(tong)信(xin)(xin)。為了(le)使(shi)4個(ge)信(xin)(xin)道在(zai)(zai)一幀數據(ju)的(de)(de)(de)發(fa)(fa)(fa)送(song)(song)或接(jie)收過程(cheng)中(zhong)(zhong),主(zhu)(zhu)機(ji)(ji)(ji)(ji)(ji)不(bu)干(gan)預,故將(jiang)發(fa)(fa)(fa)送(song)(song)的(de)(de)(de)一幀數據(ju)在(zai)(zai)發(fa)(fa)(fa)送(song)(song)開(kai)始前由CPU用(yong)批命令放(fang)入卡(ka)(ka)(ka)(ka)上的(de)(de)(de)SRAM中(zhong)(zhong),同樣,在(zai)(zai)接(jie)收過程(cheng)中(zhong)(zhong),卡(ka)(ka)(ka)(ka)上DMA將(jiang)接(jie)收到的(de)(de)(de)數據(ju)放(fang)入SRAM中(zhong)(zhong),等(deng)一幀接(jie)收完成后(hou),再用(yong)批命令取(qu)出,放(fang)入系統存儲器(qi)(qi)(qi)中(zhong)(zhong)。卡(ka)(ka)(ka)(ka)上SRAM不(bu)占用(yong)主(zhu)(zhu)機(ji)(ji)(ji)(ji)(ji)內存地址(zhi),采用(yong)I/O映像,該適配器(qi)(qi)(qi)插入主(zhu)(zhu)機(ji)(ji)(ji)(ji)(ji)之后(hou),主(zhu)(zhu)機(ji)(ji)(ji)(ji)(ji)通(tong)過系統I/O地址(zhi)對其訪問(wen),這(zhe)由地址(zhi)產生器(qi)(qi)(qi)完成。總(zong)線(xian)接(jie)口(kou)(kou)包(bao)括數據(ju)收發(fa)(fa)(fa)器(qi)(qi)(qi),數據(ju)開(kai)關電(dian)路,讀、寫及(ji)中(zhong)(zhong)斷(duan)等(deng)控制(zhi)電(dian)路,地址(zhi)譯碼等(deng)。波特率產生器(qi)(qi)(qi)提(ti)供了(le)一個(ge)可(ke)(ke)編(bian)程(cheng)的(de)(de)(de)時(shi)鐘(zhong)信(xin)(xin)號發(fa)(fa)(fa)生器(qi)(qi)(qi),用(yong)戶可(ke)(ke)自行設置通(tong)信(xin)(xin)速率,供工(gong)作于內時(shi)鐘(zhong)方(fang)式時(shi)使(shi)用(yong)。接(jie)口(kou)(kou)電(dian)路提(ti)供符合RS-232/C CITT V.24和RS-422A標準的(de)(de)(de)接(jie)口(kou)(kou)信(xin)(xin)號。
3 通信流程設計
如果要發送(song)(song)一幀數(shu)據(ju),CPU用批命令將數(shu)據(ju)放到本(ben)卡SRAM中,然后設(she)置相應的發送(song)(song)DMA通道。DMA通道是非(fei)自(zi)動(dong)(dong)重(zhong)裝方(fang)式,啟動(dong)(dong)8274控制器發送(song)(song),然后CPU就(jiu)不需要管理,由卡上硬(ying)件自(zi)動(dong)(dong)發送(song)(song)。
如果需要接(jie)收(shou)數據(ju)(ju),啟(qi)動接(jie)收(shou)通道(dao)。接(jie)收(shou)通路自動搜(sou)索(suo)輸入信(xin)號,搜(sou)索(suo)到數據(ju)(ju)幀時,由卡(ka)上DMA控制器(qi)來管理,將接(jie)收(shou)的數據(ju)(ju)放人本卡(ka)SRAM中,并向(xiang)CPU請求中斷(duan),讀出數據(ju)(ju)。
4 總線競爭設計
由(you)于同時可進行四路通信(xin)(xin),且CPU可隨時對(dui)某一(yi)路發控(kong)制(zhi)命令或訪問卡(ka)上SRAM存(cun)儲器,就(jiu)將出(chu)(chu)現CPU與(yu)本卡(ka)主設(she)備DMA爭用本卡(ka)總線(xian)的狀(zhuang)況。由(you)于ISA總線(xian)沒能給出(chu)(chu)CPU指令排(pai)隊狀(zhuang)態(tai)序(xu)列,這給總線(xian)仲裁帶來了困難,而本卡(ka)的總線(xian)競爭、仲裁是由(you)可編程邏輯器件設(she)計的狀(zhuang)態(tai)機來完成的。狀(zhuang)態(tai)機使(shi)用一(yi)個4MHz信(xin)(xin)號作為時鐘,共設(she)3種狀(zhuang)態(tai):
①CPU控制狀態(tai)。
②DMA控制狀態。
③空閑狀(zhuang)態,CPU及(ji)DMA均未能得到控(kong)制權(quan)。
當(dang)狀(zhuang)(zhuang)態機(ji)(ji)檢(jian)測到無CPU及(ji)DMA申請(qing)總(zong)(zong)(zong)(zong)線(xian)使(shi)用(yong)(yong)權時(shi)(shi),就進入空閑(xian)狀(zhuang)(zhuang)態,而(er)一(yi)旦(dan)CPU或(huo)DMA請(qing)求總(zong)(zong)(zong)(zong)線(xian),狀(zhuang)(zhuang)態機(ji)(ji)立(li)即將總(zong)(zong)(zong)(zong)線(xian)使(shi)用(yong)(yong)權交(jiao)給(gei)CPU或(huo)DMA。如(ru)果(guo)正在(zai)CPU控(kong)制(zhi)(zhi)狀(zhuang)(zhuang)態期間,DMA申請(qing)總(zong)(zong)(zong)(zong)線(xian)使(shi)用(yong)(yong)權,狀(zhuang)(zhuang)態機(ji)(ji)仍然判定(ding)CPU控(kong)制(zhi)(zhi)總(zong)(zong)(zong)(zong)線(xian),讓(rang)DMA處于等(deng)待,直(zhi)到檢(jian)測CPU指令完(wan)成,狀(zhuang)(zhuang)態機(ji)(ji)才轉(zhuan)為DMA控(kong)制(zhi)(zhi)狀(zhuang)(zhuang)態。如(ru)果(guo)在(zai)DMA控(kong)制(zhi)(zhi)狀(zhuang)(zhuang)態時(shi)(shi),CPU申請(qing)總(zong)(zong)(zong)(zong)線(xian)使(shi)用(yong)(yong)權,狀(zhuang)(zhuang)態機(ji)(ji)仍然判定(ding)DMA控(kong)制(zhi)(zhi)總(zong)(zong)(zong)(zong)線(xian),讓(rang)CPU處于等(deng)待,直(zhi)至DMA字(zi)節傳送完(wan),狀(zhuang)(zhuang)態機(ji)(ji)轉(zhuan)為CPU控(kong)制(zhi)(zhi)狀(zhuang)(zhuang)態。CPU及(ji)DMA對總(zong)(zong)(zong)(zong)線(xian)的(de)使(shi)用(yong)(yong)權是單個指令或(huo)字(zi)節傳送,不設置總(zong)(zong)(zong)(zong)線(xian)封鎖,因(yin)而(er)CPU、DMA可頻繁交(jiao)換使(shi)用(yong)(yong)權,不會(hui)出現等(deng)待時(shi)(shi)間過長的(de)現象。
通(tong)信卡的驅動程序設計
1 設(she)備驅動程序的I/O模型
通信(xin)卡(ka)的(de)(de)(de)驅動程序(xu)是利用(yong)(yong)Windows XP的(de)(de)(de)DDK軟件開(kai)發的(de)(de)(de)標準(zhun)的(de)(de)(de)核心態設(she)(she)備驅動程序(xu)。它(ta)使用(yong)(yong)統(tong)一的(de)(de)(de)“文件”形式,用(yong)(yong)戶可以通過代表通信(xin)卡(ka)設(she)(she)備的(de)(de)(de)文件名,在WIN32子系統(tong)中用(yong)(yong)文件操作函數來(lai)訪問。該設(she)(she)備驅動和程序(xu)可以根據用(yong)(yong)戶的(de)(de)(de)需要,設(she)(she)置(zhi)為(wei)自動加載,或(huo)手(shou)動加載,也可以動態的(de)(de)(de)加載該驅動程序(xu)。通信(xin)卡(ka)的(de)(de)(de)驅動程序(xu)設(she)(she)計(ji)成為(wei)支持同步I/O模型,也可以為(wei)異步I/O模型。
2 發送數據I/O例(li)程設計
在用(yong)戶態提交發(fa)送(song)任務到核心態,由I/O管理程序(xu)(xu)(xu)負責調用(yong)驅動程序(xu)(xu)(xu),驅動程序(xu)(xu)(xu)發(fa)送(song)IRP交給硬件,假(jia)若當前(qian)發(fa)送(song)器不忙,則(ze)具體的(de)發(fa)送(song)操作全(quan)部(bu)由發(fa)送(song)器自行完成(cheng),而驅動程序(xu)(xu)(xu)則(ze)返回已經一個本幀可以發(fa)送(song)的(de)標志。具體的(de)發(fa)送(song)完成(cheng)結果則(ze)可以在發(fa)送(song)任務完成(cheng)后查詢得(de)到。可是,如果程序(xu)(xu)(xu)向(xiang)當前(qian)設備發(fa)送(song)器提交發(fa)送(song)任務時,該發(fa)送(song)器正在處理上一幀,那么則(ze)有兩種方法(fa)處理。
①立(li)即(ji)方式(shi):立(li)即(ji)返回一個錯(cuo)誤,當前設備忙,不能發送。
②阻塞(sai)方式(shi):I/O管(guan)理器(qi)(qi)程序(xu)會調度(du)相(xiang)應的異步處理例程,將(jiang)當前的發(fa)送(song)(song)(song)(song)任(ren)(ren)務(wu)(wu)(wu)(wu)放進任(ren)(ren)務(wu)(wu)(wu)(wu)隊列中,返回一(yi)個(ge)標志:I/O掛起,當前設備忙,發(fa)送(song)(song)(song)(song)任(ren)(ren)務(wu)(wu)(wu)(wu)提(ti)交(jiao)任(ren)(ren)務(wu)(wu)(wu)(wu)隊列。驅動(dong)程序(xu)會在發(fa)送(song)(song)(song)(song)器(qi)(qi)空閑時,提(ti)交(jiao)任(ren)(ren)務(wu)(wu)(wu)(wu)隊列中的發(fa)送(song)(song)(song)(song)任(ren)(ren)務(wu)(wu)(wu)(wu)給(gei)發(fa)送(song)(song)(song)(song)器(qi)(qi)。完成發(fa)送(song)(song)(song)(song)任(ren)(ren)務(wu)(wu)(wu)(wu)后,將(jiang)相(xiang)關文件句柄設為(wei)有信號(hao)狀態,通知本次發(fa)送(song)(song)(song)(song)任(ren)(ren)務(wu)(wu)(wu)(wu)完成。
3 接收數據I/O例程
接(jie)收(shou)數(shu)(shu)據例程(cheng)采用客戶(hu)/服(fu)務器的(de)模式(shi)設計。由(you)于(yu)用戶(hu)的(de)接(jie)收(shou)請(qing)求(qiu)和硬件的(de)接(jie)收(shou)并不是同(tong)步(bu)的(de),所以在設計中,為避免丟失數(shu)(shu)據,考慮創造一個專門的(de)接(jie)收(shou)線程(cheng)。這樣,同(tong)步(bu)用戶(hu)請(qing)求(qiu)、接(jie)收(shou)線程(cheng)、硬件層之(zhi)間(jian)的(de)通信就(jiu)必須仔細(xi)地設計。圖2示意了用戶(hu)態接(jie)收(shou)請(qing)求(qiu)、接(jie)收(shou)線程(cheng)以及(ji)硬件層之(zhi)間(jian)的(de)通信同(tong)步(bu)。
①硬件(jian)層與接收(shou)線程(cheng)之間(jian)通信
硬(ying)件層與接(jie)(jie)(jie)收(shou)(shou)(shou)(shou)線(xian)程(cheng)之間通(tong)信(xin)(xin)的同(tong)步是(shi)通(tong)過同(tong)步事(shi)(shi)(shi)件對(dui)象(xiang)(xiang)(xiang)(xiang)來實現的。同(tong)步事(shi)(shi)(shi)件對(dui)象(xiang)(xiang)(xiang)(xiang)通(tong)常處于(yu)無信(xin)(xin)號(hao)狀(zhuang)(zhuang)態(tai)(tai),只有(you)當成功地接(jie)(jie)(jie)收(shou)(shou)(shou)(shou)到一幀時(shi),才將(jiang)(jiang)該事(shi)(shi)(shi)件置(zhi)為(wei)有(you)信(xin)(xin)號(hao)狀(zhuang)(zhuang)態(tai)(tai)。接(jie)(jie)(jie)收(shou)(shou)(shou)(shou)線(xian)長久等(deng)待(dai)同(tong)步事(shi)(shi)(shi)件對(dui)象(xiang)(xiang)(xiang)(xiang),在(zai)沒有(you)收(shou)(shou)(shou)(shou)到數(shu)(shu)據(ju)(ju)時(shi),因同(tong)步事(shi)(shi)(shi)件對(dui)象(xiang)(xiang)(xiang)(xiang)處于(yu)無信(xin)(xin)號(hao)狀(zhuang)(zhuang)態(tai)(tai)而(er)阻(zu)塞。當硬(ying)件檢測到數(shu)(shu)據(ju)(ju)時(shi),實時(shi)中斷服務程(cheng)序負責將(jiang)(jiang)同(tong)步事(shi)(shi)(shi)件對(dui)象(xiang)(xiang)(xiang)(xiang)置(zhi)為(wei)有(you)信(xin)(xin)號(hao)狀(zhuang)(zhuang)態(tai)(tai),接(jie)(jie)(jie)收(shou)(shou)(shou)(shou)線(xian)程(cheng)就(jiu)會釋(shi)放阻(zu)塞。將(jiang)(jiang)通(tong)信(xin)(xin)卡SRAM上的接(jie)(jie)(jie)收(shou)(shou)(shou)(shou)數(shu)(shu)據(ju)(ju)讀進(jin)接(jie)(jie)(jie)收(shou)(shou)(shou)(shou)線(xian)程(cheng)緩沖(chong)區隊列(lie),然(ran)后將(jiang)(jiang)同(tong)步事(shi)(shi)(shi)件對(dui)象(xiang)(xiang)(xiang)(xiang)置(zhi)為(wei)無信(xin)(xin)號(hao)狀(zhuang)(zhuang)態(tai)(tai),接(jie)(jie)(jie)收(shou)(shou)(shou)(shou)線(xian)程(cheng)再次阻(zu)塞,等(deng)待(dai)接(jie)(jie)(jie)收(shou)(shou)(shou)(shou)下一幀數(shu)(shu)據(ju)(ju)。
②用戶層和接收線程之間的通信(xin)
當用戶(hu)提交接收任務時,由驅動(dong)程(cheng)序(xu)(xu)的(de)調度程(cheng)序(xu)(xu)讀取接收線程(cheng)的(de)緩沖區隊列(lie),并將標志置為(wei)“空”,同時將緩沖隊列(lie)事件置為(wei)無信(xin)號狀態,并返(fan)回,如果緩沖區是(shi)空,則(ze)
?立即方式(shi):立即返回無數據。
?阻(zu)塞(sai)(sai)方式:阻(zu)塞(sai)(sai)直到有數據隊(dui)列進入。接(jie)收隊(dui)列的(de)每個緩沖區都對應一個通(tong)知(zhi)事(shi)件,如果接(jie)收線(xian)程(cheng)將SRAM中(zhong)的(de)數據讀進隊(dui)列,就(jiu)將相應的(de)通(tong)知(zhi)事(shi)件置為有信(xin)號(hao)狀態,用(yong)戶請求就(jiu)等待該通(tong)知(zhi)事(shi)件,只要有數據在隊(dui)列中(zhong),就(jiu)讀取返回,否則被阻(zu)塞(sai)(sai)。
4 硬中斷服(fu)務(wu)程序設計
通信卡(ka)在全雙(shuang)工的(de)通信中具(ju)有實時(shi)性,而且(qie)在較高的(de)波特率(lv),硬中斷非常多。為了防止高優先級中斷過(guo)多地搶占CPU時(shi)間,設計(ji)中采用了實時(shi)中斷服務程序和延(yan)遲過(guo)程調用的(de)方法。
在Windows XP系統中(zhong),每(mei)個內核函(han)數(shu)和過程(cheng)(cheng)都運行于特定的(de)(de)(de)(de)優(you)(you)先(xian)級(ji)(ji)(ji)。較(jiao)(jiao)高(gao)優(you)(you)先(xian)級(ji)(ji)(ji)的(de)(de)(de)(de)函(han)數(shu)或事件(jian)可以(yi)搶占較(jiao)(jiao)低(di)(di)優(you)(you)先(xian)級(ji)(ji)(ji),反之則(ze)不(bu)然。實(shi)時中(zhong)斷(duan)(duan)服務(wu)程(cheng)(cheng)序ISR運行于DIRQL級(ji)(ji)(ji),具有較(jiao)(jiao)高(gao)的(de)(de)(de)(de)優(you)(you)先(xian)級(ji)(ji)(ji),它只(zhi)能被(bei)更高(gao)級(ji)(ji)(ji)的(de)(de)(de)(de)硬中(zhong)斷(duan)(duan)所(suo)(suo)搶占,不(bu)會(hui)對同級(ji)(ji)(ji)或較(jiao)(jiao)低(di)(di)優(you)(you)先(xian)級(ji)(ji)(ji)的(de)(de)(de)(de)硬中(zhong)斷(duan)(duan)的(de)(de)(de)(de)響(xiang)應(ying)。所(suo)(suo)以(yi),在實(shi)時中(zhong)斷(duan)(duan)服務(wu)程(cheng)(cheng)序中(zhong),只(zhi)做盡(jin)量(liang)少的(de)(de)(de)(de)必須工作(zuo),即讀出(chu)中(zhong)斷(duan)(duan)向量(liang),而將大量(liang)的(de)(de)(de)(de)數(shu)據傳(chuan)送及(ji)處理(li)等工作(zuo)交給延遲過程(cheng)(cheng)DPC去完成。因為(wei)DPC過程(cheng)(cheng)運行于DISPATCH_LEVEL級(ji)(ji)(ji),是相對較(jiao)(jiao)低(di)(di)的(de)(de)(de)(de)優(you)(you)先(xian)級(ji)(ji)(ji),它可以(yi)被(bei)任何(he)級(ji)(ji)(ji)的(de)(de)(de)(de)硬中(zhong)斷(duan)(duan)所(suo)(suo)搶占。這樣,既保(bao)證了(le)(le)硬中(zhong)斷(duan)(duan)的(de)(de)(de)(de)及(ji)時響(xiang)應(ying),又提(ti)高(gao)了(le)(le)程(cheng)(cheng)序的(de)(de)(de)(de)性能。
5 驅動程(cheng)序人口例程(cheng)
Windows XP為每(mei)個核心態的驅動(dong)程(cheng)(cheng)序(xu)(xu)提供了一(yi)個默(mo)認的標準(zhun)入口(kou)點DriverEntry()。設計中(zhong),考慮到該例(li)程(cheng)(cheng)運行于PASSIVE_LEVE級,系統只運行該例(li)程(cheng)(cheng)一(yi)次就拋棄了,所以在(zai)(zai)驅動(dong)程(cheng)(cheng)序(xu)(xu)中(zhong)用到的重(zhong)要(yao)數據、對(dui)象等都不能保(bao)(bao)存在(zai)(zai)DriverEntry()例(li)程(cheng)(cheng)中(zhong),必須(xu)在(zai)(zai)初(chu)始化過程(cheng)(cheng)中(zhong)分配一(yi)塊NoPaged內存來(lai)保(bao)(bao)存。通信卡的驅動(dong)程(cheng)(cheng)序(xu)(xu)的DriverEntry()例(li)程(cheng)(cheng)主(zhu)要(yao)完成如下功能。
讀取Registry的硬件配置信(xin)息,聲明I/O地址、中斷等資源;創(chuang)建代表通(tong)信(xin)卡的設(she)備名MPSC,該名字對WIN32子系統是可見的;設(she)置調度(du)例程(cheng)(cheng)入口點;分配一塊(kuai)NoPaged的內(nei)存,存儲重要信(xin)息;連(lian)接硬中斷,設(she)置中斷服(fu)務(wu)程(cheng)(cheng)序,初始化線程(cheng)(cheng)、事件、信(xin)號燈、DPC等內(nei)核對象,返(fan)回狀態STATUS_SUCCESS。
如果在以上過程(cheng)中遇到錯誤,則需要做以下工作:斷開硬(ying)中斷;釋放硬(ying)件資源;將相關的錯誤信息打包,并記錄(lu);返回錯誤信息。
6 設(she)計驅動程序中需要注意的問(wen)題
由于通信卡在應用(yong)中(zhong)具有一定(ding)(ding)的(de)(de)實時性(xing)(xing),為了克服中(zhong)斷的(de)(de)不確定(ding)(ding)性(xing)(xing)。提高(gao)系(xi)統(tong)(tong)的(de)(de)性(xing)(xing)能,開發(fa)(fa)了Windows XP系(xi)統(tong)(tong)所有驅(qu)動程序中(zhong)最難(nan)的(de)(de)異(yi)步驅(qu)動程序。在系(xi)統(tong)(tong)的(de)(de)內(nei)核開發(fa)(fa),異(yi)步模型I/O操作中(zhong),內(nei)核對象的(de)(de)同(tong)步十分(fen)復(fu)雜,細(xi)微(wei)的(de)(de)差錯都(dou)會導致系(xi)統(tong)(tong)徹(che)底崩潰。在設計驅(qu)動程序中(zhong)需要注意以(yi)下問題。
?在程序中(zhong)用(yong)到的內核對象:事(shi)件、信號燈、線程以及(ji)連鎖等,都必(bi)須(xu)將其存(cun)儲(chu)在Nopaged內存(cun)中(zhong),否則,會造(zao)成系統崩潰。
篇8
關鍵(jian)詞:嵌(qian)入式(shi)系統(tong);linux;驅動程序
引言
Linux是(shi)一個遵循(xun)POSIX標(biao)準的(de)免費操(cao)作(zuo)系(xi)(xi)統。具有BSD和SYSV的(de)擴展特(te)性(xing)。與其(qi)(qi)(qi)他(ta)操(cao)作(zuo)系(xi)(xi)統相比(bi),嵌入式Linux系(xi)(xi)統以其(qi)(qi)(qi)可(ke)應用(yong)于(yu)多(duo)種硬件平臺、內核(he)高(gao)效穩定(ding)、源碼(ma)開(kai)(kai)放(fang)、軟(ruan)件豐富(fu)、網絡通信和文(wen)件管理機制(zhi)完善等優良特(te)性(xing)而(er)正被作(zuo)為研究熱點,越(yue)(yue)來(lai)越(yue)(yue)多(duo)的(de)研究人員(yuan)采用(yong)Linux平臺來(lai)開(kai)(kai)發自己的(de)產品。Linux設(she)備驅(qu)動程(cheng)序在(zai)(zai)Linux內核(he)源代碼(ma)中占有很大比(bi)例,從2.0、2.2到2.4版(ban)本(ben)的(de)內核(he),源代碼(ma)的(de)長度日益增(zeng)加,其(qi)(qi)(qi)實主要是(shi)設(she)備驅(qu)動程(cheng)序在(zai)(zai)增(zeng)加。
設備驅動(dong)程序(xu)的編寫
設(she)(she)備(bei)驅動(dong)程(cheng)序是(shi)(shi)linux內(nei)核的(de)(de)一(yi)(yi)部(bu)分,是(shi)(shi)操(cao)作(zuo)系(xi)統內(nei)核和(he)機器硬(ying)件(jian)之間的(de)(de)接口,它(ta)由一(yi)(yi)組函數和(he)一(yi)(yi)些私有(you)數據組成,是(shi)(shi)連接應(ying)用(yong)程(cheng)序與(yu)具體硬(ying)件(jian)的(de)(de)橋梁。Linux的(de)(de)一(yi)(yi)個(ge)基本特點是(shi)(shi)它(ta)對硬(ying)件(jian)設(she)(she)備(bei)的(de)(de)管理(li)抽象(xiang)化,系(xi)統中的(de)(de)每一(yi)(yi)個(ge)設(she)(she)備(bei)都(dou)用(yong)一(yi)(yi)個(ge)特殊的(de)(de)文件(jian)來表示。所有(you)的(de)(de)硬(ying)件(jian)設(she)(she)備(bei)都(dou)像普通的(de)(de)文件(jian)一(yi)(yi)樣(yang)看待(dai),使用(yong)與(yu)操(cao)作(zuo)系(xi)統相(xiang)同的(de)(de)標準系(xi)統來進行打(da)開(kai)、讀寫(xie)和(he)關閉。
在Linux操作系(xi)統(tong)下有3類(lei)主(zhu)要的(de)(de)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)文件類(lei)型:塊(kuai)(kuai)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)、字(zi)符(fu)(fu)(fu)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)、網(wang)(wang)絡設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)。字(zi)符(fu)(fu)(fu)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)是(shi)(shi)(shi)指存取時沒有緩存的(de)(de)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)。可(ke)(ke)像文件一(yi)樣(yang)訪問字(zi)符(fu)(fu)(fu)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei),字(zi)符(fu)(fu)(fu)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)驅動(dong)程(cheng)序(xu)負責(ze)實現(xian)這些行為。系(xi)統(tong)的(de)(de)控(kong)制(zhi)臺和(he)并口就是(shi)(shi)(shi)字(zi)符(fu)(fu)(fu)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)的(de)(de)例子,它們可(ke)(ke)以很好地(di)用“流(liu)”來描述。塊(kuai)(kuai)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)是(shi)(shi)(shi)文件系(xi)統(tong)的(de)(de)宿主(zhu),如磁盤。Linux允許(xu)像字(zi)符(fu)(fu)(fu)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)那樣(yang)讀取塊(kuai)(kuai)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)――允許(xu)一(yi)次傳(chuan)輸任意數目的(de)(de)字(zi)節。結(jie)果是(shi)(shi)(shi),字(zi)符(fu)(fu)(fu)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)和(he)塊(kuai)(kuai)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)讀取數方式一(yi)致。而網(wang)(wang)絡設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)不(bu)同(tong)于字(zi)符(fu)(fu)(fu)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)和(he)塊(kuai)(kuai)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei),它面向的(de)(de)上(shang)一(yi)層不(bu)是(shi)(shi)(shi)文件系(xi)統(tong)而是(shi)(shi)(shi)網(wang)(wang)絡協議層,是(shi)(shi)(shi)通(tong)過BSD套接口訪問數據。與(yu)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)相(xiang)對應(ying)的(de)(de)是(shi)(shi)(shi)三類(lei)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)驅動(dong)程(cheng)序(xu),字(zi)符(fu)(fu)(fu)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)驅動(dong)程(cheng)序(xu)、塊(kuai)(kuai)設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)驅動(dong)程(cheng)序(xu)、網(wang)(wang)絡設(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)(bei)驅動(dong)程(cheng)序(xu)。
字(zi)符設備(bei)驅動(dong)程序(xu)、塊設備(bei)驅動(dong)程序(xu)與網(wang)絡設備(bei)驅動(dong)程序(xu)的結構體是不同的。
在linux源代(dai)碼linux/include/linux/fs.h中定義了字(zi)符設(she)備和塊(kuai)設(she)備驅(qu)動(dong)程(cheng)序中必(bi)須使用的(de)(de)file_operations結構,每(mei)個設(she)備驅(qu)動(dong)都實現這個接(jie)口(kou)所定義的(de)(de)部(bu)分或(huo)全(quan)部(bu)函(han)數。隨(sui)著內核的(de)(de)不(bu)(bu)斷升級,file_operations結構也越來(lai)越大,不(bu)(bu)同的(de)(de)版本(ben)的(de)(de)內核會(hui)稍有不(bu)(bu)同。
應(ying)用程序(xu)(xu)只有(you)通過對(dui)設(she)(she)備(bei)文(wen)件(jian)的(de)open、release、read、write、ioctl等才能訪問(wen)字符設(she)(she)備(bei)和塊(kuai)設(she)(she)備(bei)。用戶自(zi)己定(ding)義(yi)好file_operations結構后,編寫出設(she)(she)備(bei)實際所需要的(de)各(ge)操(cao)(cao)作(zuo)函(han)(han)(han)(han)數(shu),對(dui)于不需要的(de)操(cao)(cao)作(zuo)函(han)(han)(han)(han)數(shu)用NULL初(chu)始化,這些操(cao)(cao)作(zuo)函(han)(han)(han)(han)數(shu)將(jiang)被注冊到(dao)內(nei)核,當應(ying)用程序(xu)(xu)對(dui)設(she)(she)備(bei)相(xiang)應(ying)的(de)設(she)(she)備(bei)文(wen)件(jian)進(jin)行文(wen)件(jian)操(cao)(cao)作(zuo)時(shi),內(nei)核會找到(dao)相(xiang)應(ying)的(de)操(cao)(cao)作(zuo)函(han)(han)(han)(han)數(shu),并(bing)進(jin)行調用。如(ru)果操(cao)(cao)作(zuo)函(han)(han)(han)(han)數(shu)使用NULL,操(cao)(cao)作(zuo)函(han)(han)(han)(han)數(shu)就進(jin)行默認(ren)處理(li)。
對(dui)(dui)于字符設備而言,llseek(),read(),write(),ioctl(),open(),release()這些(xie)函數是不(bu)可缺(que)的;對(dui)(dui)十塊設備,open(),release(),ioctl(),check_media_change(),revalidate()是不(bu)可缺(que)少的。
網(wang)絡設備結構體(ti)net_device定義在(zai)include\linuxhletdevice.h里,如下所示:
定義好net_device結(jie)構體后(hou),根據實際情況編寫操(cao)作函數(shu),其中(zhong)hard_start_xmit()函數(shu)是(shi)用來(lai)發送數(shu)據的,set mac address()是(shi)進行網絡(luo)參數(shu)設置的。
當linux初始化(hua)時將調用初始化(hua)函數(shu)intdevice_init(),該(gai)函數(shu)包括(kuo)以(yi)下內(nei)容:
注(zhu)冊(ce)所用設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)。linux用設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)號來標識字符設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)和(he)塊設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)。設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)號分(fen)為主(zhu)(zhu)設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)號和(he)從(cong)設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)號,最終形成(cheng)設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)接點。設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)節點在訪問字符設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)和(he)塊設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)的(de)設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)驅動(dong)程(cheng)(cheng)(cheng)序時(shi)將使用。通常(chang)主(zhu)(zhu)設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)號標識設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)對應的(de)驅動(dong)程(cheng)(cheng)(cheng)序,大多數設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)是(shi)“一(yi)個主(zhu)(zhu)設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)號對應一(yi)個驅動(dong)程(cheng)(cheng)(cheng)序”,如:虛擬(ni)控(kong)制臺(tai)和(he)串口終端(duan)由驅動(dong)程(cheng)(cheng)(cheng)序4管理。次設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)號由內核使用,用于確定設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)文件所指(zhi)的(de)設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)。字符設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)和(he)塊設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)注(zhu)冊(ce)時(shi)必須(xu)先定義(yi)好(hao)設(she)(she)(she)(she)(she)(she)備(bei)(bei)(bei)(bei)(bei)號。
字(zi)符設備注冊(ce)函數如下:
int register_chrdev(unsigned int major,constchar*name,struct file_oprations*fops);其中major是(shi)主設(she)備號。
由于對網絡設備驅(qu)動程(cheng)序的訪問不需要設備節點,它的注冊函數如(ru)下:
int register_netdev(struct net_device*dev)
注冊(ce)設備所用的中斷(duan)。中斷(duan)在(zai)現代計算機結構中有(you)重(zhong)要(yao)的地位,操(cao)作系(xi)統(tong)必須提(ti)供(gong)程序(xu)響應中斷(duan)的能力(li)。一般(ban)是把一個中斷(duan)處理(li)程序(xu)注冊(ce)到系(xi)統(tong)中去。操(cao)作系(xi)統(tong)在(zai)硬件中斷(duan)發生后調用驅動程序(xu)的處理(li)程序(xu)。
注冊中(zhong)斷(duan)(duan)所(suo)用的函數如下:其中(zhong),irq是(shi)中(zhong)斷(duan)(duan)向量;handler是(shi)中(zhong)斷(duan)(duan)處(chu)理函數;flags是(shi)中(zhong)斷(duan)(duan)處(chu)理中(zhong)的掩(yan)碼;devices是(shi)設備名;dev_id是(shi)在中(zhong)斷(duan)(duan)共享(xiang)使用的id。
當linux不(bu)使(shi)用該設備時,就要調用清除函
編寫服務子程序
服務于(yu)I/O請求的(de)子(zi)程(cheng)序,又(you)稱為驅動程(cheng)序的(de)上半(ban)部分(fen)。調(diao)用(yong)這部分(fen)是由于(yu)系(xi)統(tong)調(diao)用(yong)的(de)結果。這部分(fen)程(cheng)序在(zai)執行(xing)(xing)的(de)時候(hou),系(xi)統(tong)仍認為是和(he)進(jin)行(xing)(xing)調(diao)用(yong)的(de)進(jin)程(cheng)屬于(yu)同一個進(jin)程(cheng),只是用(yong)戶(hu)態(tai)變成了核心(xin)態(tai),具(ju)有進(jin)行(xing)(xing)此系(xi)統(tong)調(diao)用(yong)的(de)用(yong)戶(hu)程(cheng)序的(de)運(yun)行(xing)(xing)環境(jing),因此可(ke)以在(zai)其中調(diao)用(yong)sleep等與進(jin)程(cheng)運(yun)行(xing)(xing)環境(jing)有關的(de)函數。
中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)服(fu)務(wu)子程(cheng)(cheng)(cheng)序(xu),又(you)稱(cheng)為(wei)驅動(dong)程(cheng)(cheng)(cheng)序(xu)的下(xia)半部分。在(zai)Linux系(xi)統中(zhong)(zhong)(zhong)(zhong)(zhong),并不(bu)是直接從(cong)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)向量表中(zhong)(zhong)(zhong)(zhong)(zhong)調用(yong)設(she)備(bei)驅動(dong)程(cheng)(cheng)(cheng)序(xu)的中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)服(fu)務(wu)子程(cheng)(cheng)(cheng)序(xu),而是由(you)Linux系(xi)統來接收硬件(jian)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan),再由(you)系(xi)統調用(yong)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)服(fu)務(wu)子程(cheng)(cheng)(cheng)序(xu)。中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)可以(yi)產生在(zai)任何(he)(he)一(yi)個進(jin)程(cheng)(cheng)(cheng)運(yun)行(xing)的時(shi)候,因(yin)此(ci)在(zai)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)服(fu)務(wu)程(cheng)(cheng)(cheng)序(xu)被調用(yong)的時(shi)候,不(bu)能依賴于任何(he)(he)進(jin)程(cheng)(cheng)(cheng)的狀態,也就不(bu)能調用(yong)任何(he)(he)與進(jin)程(cheng)(cheng)(cheng)運(yun)行(xing)環境相關的函數。因(yin)為(wei)設(she)備(bei)驅動(dong)程(cheng)(cheng)(cheng)序(xu)一(yi)般支(zhi)持同一(yi)類型的若(ruo)干(gan)設(she)備(bei),所(suo)以(yi)一(yi)般在(zai)系(xi)統調用(yong)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)服(fu)務(wu)程(cheng)(cheng)(cheng)序(xu)的時(shi)候,都(dou)帶(dai)有一(yi)個或多個參數,以(yi)唯一(yi)標識請求服(fu)務(wu)的設(she)備(bei)。
設備(bei)驅(qu)動程序的(de)使用(yong)
直接將(jiang)驅動程序(xu)編(bian)譯進(jin)linux內核(he)
將設備驅動(dong)(dong)程序復制到linux/drivers相關的子目錄(lu)下,比如(ru)字符設備驅動(dong)(dong)程序就放在linux/drivers/char下。
修改linux/drivers相關的子目錄的Makefile,
如obj-$(config_dev_driver)+=dev_driver.o,這樣在編(bian)譯(yi)內核時將會編(bian)譯(yi)dev_driver.c,生成dev_driver.o.
對內核進行重新編譯時,進行相關(guan)的(de)配(pei)置,比如(ru)要使用(yong)AT91RM9200的(de)UART,就要如(ru)下配(pei)置:
Character devices->Serial drivers.>AT91RM9200 serial port suppot
將驅動程(cheng)序編譯成驅動模塊
在設備驅動程(cheng)序中要有兩個重要函數:
module_init(dev-init),module_exit(dev_exit)
利(li)用(yong)相(xiang)應的交(jiao)叉編譯器以及編譯命(ming)令將驅動程序dev_driver.c編譯成dev_driver.o這樣的動態驅動模(mo)塊。利(li)用(yong)insmod命(ming)令給系統安裝驅動模(mo)塊,如果(guo)在(zai)/dev目錄下(xia)沒有相(xiang)應的設備文件,就可以使用(yong)mknod創建一個設備文件。利(li)用(yong)rmmod命(ming)令卸載(zai)驅動模(mo)塊,設備文件的刪除可以用(yong)rm命(ming)令。
篇9
A/D轉換是單(dan)(dan)片機(ji)數據(ju)采(cai)集系統的(de)重要組(zu)成部分(fen),實(shi)時(shi)內(nei)核下A/D驅動程(cheng)序的(de)實(shi)現(xian)過程(cheng)主(zhu)取決(jue)于A/D轉換器的(de)轉換時(shi)間(jian)。本文(wen)首先比較和(he)分(fen)析μC/OS-II下A/D采(cai)樣數據(ju)的(de)三種方法;其次介(jie)紹(shao)C8051F015單(dan)(dan)片機(ji)A/D模數轉換器配置及特點(dian);最后,在μC/OS-II內(nei)核移植到8位單(dan)(dan)片機(ji)C8051F015的(de)基礎(chu)上(shang),介(jie)紹(shao)編寫(xie)A/D驅動程(cheng)序的(de)一般(ban)思(si)想和(he)方法。
1 μC/OS-II實(shi)時內核下的A/D讀(du)方法
實時內核(he)下,驅動程序采用(yong)什么方(fang)(fang)法讀(du)(du)取(qu)(qu)A/D采樣數據(ju)是(shi)首先考慮的(de)(de)問(wen)題。許多(duo)(duo)因素將(jiang)影(ying)響讀(du)(du)取(qu)(qu)A/D,如A/D的(de)(de)轉(zhuan)(zhuan)(zhuan)換(huan)(huan)時間、模(mo)擬(ni)值(zhi)的(de)(de)轉(zhuan)(zhuan)(zhuan)換(huan)(huan)頻率、輸入通道(dao)數等,但最主要的(de)(de)取(qu)(qu)決于A/D的(de)(de)轉(zhuan)(zhuan)(zhuan)換(huan)(huan)時間。典(dian)型(xing)的(de)(de)A/D轉(zhuan)(zhuan)(zhuan)換(huan)(huan)典(dian)型(xing)的(de)(de)A/D轉(zhuan)(zhuan)(zhuan)換(huan)(huan)電(dian)路由模(mo)擬(ni)多(duo)(duo)路復用(yong)器(MUX)、放大器和模(mo)數轉(zhuan)(zhuan)(zhuan)換(huan)(huan)器(ADC)三部分組成。下面描述讀(du)(du)取(qu)(qu)A/D的(de)(de)三種方(fang)(fang)法。
圖1所示的(de)是第1種讀(du)(du)取(qu)方法。假設A/D轉(zhuan)(zhuan)(zhuan)換器的(de)轉(zhuan)(zhuan)(zhuan)換時間較慢(man)(5ms以上)。應用程(cheng)(cheng)序調用圖1所示的(de)驅(qu)(qu)動程(cheng)(cheng)序,并傳遞(di)要讀(du)(du)取(qu)的(de)通道(dao)。驅(qu)(qu)動程(cheng)(cheng)序通過MUX選擇要讀(du)(du)取(qu)的(de)模擬(ni)通道(dao)(①)開(kai)始讀(du)(du)。有,延時幾(ji)μs以便使(shi)信(xin)號通過MUX傳遞(di),并之穩定下來。接著,ADC被觸發開(kai)始轉(zhuan)(zhuan)(zhuan)換(②)。然后(hou)驅(qu)(qu)動程(cheng)(cheng)序延時一段時間以完成轉(zhuan)(zhuan)(zhuan)換(③_。延時時間必須(xu)比ADC轉(zhuan)(zhuan)(zhuan)換時間長(chang)。最后(hou)驅(qu)(qu)動程(cheng)(cheng)序讀(du)(du)取(qu)ADC轉(zhuan)(zhuan)(zhuan)換結果(④)。并將(jiang)轉(zhuan)(zhuan)(zhuan)換結果返回到應用程(cheng)(cheng)序(⑤)。
圖2所示(shi)的(de)是第2種讀取方(fang)法。當(dang)模擬轉(zhuan)換(huan)(huan)完成(cheng)后,ADC產(chan)生的(de)個中(zhong)斷信號(hao)。若ADC轉(zhuan)換(huan)(huan)完成(cheng),ISR給(gei)信號(hao)量發一個信號(hao)(⑤),通知(zhi)驅(qu)動(dong)程序,ADC已經完成(cheng)轉(zhuan)換(huan)(huan)。如(ru)果ADC在(zai)規定的(de)時(shi)限內沒有完成(cheng)轉(zhuan)換(huan)(huan)。信號(hao)量超過(③),則(ze)驅(qu)動(dong)程序不(bu)再等待下去。驅(qu)動(dong)程序和中(zhong)斷服務子程序(ISR)的(de)偽代(dai)碼如(ru)下:
ADRd(ChannelNumber)
{
選擇(ze)要讀(du)取的模擬輸(shu)入通道;
等待AMUX輸出穩定;
啟動ADC轉換;
等待(dai)來自ADC轉(zhuan)換結束中斷產生(sheng)的(de)信號量(liang);
if(超時){
*eer=信號錯誤;
return;
}else{
讀取ADC轉(zhuan)換結果并將(jiang)其返回到應用程序;
}
}
ADCoversion Complete ISR {
保存全部CPU寄(ji)存器(qi); /*將CPU的(de)PSW、ACC、B、DPL、DPH及Rn入棧*/
通(tong)知內核進入ISR(調用OSIntEnter()或OSIntNesting直接加1);
發送ADC轉換完成(cheng)信號; /*利用μC/OS-II內核的OSSemPost()*/
通知內核退出ISR(調用(yong)OSIntExit());
恢復所有(you)CPU寄存器(qi);/*將CPU的PSW、ACC、B、DPL、DPH及(ji)Rn出棧(zhan)*/
執行中斷返回(hui)指令(即RETI);
}
在這(zhe)種方法里,要求ISR執行(xing)時間(jian)與調用等待(dai)信(xin)號(hao)的時間(jian)之和(he)為A/D轉換時間(jian)。
如(ru)果(guo)(guo)A/D轉換(huan)時(shi)(shi)(shi)(shi)間(jian)小于處理中(zhong)斷時(shi)(shi)(shi)(shi)間(jian)與等待(dai)信(xin)(xin)號(hao)所(suo)需的(de)(de)時(shi)(shi)(shi)(shi)間(jian)之和,則可以用第三種方(fang)法(fa)。如(ru)圖(tu)3所(suo)示,前兩(liang)步(bu)(①②同(tong)以上兩(liang)種方(fang)法(fa))結(jie)(jie)(jie)束(shu)(shu)后,驅(qu)(qu)(qu)動程(cheng)序接著(zhu)在一個軟件(jian)循(xun)(xun)環中(zhong)等待(dai)(③)ADC直到完成轉換(huan)。在循(xun)(xun)環等待(dai)時(shi)(shi)(shi)(shi),驅(qu)(qu)(qu)動程(cheng)序檢測ADC的(de)(de)狀態(BUSY)信(xin)(xin)號(hao)。如(ru)果(guo)(guo)等待(dai)時(shi)(shi)(shi)(shi)間(jian)超過(guo)設定(ding)的(de)(de)定(ding)時(shi)(shi)(shi)(shi)值(軟件(jian)定(ding)時(shi)(shi)(shi)(shi)),則結(jie)(jie)(jie)束(shu)(shu)等待(dai)循(xun)(xun)環(循(xun)(xun)環等超時(shi)(shi)(shi)(shi))。如(ru)果(guo)(guo)在循(xun)(xun)環等待(dai)中(zhong),檢測到ADC發出轉換(huan)結(jie)(jie)(jie)束(shu)(shu)的(de)(de)信(xin)(xin)號(hao)(BUSY)時(shi)(shi)(shi)(shi),驅(qu)(qu)(qu)動程(cheng)序讀取ADC轉換(huan)結(jie)(jie)(jie)果(guo)(guo)(④)并將(jiang)結(jie)(jie)(jie)果(guo)(guo)返回到應用程(cheng)序(⑤)。驅(qu)(qu)(qu)動程(cheng)序偽代碼如(ru)下:
ADRd(ChannelNumber){
選擇要讀取的模擬輸入(ru)通道(dao);
等待AMUX輸出穩定;
啟動ADC轉換;
啟動超時定時器;
while(ADC Busy & Counter 0);/*循環檢測*/
if(Counter==0){
*err=信號錯誤;
return;
}else{
讀取ADC轉換結果并將其返回到應用(yong)程(cheng)序;
}
}
A、D轉(zhuan)換速度(du)快,這種(zhong)驅(qu)動程序(xu)的實現是最(zui)好的。
2 C8051F015單片機的A/D轉(zhuan)換(huan)器
2.1 C8051C015單片(pian)機
C8051C015的(de)(de)(de)美國Cygnal公(gong)司(si)新推出的(de)(de)(de)高(gao)速SOC型C8051Fxxx系(xi)列單片(pian)機。它的(de)(de)(de)內(nei)核CIP-51與MCS-51的(de)(de)(de)指(zhi)令集(ji)完(wan)全兼容,CIP-51的(de)(de)(de)系(xi)統時(shi)(shi)鐘(zhong)(zhong)頻率在0~25MHz。C8051Fxxx系(xi)列單片(pian)機采用流水線結構,與標準的(de)(de)(de)8051相比,指(zhi)令執行速度(du)有(you)很大的(de)(de)(de)提高(gao)。CIP-51內(nei)核的(de)(de)(de)指(zhi)令執行時(shi)(shi)間(jian)是以系(xi)統時(shi)(shi)鐘(zhong)(zhong)為(wei)單位(wei),70%的(de)(de)(de)指(zhi)令執行時(shi)(shi)間(jian)為(wei)1個(ge)或2個(ge)系(xi)統時(shi)(shi)鐘(zhong)(zhong)周期。C8051F015具有(you)32KB的(de)(de)(de)內(nei)存、2304B的(de)(de)(de)RAM(片(pian)內(nei)256B、片(pian)外2048B)。CIP-51內(nei)核具有(you)標準8052的(de)(de)(de)所有(you)外設部件,片(pian)上還集(ji)成有(you)9通道10位(wei)A/D轉換接口電(dian)路、SMBus/I2C、SPI串行接口。
2.2 C8051F015的A/D轉(zhuan)換電路
C8051F015的(de)A/D轉換電(dian)路包(bao)括1個(ge)9通道可配置模擬多路開關AMUX(8路用于(yu)外部模擬輸入、1路用于(yu)芯片環(huan)境溫度的(de)測量)、1個(ge)可編(bian)程增益(yi)放大(da)器PGA和1個(ge)100ksps 10位分(fen)辨率的(de)逐次逼近型(xing)ADC。A/D中還集成(cheng)了跟蹤保(bao)持電(dian)路和可編(bian)程窗(chuang)口檢測器。
ADC有4種啟動方(fang)式(shi)(shi):軟件命令、定時(shi)器2溢出、定時(shi)器3溢出及外部(bu)信號輸入。寄(ji)存器ADC0CN是配置啟動和跟(gen)蹤方(fang)式(shi)(shi)的控(kong)制寄(ji)存器。每(mei)次(ci)轉換結(jie)束(shu)時(shi),ADC0CH的ADBUSY(忙標志)的下降(jiang)沿(yan)觸發中斷,也(ye)可用(yong)軟件查詢(xun)這個狀態位(wei)。
2.3 ADC轉換速度
C8051Fxxx系(xi)(xi)列單(dan)片機中ADC的速率都是可編程設置(zhi)的。表(biao)1給出了所需最小分頻系(xi)(xi)數與SYSCLK(系(xi)(xi)統時(shi)鐘)的關(guan)系(xi)(xi)(ADC0CF為ADC配置(zhi)寄存器(qi))。
表1 ADC時(shi)鐘(zhong)分頻系(xi)數(shu)與(yu)SYSCLK頻率的關系(xi)
SYSCLK頻(pin)率(lv)/MHzADC時(shi)(shi)(shi)鐘分(fen)頻(pin)系(xi)數ADC0CF的(de)ADCSC2~1時(shi)(shi)(shi)鐘頻(pin)率(lv)<2.510002.5~520015~10401010~208(復位值(zhi))011時(shi)(shi)(shi)鐘頻(pin)率(lv)>20161xx在(zai)(zai)C8051F015單片機中,ADC的(de)轉(zhuan)換(huan)(huan)(huan)(huan)時(shi)(shi)(shi)鐘周期(qi)至少在(zai)(zai)400ns,轉(zhuan)換(huan)(huan)(huan)(huan)時(shi)(shi)(shi)鐘應不大于2MHz。一般(ban)在(zai)(zai)啟動ADC之前(qian)都要處于跟蹤(zong)方式,而(er)ADC一次(ci)(ci)轉(zhuan)換(huan)(huan)(huan)(huan)完(wan)(wan)成(cheng)要用(yong)16個(ge)系(xi)統時(shi)(shi)(shi)鐘。另外,在(zai)(zai)轉(zhuan)換(huan)(huan)(huan)(huan)之前(qian)還要加上3個(ge)系(xi)統時(shi)(shi)(shi)鐘的(de)跟蹤(zong)/保持捕獲時(shi)(shi)(shi)間(jian),所以完(wan)(wan)成(cheng)一次(ci)(ci)轉(zhuan)換(huan)(huan)(huan)(huan)需19個(ge)ADC轉(zhuan)換(huan)(huan)(huan)(huan)時(shi)(shi)(shi)鐘(9.5μs)。
圖1中的(de)方法(fa)簡單,轉換時(shi)(shi)(shi)間(jian)(jian)在ms級(ji)以上(shang),一(yi)般(ban)用(yong)(yong)于(yu)變化慢的(de)模擬輸入信號,不(bu)適(shi)用(yong)(yong)于(yu)C8051F015。圖2中的(de)方法(fa),為了減少(shao)μC/OS-II內核調(diao)用(yong)(yong)ISR所(suo)用(yong)(yong)時(shi)(shi)(shi)間(jian)(jian),ISR一(yi)般(ban)都用(yong)(yong)于(yu)匯編(bian)語言編(bian)寫(xie)。從程序1中ISR偽代碼(ma)可以看(kan)出,盡管ISR用(yong)(yong)匯編(bian)語言編(bian)寫(xie)。代碼(ma)效率(lv)高(gao),但μC/OS-II調(diao)用(yong)(yong)ISR的(de)時(shi)(shi)(shi)間(jian)(jian)與調(diao)用(yong)(yong)等待信號時(shi)(shi)(shi)間(jian)(jian)之(zhi)和大(da)于(yu)A/D的(de)轉換時(shi)(shi)(shi)間(jian)(jian),所(suo)以CPU用(yong)(yong)于(yu)ISR和循環檢測(ce)的(de)開(kai)銷(xiao)大(da)。
圖3所示的(de)方(fang)法顯然適合于C8051F015單(dan)片機,其優點是(shi):可以獲(huo)得(de)快速的(de)轉換時間(jian);不(bu)需要增加(jia)一個復雜的(de)ISR;轉換時信號(hao)(hao)改變時間(jian)更短;CPU的(de)開銷小(xiao);循環檢測程序可被中斷,為中斷信號(hao)(hao)服務。
圖(tu)4 A/D驅動程序模塊流(liu)程圖(tu)
3 A/D驅動程(cheng)序(xu)的(de)編寫
外設(she)驅(qu)動(dong)程(cheng)序是實時內核(he)和(he)硬件(jian)(jian)之(zhi)間(jian)的接(jie)口,是連接(jie)底層(ceng)硬件(jian)(jian)和(he)內核(he)的紐帶。編寫(xie)驅(qu)動(dong)程(cheng)序模塊應滿足以下主(zhu)要功能:①對設(she)備初始化(hua);②把(ba)數(shu)據從(cong)內核(he)傳(chuan)送(song)到(dao)硬件(jian)(jian)從(cong)硬件(jian)(jian)讀(du)取數(shu)據;③讀(du)取應用程(cheng)序傳(chuan)送(song)給(gei)設(she)備的數(shu)據和(he)回(hui)送(song)應用程(cheng)序請求(qiu)的數(shu)據;④監測和(he)處(chu)理(li)設(she)備出現(xian)的異常(chang)。
A/D轉換電路作為(wei)一個(ge)模(mo)(mo)擬輸(shu)(shu)入(ru)模(mo)(mo)塊,μC/OS-II內核應(ying)把它作為(wei)一個(ge)獨立的(de)任務(以下稱為(wei)ADTask())來調(diao)用。A/D驅動(dong)程(cheng)序(xu)模(mo)(mo)塊流(liu)程(cheng)如圖4所(suo)示。ADInit()初始化所(suo)有的(de)模(mo)(mo)擬輸(shu)(shu)入(ru)通道、硬件ADC以及應(ying)用程(cheng)序(xu)調(diao)用A/D模(mo)(mo)塊的(de)參量,并(bing)且ADInit()創建任務ADTask()。ADTb1[]是(shi)一個(ge)模(mo)(mo)擬輸(shu)(shu)入(ru)通道信(xin)息、ADC硬件狀態等(deng)參數配置以及轉換結果存(cun)儲表。ADUpdate()負(fu)(fu)責讀取所(suo)有模(mo)(mo)擬輸(shu)(shu)入(ru)通道,訪問ADRd()并(bing)傳遞給它一個(ge)通道數。ADRd()負(fu)(fu)責通過多(duo)路復用器選擇(ze)合適的(de)模(mo)(mo)擬輸(shu)(shu)入(ru),啟動(dong)并(bing)等(deng)待ADC轉換,以及返回ADC轉換結果到ADUpdate()。
在μC/OS-II這(zhe)時內核(he)下各原型函數、數據結構和(he)常量的(de)定義如下:
INT16S ADRd(INT8U ch);
/*定義如何讀取A/D,A/D必須(xu)通(tong)過AIRd()來驅動*/
void ADUpdate(void);
/*一定時間內更新(xin)輸入通道*/
void ADInit(void);
/*A/D模塊初(chu)始(shi)化(hua)代(dai)碼,包括初(chu)始(shi)化(hua)所有(you)內部變量(通過(guo)ADInit()初(chu)始(shi)化(hua)ADTb[]),初(chu)始(shi)化(hua)硬件A/D(通過(guo)ADInitI())及(ji)創建任務ADTask()*/
void ADTask (void data);
/*由(you)ADInit()創(chuang)建,負責(ze)更新輸入通道(調(diao)用ADUpdate ())*/
void ADInitI (void);
/*初始(shi)化硬件A/D*/
AD_TaskPrio:設(she)置(zhi)任(ren)務ADTask()的優先級。
AD_TaskStkSize:設置(zhi)分(fen)配(pei)給(gei)任務(wu)ADTask()的(de)堆棧大小。
AD_MaxNummber:AMUX的輸入(ru)通道數。
AD_TaskDly:設定更新通道的間(jian)隔時間(jian)。
AD ADTbl[AD_MaxNummber]:AD類型的(de)數組(zu)(AD是定義的(de)數據結構)。
4 結論
對于A/D轉(zhuan)換器接口電(dian)路驅動程(cheng)序的編寫(xie)歸納出以下幾點:
①在決定采(cai)用具體的驅動(dong)方案(an)之(zhi)前(qian),分析接口電路(lu)的特點,尤其是了解A/D的轉換速度;
②對于(yu)轉換(huan)速(su)度(du)快(kuai)的A/D轉換(huan)器,可能(neng)出(chu)現CPU的處理(li)速(su)度(du)與(yu)A/D轉換(huan)速(su)度(du)不(bu)匹配,一般的A/D中不(bu)帶有(you)FIFO緩(huan)(huan)沖(chong)區(qu),須有(you)內存中開辟緩(huan)(huan)沖(chong)區(qu);
篇10
第一節windows nt網絡(luo)結構
§1.1.1 windows nt網絡體系結構
windows nt的(de)(de)網絡體系結(jie)構(gou)是基于國際標(biao)準化(iso)制定(ding)的(de)(de)標(biao)準模型──開(kai)放式系統互連(open system interconnection:osi)參考(kao)模型分層(ceng)建立(li)的(de)(de),這種方式有(you)利于隨時(shi)擴展(zhan)其它功能(neng)和(he)服務(wu)。
windows nt網(wang)絡模(mo)型(xing)開始于mac子層(ceng),網(wang)卡(ka)驅(qu)動程序就駐(zhu)留在(zai)其中(zhong)。它通過相關的(de)網(wang)卡(ka)把windows nt與(yu)網(wang)絡連接起來,圖中(zhong)的(de)多(duo)個網(wang)卡(ka)表明在(zai)一臺(tai)運行windows nt的(de)計(ji)算(suan)機(ji)上能(neng)使用多(duo)種網(wang)卡(ka)。
這一網絡(luo)體系結構包括兩個重要(yao)接口(kou)(kou)──ndis接口(kou)(kou)與傳輸驅(qu)動(dong)
程序(xu)(xu)接(jie)(jie)口(tdi)。這兩個接(jie)(jie)口把兩個層隔(ge)離開來(lai),辦(ban)法(fa)是相(xiang)鄰的(de)部件(jian)只允(yun)(yun)許按單一(yi)的(de)標準來(lai)寫,不(bu)允(yun)(yun)許多重標準。例(li)如一(yi)個網(wang)卡(ka)驅動程序(xu)(xu)(在ndis接(jie)(jie)口的(de)下面)就不(bu)需(xu)要(yao)特地按每個傳輸協議來(lai)寫它的(de)代(dai)碼塊,恰(qia)恰(qia)相(xiang)反,該驅動程序(xu)(xu)是寫給(gei)ndis接(jie)(jie)口的(de),它通過(guo)符合ndis的(de)相(xiang)應傳輸協議來(lai)請求服務(wu)。這些接(jie)(jie)口包含在windows nt的(de)網(wang)絡體系結構(gou)中,以容納可移植、可互換的(de)模塊。
在兩個接口之間,是傳(chuan)輸協議。它在網絡中起著組織者(zhe)的作用。一個傳(chuan)輸協議規(gui)定了數(shu)據(ju)(ju)以何種(zhong)方式(shi)呈遞給下一個接收層(ceng),以及如何對(dui)數(shu)據(ju)(ju)相應地(di)進行打包(bao)。它通過ndis把數(shu)據(ju)(ju)傳(chuan)給網卡驅動程序(xu),并通過tdi把數(shu)據(ju)(ju)傳(chuan)給轉發程序(xu)(redirector)
tdi之上是轉(zhuan)發(fa)程序,它把本(ben)地的網絡(luo)資源申(shen)請轉(zhuan)送(song)給網絡(luo)。
為了能和其他廠商的(de)網(wang)絡互連,windows nt允(yun)許有多個轉(zhuan)(zhuan)發(fa)(fa)程序(xu)(xu)。對于每一(yi)個轉(zhuan)(zhuan)發(fa)(fa)程序(xu)(xu)windows nt計算機必須(xu)也有一(yi)個相(xiang)應(ying)(ying)的(de)供(gong)(gong)應(ying)(ying)者(provider)(由網(wang)絡廠商提(ti)供(gong)(gong))。多供(gong)(gong)應(ying)(ying)者路由選擇(ze)程序(xu)(xu)決定適當(dang)的(de)供(gong)(gong)應(ying)(ying)者,然(ran)后(hou)借(jie)助于供(gong)(gong)應(ying)(ying)者,對應(ying)(ying)用請求到相(xiang)應(ying)(ying)的(de)轉(zhuan)(zhuan)發(fa)(fa)程序(xu)(xu)做出(chu)選擇(ze)。windows nt支持(chi)兩種類型(xing)的(de)網(wang)絡驅(qu)動程序(xu)(xu)
傳輸驅動程序
實現數據(ju)鏈路(lu)層(ceng)中的邏輯鏈路(lu)控制子層(ceng)協議和傳輸層(ceng)協議。向 下與ndis接口(kou),向上與tdi接口(kou)。
網卡驅動程序
實現對物(wu)理層的管理和數據鏈(lian)路層中(zhong)介(jie)質訪(fang)問(wen)控制子層協議,通過(guo)ndis向下管理物(wu)理網卡,向上與傳輸驅(qu)動程(cheng)序通信(xin)。
§1.1.3 windows nt網卡(ka)驅動程序
windows nt環境下的網卡驅動程序也分(fen)為兩種(zhong):
miniport網卡驅(qu)動(dong)程(cheng)序(xu)(xu):miniport驅(qu)動(dong)程(cheng)序(xu)(xu)只(zhi)須實現與網絡硬件相關的操作(包(bao)括發送和接收)。而所有底(di)層網卡驅(qu)動(dong)程(cheng)序(xu)(xu)的通用操作(如同步),一般由ndis接口(kou)程(cheng)序(xu)(xu)來實現。
full網卡驅動程序(xu):full網卡驅動程序(xu)必須實現所有硬件相關和同步、排隊等(deng)操作。例(li)如full網卡驅動程序(xu)為了響應數據(ju)接(jie)收(shou),需要保持本身的捆綁信息,而miniport就可(ke)以由ndis接(jie)口庫來實現。
在windows nt的(de)(de)早期版本中(zhong),full網卡驅動程序要求(qiu)開發(fa)者(zhe)實現許多底層操作,來處理(li)多處理(li)器的(de)(de)核心問題(ti)以及處理(li)器、線程的(de)(de)同(tong)步,這(zhe)樣不同(tong)的(de)(de)開發(fa)者(zhe)在大(da)量重復著(zhu)許多相同(tong)的(de)(de)工作。
而miniport網(wang)卡驅(qu)(qu)動(dong)程序允許開發者僅(jin)(jin)僅(jin)(jin)寫一些(xie)與網(wang)絡硬件相關的代碼即可,而那些(xie)通用的函數由ndis接(jie)口庫來(lai)實現,這樣開發出來(lai)的驅(qu)(qu)動(dong)程序減少了(le)不必要的工作(zuo)。
第二節miniport驅動程(cheng)序的結構(gou)
ndis接口規范了網卡(ka)驅(qu)(qu)動(dong)程(cheng)(cheng)序的實現,同時也(ye)對tdi驅(qu)(qu)動(dong)程(cheng)(cheng)序的實現提出了一定的要求,在nt中,ndis約束下的網卡(ka)驅(qu)(qu)動(dong)程(cheng)(cheng)序、tdi驅(qu)(qu)動(dong)程(cheng)(cheng)序和系統(tong)的關(guan)系如下圖所示(shi):
圖2.0 ndis約(yue)束下的網卡驅動程序(xu)、tdi驅動程序(xu)和(he)系統的關系
miniport驅動(dong)程(cheng)序包括驅動(dong)程(cheng)序對象(xiang)、驅動(dong)程(cheng)序源代碼(ma)和ndis接口庫(ku)代碼(ma)。windows nt ddk提供ndis.h作為miniport驅動(dong)程(cheng)序的主要頭文件(jian),定義(yi)了(le)miniport驅動(dong)程(cheng)序的入口點、ndis接口庫(ku)函數和通用數據結構。
上(shang)(shang)邊(bian)緣(yuan)函(han)(han)數(shu)的(de)(de)(de)(de)(de)(de)(de)作用是網(wang)(wang)卡(ka)(ka)(ka)驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)與(yu)ndis接(jie)口(kou)(kou)庫(ku)進行通(tong)信(xin)(xin),而(er)下邊(bian)緣(yuan)函(han)(han)數(shu)是tdi協議驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)與(yu)ndis通(tong)信(xin)(xin)的(de)(de)(de)(de)(de)(de)(de)手段(duan)。ndis用一(yi)(yi)個(ge)(ge)叫做邏輯(ji)網(wang)(wang)卡(ka)(ka)(ka)的(de)(de)(de)(de)(de)(de)(de)軟件對(dui)象(xiang)來描(miao)(miao)(miao)述(shu)系(xi)統(tong)中(zhong)的(de)(de)(de)(de)(de)(de)(de)每塊(kuai)網(wang)(wang)卡(ka)(ka)(ka),而(er)邏輯(ji)網(wang)(wang)卡(ka)(ka)(ka)與(yu)windows nt設(she)(she)備對(dui)象(xiang)的(de)(de)(de)(de)(de)(de)(de)通(tong)信(xin)(xin)由i/o子系(xi)統(tong)來管理,描(miao)(miao)(miao)述(shu)網(wang)(wang)卡(ka)(ka)(ka)的(de)(de)(de)(de)(de)(de)(de)設(she)(she)備對(dui)象(xiang)包(bao)括(kuo)相(xiang)關的(de)(de)(de)(de)(de)(de)(de)網(wang)(wang)絡(luo)信(xin)(xin)息(xi)如(ru)名字、網(wang)(wang)絡(luo)地址(zhi)和(he)(he)網(wang)(wang)卡(ka)(ka)(ka)內(nei)存基地址(zhi)等(deng),它(ta)還包(bao)含與(yu)硬(ying)件相(xiang)關的(de)(de)(de)(de)(de)(de)(de)驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)狀(zhuang)(zhuang)態數(shu)據(捆綁數(shu)目,捆綁句(ju)柄(bing),包(bao)過濾數(shu)據庫(ku)等(deng))。ndis分配一(yi)(yi)個(ge)(ge)句(ju)柄(bing)到miniportinitialize這個(ge)(ge)上(shang)(shang)邊(bian)緣(yuan)函(han)(han)數(shu)的(de)(de)(de)(de)(de)(de)(de)一(yi)(yi)個(ge)(ge)結(jie)(jie)(jie)構(gou)中(zhong),然后miniport網(wang)(wang)卡(ka)(ka)(ka)驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)將在(zai)以后提供這個(ge)(ge)句(ju)柄(bing)來給ndis調(diao)(diao)用,這個(ge)(ge)結(jie)(jie)(jie)構(gou)一(yi)(yi)直被ndis保持(chi)(chi),并(bing)且對(dui)miniport驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)不透明。 當(dang)(dang)miniport網(wang)(wang)卡(ka)(ka)(ka)驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)初始化一(yi)(yi)塊(kuai)網(wang)(wang)卡(ka)(ka)(ka)時(shi),它(ta)創立自(zi)己(ji)的(de)(de)(de)(de)(de)(de)(de)內(nei)部數(shu)據結(jie)(jie)(jie)構(gou)來描(miao)(miao)(miao)述(shu)網(wang)(wang)卡(ka)(ka)(ka),記錄需(xu)要它(ta)管理的(de)(de)(de)(de)(de)(de)(de)與(yu)設(she)(she)備相(xiang)關的(de)(de)(de)(de)(de)(de)(de)狀(zhuang)(zhuang)態信(xin)(xin)息(xi)。當(dang)(dang)miniport網(wang)(wang)卡(ka)(ka)(ka)驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)調(diao)(diao)用ndismsetatttibutes或ndismsetattributesex兩ndis庫(ku)函(han)(han)數(shu)時(shi),它(ta)傳(chuan)遞一(yi)(yi)個(ge)(ge)句(ju)柄(bing)給這數(shu)據結(jie)(jie)(jie)構(gou)。這樣,當(dang)(dang)調(diao)(diao)用miniport驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)入口(kou)(kou)點時(shi),它(ta)就傳(chuan)遞這個(ge)(ge)句(ju)柄(bing)來驗證驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)所對(dui)應(ying)的(de)(de)(de)(de)(de)(de)(de)網(wang)(wang)卡(ka)(ka)(ka)的(de)(de)(de)(de)(de)(de)(de)正確性。這個(ge)(ge)數(shu)據結(jie)(jie)(jie)構(gou)為miniport網(wang)(wang)卡(ka)(ka)(ka)驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)所擁(yong)有并(bing)維護。miniport nic驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)還需(xu)要維護一(yi)(yi)組對(dui)象(xiang),這些對(dui)象(xiang)是系(xi)統(tong)定義的(de)(de)(de)(de)(de)(de)(de)對(dui)象(xiang)標(biao)識符(object idetifier:oid)來標(biao)識,以描(miao)(miao)(miao)述(shu)驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)的(de)(de)(de)(de)(de)(de)(de)性能(neng)和(he)(he)當(dang)(dang)前(qian)狀(zhuang)(zhuang)態信(xin)(xin)息(xi)。為查詢(xun)(xun)這些信(xin)(xin)息(xi),上(shang)(shang)層驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)調(diao)(diao)用ndisrequest向ndis接(jie)口(kou)(kou)庫(ku)指示(shi)oid。oid表示(shi)了調(diao)(diao)用所需(xu)的(de)(de)(de)(de)(de)(de)(de)信(xin)(xin)息(xi)類型,如(ru)miniport驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)所支持(chi)(chi)的(de)(de)(de)(de)(de)(de)(de)lookahead緩(huan)沖區大小等(deng)。ndis接(jie)到上(shang)(shang)層驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)的(de)(de)(de)(de)(de)(de)(de)查詢(xun)(xun)請求,將oid傳(chuan)遞給上(shang)(shang)邊(bian)緣(yuan)函(han)(han)數(shu)miniportqueryinformation實(shi)現(xian)對(dui)oid的(de)(de)(de)(de)(de)(de)(de)查詢(xun)(xun),如(ru)果上(shang)(shang)層驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)請求改(gai)變狀(zhuang)(zhuang)態信(xin)(xin)息(xi)則調(diao)(diao)用miniportsetinformation實(shi)現(xian)對(dui)oid的(de)(de)(de)(de)(de)(de)(de)設(she)(she)置。典型的(de)(de)(de)(de)(de)(de)(de)miniport nic驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)必須(xu)有一(yi)(yi)些函(han)(han)數(shu)來通(tong)過ndis接(jie)口(kou)(kou)實(shi)現(xian)上(shang)(shang)層驅(qu)(qu)(qu)(qu)動(dong)(dong)(dong)(dong)程(cheng)(cheng)(cheng)序(xu)(xu)(xu)(xu)與(yu)硬(ying)件的(de)(de)(de)(de)(de)(de)(de)通(tong)信(xin)(xin)。這些函(han)(han)數(shu)稱為上(shang)(shang)邊(bian)緣(yuan)服務函(han)(han)數(shu)。
這(zhe)些上(shang)邊緣服務函數由驅(qu)動(dong)(dong)程序的(de)(de)開發(fa)者根據驅(qu)動(dong)(dong)程序面向的(de)(de)特定低層(ceng)網絡(luo)類型和硬(ying)件以(yi)(yi)及相(xiang)應環境,可以(yi)(yi)有(you)選擇地(di)實現,但(dan)必須保證驅(qu)動(dong)(dong)程序最基(ji)(ji)本的(de)(de)功能,這(zhe)些基(ji)(ji)本功能包括(kuo)初始(shi)化、發(fa)送、中斷(duan)處理(li)、重置(zhi)、參(can)數查詢(xun)與設置(zhi)和報文接收。
miniportinitialize:操(cao)作系(xi)統根據(ju)系(xi)統配(pei)置信(xin)息,檢測出網(wang)(wang)卡已安裝時,由(you)ndis接口在(zai)初(chu)始化(hua)時調用,主要完成低層網(wang)(wang)絡類型確定,對應(ying)于物理網(wang)(wang)卡的邏輯(ji)網(wang)(wang)卡初(chu)始化(hua),中斷信(xin)息注冊,網(wang)(wang)卡與(yu)主機通訊方(fang)式的確認。i/o端口的申請(qing)與(yu)注冊,內(nei)存(cun)映(ying)像,mib的初(chu)始化(hua),物理網(wang)(wang)卡的驗證(zheng)與(yu)初(chu)始化(hua)等。
miniportreconfigure:支(zhi)持(chi)網卡參數動態(tai)變化,和miniportinitilize一(yi)樣由ndis接口以(yi)初始化級別(bie)調(diao)度執行(不(bu)能屏蔽中斷,必須(xu)由驅動程序(xu)承(cheng)認并清除在(zai)此(ci)期間(jian)產生的(de)中斷),支(zhi)持(chi)即插即用和軟配置的(de)網卡在(zai)動態(tai)改(gai)變參數時,必須(xu)提(ti)供此(ci)函(han)數。
miniportqueryinformation:查詢網(wang)(wang)卡(ka)(ka)(ka)的狀態以及網(wang)(wang)卡(ka)(ka)(ka)驅動程序的操作(zuo)或統計參數,如是否(fou)支持(chi)組通訊、網(wang)(wang)卡(ka)(ka)(ka)的物理速率是否(fou)支持(chi)回環(huan)、是否(fou)支持(chi)直接拷貝等(deng),這些參數以oid方式統一(yi)管理。
miniportsetinformation:ndis接口(kou)或協(xie)議驅動(dong)(dong)程(cheng)序通過調用此(ci)接口(kou)改變驅動(dong)(dong)程(cheng)序維(wei)護的oid庫,一些操作參數的改變也將同時改變驅動(dong)(dong)程(cheng)序狀態,例如(ru)組(zu)地址的設置。
miniportreset:包括(kuo)(kuo)網卡硬(ying)件(jian)重(zhong)(zhong)(zhong)置(zhi)和驅動(dong)程序軟件(jian)重(zhong)(zhong)(zhong)置(zhi),軟件(jian)重(zhong)(zhong)(zhong)置(zhi)包括(kuo)(kuo)驅動(dong)程序狀(zhuang)態重(zhong)(zhong)(zhong)置(zhi),以及(ji)一些相關的(de)參數重(zhong)(zhong)(zhong)置(zhi),還(huan)需考慮有些參數的(de)恢(hui)復,重(zhong)(zhong)(zhong)置(zhi)時不必(bi)完(wan)成(cheng)所(suo)有正(zheng)在活躍的(de)外部(bu)請求(qiu),但必(bi)須釋放已占(zhan)用(yong)的(de)外部(bu)資(zi)源(yuan)。
miniporthalt:掛起網卡并釋放該網卡驅動程序占(zhan)用的所有資源,在此期間不屏蔽(bi)中斷。
miniportisr:高優先級的中(zhong)斷(duan)(duan)處理(li)程序,進行(xing)的工作包括(kuo)初始中(zhong)斷(duan)(duan)處理(li)類(lei)型,決定是(shi)否進行(xing)中(zhong)斷(duan)(duan)轉交,對卡上中(zhong)斷(duan)(duan)進行(xing)處理(li) 等,該服務(wu)類(lei)型只在以下情況被調用(yong):
ndis接(jie)口調用(yong)miniportinitialize和miniporthalt兩函數時。
.中斷處理(li)類型設為(wei)每此中斷處理(li)過程都(dou)調用時。
為使(shi)系統能及時響應所有硬(ying)件中斷,高(gao)優先級的硬(ying)件中斷處理程(cheng)序應盡可能的減少運行時間,防止長(chang)時間的屏蔽低優先級中斷,避免造程(cheng)中斷丟(diu)失。
miniporthandleinterrupt:由中斷(duan)延(yan)(yan)時處理(li)(li)程序在中斷(duan)延(yan)(yan)時處理(li)(li)時進行調用。ndis排隊所有(you)的延(yan)(yan)時處理(li)(li),該服(fu)務主要處理(li)(li)發送完成(cheng)、報(bao)文接收(shou)、描(miao)述(shu)符用盡、溢出、網卡(ka)異常等中斷(duan)。
miniportsend:ndis收到上層發(fa)送請求時經(jing)過(guo)若干(gan)協(xie)議處(chu)理再向下調用此服務過(guo)程,發(fa)送的packet已(yi)含有llc和(he)mac頭(tou),該服務過(guo)程進行邊界(jie)對齊、packet約束重(zhong)整、描述符映(ying)射和(he)報文發(fa)送、以及發(fa)送資源(yuan)和(he)packet緩沖(chong)隊列管(guan)理。
miniporttransferdata:多個已(yi)和網卡捆(kun)綁的協(xie)議驅動(dong)程序(xu)在接(jie)收到(dao)報文到(dao)達(da)指示(shi)后,向(xiang)網卡驅動(dong)程序(xu)發出傳(chuan)送請(qing)求以拷貝(bei)各自(zi)所需的報文數據部分,網卡驅動(dong)程序(xu)根據各協(xie)議驅動(dong)程序(xu)對(dui)單個packet是(shi)(shi)否(fou)進行多次拷貝(bei),以決(jue)定是(shi)(shi)否(fou)暫存只允(yun)許單次拷貝(bei)的packet等。
miniportcheckhandle:ndis每(mei)秒調用此服務函數(shu)一次,驅動程序發現(xian)網卡(ka)異常時報告給ndis由ndis調用miniportreset進行硬件重恢復。
miniportenableintrrupt:中斷(duan)使(shi)能。
miniportdisableinterrupt:中(zhong)斷屏蔽。
另外,每個(ge)網卡驅動(dong)(dong)(dong)程(cheng)序(xu)必須有一(yi)個(ge)初始化(hua)入口(kou)點,由(you)(you)driver entry函(han)數實(shi)現,它和系統(tong)相(xiang)關(guan),由(you)(you)操作系統(tong)在裝(zhuang)入驅動(dong)(dong)(dong)程(cheng)序(xu)時調用,主(zhu)要完成(cheng)(cheng)初始化(hua)ndis wrapper,再由(you)(you)wrapper初始生成(cheng)(cheng)驅動(dong)(dong)(dong)程(cheng)序(xu)管理塊并(bing)完成(cheng)(cheng)相(xiang)應各種初始化(hua)工作,登錄網卡驅動(dong)(dong)(dong)程(cheng)序(xu)所有上邊緣服務入口(kou)點,同時寫入ndis版本信息。ndis接口(kou)庫(ku)包(bao)括(kuo)在ndis.sys中,它是一(yi)個(ge)核態(tai)函(han)數庫(ku),有一(yi)套抽象的函(han)數,無論協(xie)議驅動(dong)(dong)(dong)程(cheng)序(xu)還是nic驅動(dong)(dong)(dong)程(cheng)序(xu)都連接到(dao)這個(ge)庫(ku)中,以(yi)實(shi)現上下層之間的操作。
第二章(zhang)fddi網卡(ka)驅(qu)動程序的(de)加載(zai)和(he)運(yun)行(xing)
第(di)一節 網(wang)卡(ka)驅動程序的安裝
windows nt網卡驅動(dong)程序(xu)(xu)安裝的目的是實現網卡相應硬件信息和驅動(dong)程序(xu)(xu)在windows nt注冊(ce)庫中的注冊(ce),使windows nt能(neng)夠正確識別網卡,了(le)解所必需的軟(ruan)硬件信息并能(neng)在windows nt啟動(dong)時(shi)加載(zai)相應驅動(dong)程序(xu)(xu)。
網(wang)卡(ka)驅(qu)動程序安裝(zhuang)時(shi),首先在(zai)主群組的(de)控制面板中(zhong)選擇“網(wang)絡”,然后添加(jia)網(wang)卡(ka),指定相應信(xin)息文件──oemsetup.inf的(de)路徑,以完成以下兩個(ge)必(bi)要(yao)的(de)操(cao)作:
復制驅動(dong)程序到相應(ying)的系統(tong)目(mu)錄(windows nt根(gen)目(mu)錄system32drivers)中;
在windows nt注冊庫中存入相應軟硬(ying)件信(xin)息。
下面主要(yao)以fddi網卡為例介(jie)紹安裝(zhuang)驅動(dong)程序(xu)所必(bi)需的工作:
§2.1.1網卡(ka)一(yi)般硬件參(can)數(shu)
對于(yu)fddi網卡,必須(xu)在編(bian)寫其oemsetup.inf文(wen)件時確(que)定以下硬(ying)件參數(shu):
總(zong)(zong)線類型:pci(5)……括(kuo)號中的數字5表示pci總(zong)(zong)線在ndis中的總(zong)(zong)線類型代碼;
廠商(shang)代號:0x5588……系統加載時確(que)定(ding)網(wang)卡的標記(ji),也是編程(cheng)時確(que)定(ding)pci槽號的標識(shi);
cfid: 0x01;
介質類型:光纖(3) ……括(kuo)號中的(de)數字表示光纖在ndis中的(de)介質類型代碼;
是否支(zhi)持全雙工:支(zhi)持。
對于其它的(de)(de)硬件(jian)信(xin)(xin)息(xi)(xi)在此inf配(pei)置信(xin)(xin)息(xi)(xi)文件(jian)中(zhong)可有可無,如若(ruo)配(pei)置,則可在驅動(dong)程(cheng)序(xu)的(de)(de)編寫時利用這些信(xin)(xin)息(xi)(xi),方(fang)便編程(cheng),同時有利于其它應用對其參數的(de)(de)確定和使用。網(wang)卡驅動(dong)程(cheng)序(xu)的(de)(de)安裝(zhuang)通常將創建登錄表中(zhong)的(de)(de)四個不(bu)同子(zi)鍵:
software registrion鍵(jian),對應于驅動程序(xu),存在于hkey_local_machinesoftwarecompany productnameversion中。我們的(de)fddi網卡(ka)驅動程序(xu)所對應的(de)是hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;
網(wang)卡(ka)的軟件登(deng)錄(lu)鍵,存在于hkey_local_machinesoftwaremicrosoft windows ntnt3.51networkcardsyhfddi1;
驅動程序的服務登錄鍵(jian),存在于hkey_local_machinesystemcurrentcontrolsetservices
網卡的服務登錄鍵(jian),存在于hkey_local_machinesystemcurrentcontrolsetservices
對(dui)于(yu)每一個網(wang)(wang)絡部件(jian),一個名為netrules的特(te)殊子(zi)鍵在鄰近的驅動(dong)程序或網(wang)(wang)卡登錄(lu)子(zi)鍵里創建,netrules標識網(wang)(wang)絡部件(jian)為網(wang)(wang)絡整體的一部分。
fddi網卡驅(qu)動程序對(dui)應的標準軟(ruan)件登錄表項將出(chu)現在(zai)以下路徑:
hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;
驅動程序對(dui)應的標準項的值為(wei):
description =yhfddi/pci adapter controller
install date =……
……
refcount =0x01
servicename =yhfddi
softwaretype =driver
title =yhfddi/pci adapter controller
而且(qie)在yhfddi驅動(dong)程序相關(guan)的netrules子(zi)鍵下,這些值項為:
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網卡在(zai)如下路(lu)徑的networkcards子鍵(jian)里(li)介(jie)紹:
hkey_local_machinesoftwaremicrosoft
windows ntnt3.51networkcardsyhfddi1;
網卡的(de)標準項包括以下(xia)這些值:
description =yhfddi/pci adapter controller
install date =……
manufacturer =net612
productname =yhfddi
servicename =yhfddi01
title =[01]yhfddi/pci adapter controller
§2.1.3編寫inf信息配置文件(jian)
gui inf描述(shu)語言被windows nt用以(yi)(yi)書寫(xie)系統(tong)所有部(bu)(bu)件(jian)的(de)配(pei)(pei)置(zhi)(zhi)(zhi)(zhi)文(wen)(wen)(wen)件(jian),當(dang)然也可(ke)(ke)以(yi)(yi)用以(yi)(yi)書寫(xie)網絡(luo)(luo)系統(tong)各部(bu)(bu)件(jian)的(de)配(pei)(pei)置(zhi)(zhi)(zhi)(zhi)文(wen)(wen)(wen)件(jian),該(gai)配(pei)(pei)置(zhi)(zhi)(zhi)(zhi)文(wen)(wen)(wen)件(jian)描述(shu)了(le)網絡(luo)(luo)部(bu)(bu)件(jian)安(an)裝、配(pei)(pei)置(zhi)(zhi)(zhi)(zhi)、刪(shan)除(chu)的(de)執行(xing)過程。當(dang)網絡(luo)(luo)部(bu)(bu)件(jian)進行(xing)初(chu)始安(an)裝或二次安(an)裝(通(tong)常(chang)通(tong)過ncpa進行(xing))時,安(an)裝程序讀取部(bu)(bu)件(jian)對應的(de)配(pei)(pei)置(zhi)(zhi)(zhi)(zhi)文(wen)(wen)(wen)件(jian),進行(xing)解釋(shi)執行(xing)。gui inf描述(shu)語言由節(jie)、命(ming)令、邏輯操作、變量規范(fan)、流程控(kong)制以(yi)(yi)及一(yi)套(tao)調(diao)(diao)用dll或外部(bu)(bu)程序的(de)機制組(zu)成,其中,節(jie)是配(pei)(pei)置(zhi)(zhi)(zhi)(zhi)文(wen)(wen)(wen)件(jian)的(de)主體(ti),節(jie)可(ke)(ke)分(fen)為install節(jie)(類似(si)于函數(shu)),shell節(jie)(也類似(si)于函數(shu),但可(ke)(ke)調(diao)(diao)用insall和(he)shell節(jie)),detect節(jie)(不包含命(ming)令),一(yi)個配(pei)(pei)置(zhi)(zhi)(zhi)(zhi)文(wen)(wen)(wen)件(jian)一(yi)般由若干不同類型(xing)的(de)節(jie)組(zu)成。驅動程序的(de)開發者根據需(xu)要可(ke)(ke)以(yi)(yi)在配(pei)(pei)置(zhi)(zhi)(zhi)(zhi)文(wen)(wen)(wen)件(jian)中編寫(xie)相應代碼,使得用戶(hu)和(he)系統(tong)之間能進行(xing)交互,并且由用戶(hu)決定一(yi)些配(pei)(pei)置(zhi)(zhi)(zhi)(zhi)參(can)數(shu)。
nt網卡配置(zhi)(zhi)文件有其一套(tao)規范,驅動程序開發(fa)者必須按(an)規范編寫(xie)配置(zhi)(zhi)文件,一般(ban)來說,一個配置(zhi)(zhi)文件至少應該提供下面三個節:
安裝入口點:[identify]shell節(jie)。該節(jie)主要功(gong)能是給出安裝部件(jian)的類(lei)型名,系統通過它識別該部件(jian)屬于(yu)哪一大類(lei)(display,mouse,scsi,network等)中(zhong)的哪一類(lei)(網絡adapter,driver,transport,service,network和netprovidor),同(tong)時,還需要給出映像文(wen)件(jian)和配置文(wen)件(jian)所在的源介質及標識。
[returnoption]shell節。系(xi)統執行(xing)安裝(zhuang)identify節后,執行(xing)該節。它主要功能(neng)是檢查所(suo)需安裝(zhuang)的部件是否支持(chi)的硬件平臺(tai)和語言(yan),并(bing)給出網卡名(有(you)些(xie)配置文(wen)件支持(chi)多類網卡,此(ci)時(shi)必須讓用戶進(jin)行(xing)選(xuan)擇,并(bing)獲(huo)得選(xuan)擇結果)。
[installoption]shell節(jie)。該節(jie)是(shi)(shi)配(pei)(pei)置文(wen)(wen)件(jian)(jian)得主體(ti),也是(shi)(shi)上次安(an)裝完后再次進行配(pei)(pei)置、刪(shan)除(chu)、更新(xin)的入口點。主要功(gong)能(neng)是(shi)(shi)拷(kao)貝映(ying)像文(wen)(wen)件(jian)(jian)和配(pei)(pei)置文(wen)(wen)件(jian)(jian),生成配(pei)(pei)置的各(ge)種選項,創建該部件(jian)(jian)在(zai)注冊庫中對應(ying)的各(ge)種登錄(lu)子樹并更新(xin)重(zhong)寫。
第二節 驅(qu)動程序(xu)的(de)加(jia)載(zai)過(guo)程
§2.2.1 windows nt的啟動過程