時間:2023-03-02 15:09:19
序論:速發(fā)表網(wǎng)結(jié)合其深厚的文秘經(jīng)驗,特別為您篩選了11篇驅(qū)動程序設計范文。如果您需要更多原創(chuàng)資料,歡迎隨時與我們的客服老師聯(lián)系,希望您能從中汲取靈感和知識!
中圖分類號:TP316文獻標識碼:A文章編號:1009-3044(2011)22-5418-02
Design of USB Device Drver Program on linux
SUN Yong-gang, JIAO Li-fei
(College of Science, GuiZhou University, Guiyang 550025, China)
Abstract:USB interface, with its efficient, reliable and widely is used in various embedded products. However, existing data on linux operating system, more studies USB Host, USB Device driver rarely is done. Therefore this paperthrough a simpleintroduction of USB protocol, as well as analysis of USB driver architecture about linux, is about an design of USB Device driver of linux systemfor embedded microprocessor S3C2440 .
Key words: USB agreement; linux driver;USB device driver
嵌入式產(chǎn)品通過的USB接口品可以很方便與PC的USB進行通信以完成數(shù)據(jù)的傳輸與交互。ARM嵌入式處理器性以其性能高、功耗低而被廣泛地應用于消費電子、工業(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ū)動程序設計。
1 USB體系結(jié)構(gòu)及協(xié)議
1.1 USB硬件系統(tǒng)結(jié)構(gòu)
USB接口是由+5V電源線、電源地線、信號線D+、信號線D-四根電纜線組成接口。其中+5V電源是向設備提供電源,信號線作用是傳輸數(shù)據(jù), 為了提高信號傳輸?shù)目垢蓴_能力這兩根數(shù)據(jù)線采用差分傳輸。主機可以通過D+和D-線的電平高低來確設備是高速設備還是全速設備。
1.2 USB數(shù)據(jù)傳輸通道
USB主機與USB設備由很多端點構(gòu)成,它們之間通過端點進行通訊。通過設置與些端點相對應的寄存器,可以為這些端點分配唯一的地址(由端點號和傳輸方向組成)。USB總線支持四種傳輸類型,他們分別是控制傳輸、同步傳輸、中斷傳輸、批量傳輸。端點O只支持控制傳輸。
1.3 USB總線枚舉
USB總線枚舉就是當USB設備連接到USB主機時,主機通過缺省管道以控制傳輸方式來獲取USB設備發(fā)來的設備描述符、配置描述符、接口描述符、端點描述符信息,并根據(jù)這些描述相關(guān)內(nèi)容對USB設備進行相應的配置。
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設備驅(qū)動處于USB驅(qū)動的最頂層,它主要實現(xiàn)USB設備如何與主機進行通信。處在USB主機控制器驅(qū)動與USB設備驅(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ū)動程序完成設備功能的實現(xiàn)。通過編寫不同Gadget驅(qū)動程序可以使設備具有不同的功能。
3 S3C2440 USB Device驅(qū)動
3.1 S3C2440 USB接口特性
S3C2440嵌入式微處理器集成了一個設備控制器。該設備控制器具有以下特征:
1) 完全兼容USB1.1的協(xié)議。設備全速運行時可達到了12Mb/s。
2) 支持控制、中斷和批量傳輸,批量傳輸支持DMA接口。
3) 自帶5個的端點。端點EP0帶有16byte的FIFO,該端點為雙向的控制端點,其余4個端點都帶有128字節(jié)輸入/輸出的FIFO(異步雙端口RAM)的,支持中斷或DMA批量傳輸。
3.2 S3C2440 USB Device驅(qū)動程序設計
一個完整的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ū)動程序使該設備具有不同的功能。
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ū)動進行注冊。當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注冊設備驅(qū)動程序。
Bind函數(shù)完成這后當有USB Host 向USB設備發(fā)出請求時,Linux系統(tǒng)將調(diào)用setup函數(shù)來響應請求。Setup函數(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ù)注冊后該設備就可以像字符設備那樣使有了。該結(jié)構(gòu)中的一些函數(shù)完成的功能如下:
1) open函數(shù)通過init_waitqueue_head完成等待隊列初始化。
2) read函數(shù)通過alloc_ep_req函數(shù)分配一個讀請求變量,并為該變量中的complete設置一個請求完成函數(shù),調(diào)用usb_ep_queue函數(shù)向端點提交I/O讀請求。當內(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設置一個請求,調(diào)用usb_ep_queue函數(shù)向端點提交I/O寫請求。當內(nèi)核向USB Device寫完數(shù)據(jù)時就會調(diào)有剛才的完成函數(shù)。在完成寫數(shù)據(jù)之前可以通過add_wait_queue和chedule()函數(shù)讓進程掛起,在完成函數(shù)中喚醒掛起的進程。
至此整個驅(qū)動程序就設計完成了,圖2為USB Host 與 USB Device 通信測試效果。
4 結(jié)束語
USB Device 為眾多電子產(chǎn)品提供了一個與PC信息交互的更好的方案。本文通過對USB協(xié)議介紹,以及對Linux下USB驅(qū)動程序進行分析,在此基礎(chǔ)上實現(xiàn)了USB Device驅(qū)動程序進行設計。實踐表明該設計是可行的。
參考文獻:
[1] 馮國進.嵌入式Linux驅(qū)動程序設計從入門到精通[M]北京:清華大學出版社,2008.
[2] 薛園園.USB應用開發(fā)技術(shù)大全[M].北京:人民郵電出版社,2007.
[3] 劉少峰,韋克平.USB軟件系統(tǒng)的開發(fā)[J].計算機應用研究,2002,19(30).
中圖分類號:TP336 文獻標識碼:A 文章編號:1007-9416(2015)05-0000-00
Abstract:This paper introduces the design of Device Drivers of PCI synchronous clock card based on WDF model. Briefly introduces the system architecture and works on our own PCI synchronous clock card, and Analysis the framework of the WDF model and the design process. Focused on the research and development of the WDF Device Drivers based on the PCI synchronous clock card, including hardware access, Interrupt notification. The driver has passed the test for stability and reliability.
Key words: WDF; PCI; interrupt; driver; synchronous clock card.
時間是科學實驗、科學研究和工程技術(shù)等領(lǐng)域中的一個基本物理參量。為了保證系統(tǒng)各部分時間的一致性和正確性,系統(tǒng)內(nèi)各設備的同步時鐘從卡從時鐘源獲取高精度的標準時間,提供給相應設備。這樣系統(tǒng)內(nèi)各設備的時間與時間源相同而保持一致。同步時鐘卡一般采用PCI總線方式。PCI總線能夠?qū)崿F(xiàn)設備間的快速訪問,它以突出的性能受到計算機和通信界工程師們的青睞。
因此如何開發(fā)出穩(wěn)定、可靠、高效的PCI設備驅(qū)動程序成為驅(qū)動工程師們面臨的一個棘手的問題[5]。過去對于PCI設備驅(qū)動程序的開發(fā)大多采用WDM(Windows Driver Model)框架,但是它編程比較復雜,快速掌握其開發(fā)要領(lǐng)對于初學者來說比較困難[5]。本文所述的PCI同步時鐘卡的驅(qū)動程序的開發(fā)采用微軟最新推出的WDF(Windows Driver Foundation)驅(qū)動模型。WDF驅(qū)動模型提供事件驅(qū)動和面向?qū)ο蟮尿?qū)動程序開發(fā)框架,大大降低了設備驅(qū)動程序的開發(fā)難度[5]。
1 同步時鐘卡系統(tǒng)架構(gòu)
本文所述的驅(qū)動程序是基于自行研發(fā)的PCI同步時鐘卡,其原理框圖如圖1所示。本同步時鐘卡選擇PCI9052芯片做為PCI總線的接口芯片。該電路除了用到PCI9052外,還用到了單片機、EEPROM、雙口RAM、CPLD。單片機是系統(tǒng)的控制單元;串行EEPROM存儲了PCI9052芯片所需要的配置信息;雙口RAM用于PC機與時鐘卡之間交換數(shù)據(jù);CPLD用于200us時標的產(chǎn)生和中斷的控制。
同步時鐘卡的工作流程如下:同步時鐘從卡接收時鐘源輸出的時間信號,單片機將其解析成高精度的同步時間信息,控制邏輯(CPLD)通過1PPS脈沖信號產(chǎn)生200us的高精度時間刻度,于是產(chǎn)生高精度的同步絕對時標,連續(xù)存儲于雙口RAM中,最后計算機通過PCI總線接口獲取高精度的絕對時間。本系統(tǒng)中計算機獲取雙口RAM中的時間數(shù)據(jù)的方式有兩種:(1)PC機主動讀取雙口RAM中的數(shù)據(jù)。(2)外部事件通過中斷通知PC機事件發(fā)生,PC機收到通知后讀取雙口RAM中的時間信息,可獲得外部事件發(fā)生的精確時刻。兩種方式分別涉及驅(qū)動程序的硬件訪問和中斷通知。于是涉及到本文介紹的重點:基于WDF模型的PCI總線驅(qū)動程序的開發(fā)。
2 WDF驅(qū)動程序設計
微軟對過去的WDM(Windows Driver Model)驅(qū)動程序的架構(gòu)做了改進,形成了全新的WDF(Windows Driver Foundation)框架結(jié)構(gòu)。它將原來普通軟件開發(fā)中面向?qū)ο蟮募夹g(shù)應用到了驅(qū)動程序的開發(fā)中。WDF改變了驅(qū)動程序與操作系統(tǒng)內(nèi)核之間的關(guān)系,在傳統(tǒng)的WDM驅(qū)動程序中,不僅要處理硬件,還要處理驅(qū)動程序與操作系統(tǒng)內(nèi)核之間的交互[4]。現(xiàn)在WDF則使驅(qū)動程序與操作系統(tǒng)內(nèi)核獨立開來,驅(qū)動程序與操作系統(tǒng)交互工作將由框架內(nèi)封裝的方法(函數(shù))去完成,這樣驅(qū)動開發(fā)工程師只需專注處理目標硬件的行為即可,避免了兩面不周顧此失彼的弊端。不僅大大降低了驅(qū)動程序的代碼量,還使整個系統(tǒng)更加穩(wěn)定、可靠。
WDF驅(qū)動程序包括兩個類型,一個是內(nèi)核級的,稱為KMDF(Kernel-Mode Driver Framework);另一個是用戶級的,稱為UMDF(User-Mode Driver Framework)。本文所述的驅(qū)動程序采用KMDF模式。
2.1 WDF驅(qū)動程序開發(fā)流程
本文所用開發(fā)環(huán)境為Microsoft Windows Driver Kit(WDK) 8.1和Microsoft Visual Studio 2013,操作系統(tǒng)為Windows7。先安裝VS2013,再安裝WDK8.1,便可在VS2013中直接創(chuàng)建KMDF工程。根據(jù)同步時鐘卡所需功能編寫好驅(qū)動程序即可進行編譯。
WDF驅(qū)動程序框圖如圖2所示。
2.2 基于WDF模型的PCI設備驅(qū)動程序的實現(xiàn)
WDF模型的設備驅(qū)動程序從功能上可分為三個部分:初始化設備、控制設置與交換數(shù)據(jù)[3]。初始化設備主要實現(xiàn)設備的識別、驅(qū)動對象與設備對象的建立與硬件資源的分配;控制設置負責應用程序與驅(qū)動程序的連接和設備的打開;交換數(shù)據(jù)處理的是設備功能的具體應用,即PCI總線與同步時鐘卡之間的數(shù)據(jù)傳輸。
從本質(zhì)上來說,WDF模型的設備驅(qū)動程序是由入口函數(shù)DriverEntry和事件例程及其子函數(shù)組成的[3]。操作系統(tǒng)在第一次加載驅(qū)動程序時會通過調(diào)用DriverEntry例程來完成設備驅(qū)動程序和框架的初始化[3]。所有的驅(qū)動程序都必須包含一個DriverEntry例程。對于不同類型的驅(qū)動程序其入口函數(shù)DriverEntry也不同,可分為:設備驅(qū)動、純軟件驅(qū)動與過濾驅(qū)動。本文所述的PCI總線驅(qū)動程序?qū)儆谠O備驅(qū)動,在入口函數(shù)DriverEntry中,主要完成兩件事:注冊EvtDriverDeviceAdd回調(diào)例程、創(chuàng)建和初始化WDFDRIVER對象。
WDF_DRIVER_CONFIG_INIT(&config,PCIdriverEvtDeviceAdd);
//注冊EvtDriverDeviceAdd回調(diào)例程
status = WdfDriverCreate(DriverObject, RegistryPath,...);
//創(chuàng)建驅(qū)動對象
2.2.1初始化設備
在驅(qū)動程序被成功初始化完成之后,操作系統(tǒng)會順序調(diào)用EvtDriverDeviceAdd、EvtDevicePrepareHardware等回調(diào)例程以實現(xiàn)所控制的設備的初始化。
當首次枚舉設備時,EvtDriverDeviceAdd例程在系統(tǒng)初始化時被PnP管理器調(diào)用。在系統(tǒng)運行過程中,任何時候一個新的相同設備被枚舉,系統(tǒng)都將調(diào)用此例程。EvtDriverDeviceAdd例程是設備初始化過程中最新被調(diào)用的回調(diào)例程,它需要完成:設備對象的創(chuàng)建,創(chuàng)建符號鏈接或設備對象GUID接口,創(chuàng)建一個或多個I/O隊列,各種事件的回調(diào)函數(shù)的注冊,如即插即用、電源管理、I/O處理例程等[1]。
EvtDriverDeviceAdd例程的主要代碼如下所示:
注冊即插即用基本例程:
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
pnpPowerCallbacks.EvtDevicePrepareHardware = PCIDriverEvtDevicePrepareHardware;
pnpPowerCallbacks.EvtDeviceReleaseHardware = PCIDriverEvtDeviceReleaseHardware;
..........
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
創(chuàng)建設備對象:
WDF_FILEOBJECT_CONFIG_INIT(&f_config,...);
WdfDeviceInitSetFileObjectConfig(DeviceInit, &f_config,WDF_NO_OBJECT_ATTRIBUTES);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, ..);
status = WdfDeviceCreate(&DeviceInit, &attributes, &control_device);
創(chuàng)建隊列對象并注冊回調(diào)例程:
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,....);
ioQueueConfig.EvtIoDeviceControl = PCIdriverEvtIoDeviceControl;
ioQueueConfig.EvtIoStop = PCIdriverEvtIoStop;
status = WdfIoQueueCreate(control_device,&ioQueueConfig,...);
創(chuàng)建符號鏈接:
status = WdfDeviceCreateSymbolicLink(control_device, &ustring);
創(chuàng)建中斷對象:
deviceContext = GetDeviceContext(control_device);
WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,PCIDriverEvtInterruptIsr,
PCIDriverEvtInterruptDpc);//設置中斷服務例程和延遲過程調(diào)用WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&interruptAttributes,..);
status = WdfInterruptCreate(control_device,&interruptConfig,
&interruptAttributes,&deviceContext->Interrupt);
EvtDriverDeviceAdd例程調(diào)用完成之后,系統(tǒng)將調(diào)用EvtDevicePrepareHardware例程初始化地址指針,將設備所占用的I/O地址和內(nèi)存地址映射為虛擬地址,驅(qū)動程序?qū)⑼ㄟ^這些虛擬地址完成與設備的數(shù)據(jù)傳輸。由于串行EEPROM存儲了PCI9052芯片所需要的配置信息,系統(tǒng)將自動為本文所述的PCI同步時鐘卡分配資源,它們包括雙口RAM的內(nèi)存地址、PCI9052的I/O地址空間,所以EvtDevicePrepareHardware例程必須將這些資源映射為虛擬地址。對于I/O端口,只需將首地址與地址數(shù)目值保存在設備上下文;對于存儲器芯片,調(diào)用MmMapIoSpace函數(shù)將物理地址映射為系統(tǒng)內(nèi)核虛擬地址,然后保存于設備上下文。相對應的,當設備被卸載時,系統(tǒng)會自動調(diào)用EvtDeviceReleaseHardware回調(diào)例程釋放之前申請的硬件資源。
for (i = 0; i < WdfCmResourceListGetCount(ResourceListTranslated); i++) {//WdfCmResourceListGetDescriptor函數(shù)獲取該資源的描述符
descri = WdfCmResourceListGetDescriptor(ResourceListTranslated, i);
switch (descri->Type)
{case CmResourceTypeMemory:
Mem_Count++;
if (Mem_Count == 2)//將雙口RAM地址映射為虛擬地址
{pDevice_context->MemBaseAddress = MmMapIoSpace(
descri->u.Memory.Start,
descri->u.Memory.Length,
MmNonCached);
pDevice_context->MemLength = descri->u.Memory.Length;}
break;
case CmResourceTypePort://將PCI9052的I/O地址映射為虛擬地址
pDevice_context->Io_baseAddress = descri->u.Port.Start.LowPart;
pDevice_context->Io_length = descri->u.Port.Length;
default:
break;}}
2.2.2控制設置與數(shù)據(jù)交換
應用程序?qū)崿F(xiàn)和驅(qū)動程序通信的過程是:應用程序首先調(diào)用CreateFile函數(shù)打開設備,然后可以使用DeviceIoControl和驅(qū)動程序通信,包括寫數(shù)據(jù)給驅(qū)動程序和從驅(qū)動程序讀數(shù)據(jù)兩種情況,也可以用WriteFile寫數(shù)據(jù)給驅(qū)動程序或用ReadFile從驅(qū)動程序讀數(shù)據(jù),當應用程序退出時,調(diào)用用CloseHandle關(guān)閉設備。本文所述的系統(tǒng)是用DeviceIoControl和驅(qū)動程序通信。CreateFile打開設備的方式有兩種:符號鏈接名與GUID接口,本文所述驅(qū)動程序采用的是符號鏈接名的方式。
m_hDevice=CreateFile(sLinkName,...);//以符號鏈接名的方式打開設備
上述代碼中sLinkName為符號鏈接名,它與驅(qū)動程序中設置的符號鏈接名相同。m_hDevice為返回的設備的有效句柄,應用程序就可以應用它調(diào)用DeviceIoControl函數(shù)與驅(qū)動程序交換數(shù)據(jù)。應用程序的請求會被放入請求隊列中,并在EvtIoDeviceControl函數(shù)之中被處理。
本文中應用程序獲取時鐘卡上的時間信息的方式有兩種:(1)直接讀取。(2)中斷方式。
對于第一種方式,應用程序直接調(diào)用DeviceIoControl函數(shù)與驅(qū)動程序交換數(shù)據(jù)。由于系統(tǒng)的雙口RAM被映射到虛擬內(nèi)存,驅(qū)動程序可以使用下面兩條指令對雙口RAM進行讀寫: READ_REGISTER_XXX;//讀雙口RAM,WRITE_REGISTER_XXX;//寫雙口RAM。
對于中斷方式,當被捕獲的外部事件發(fā)生時,驅(qū)動程序會進入中斷服務例程EvtInterruptIsr,然后進入延時過程調(diào)用EvtInterruptDpc,首先清中斷源,然后將雙口RAM中的時間數(shù)據(jù)讀取到設備上下文中緩存,該數(shù)據(jù)即為外部事件發(fā)生的時間,最后通知應用程序讀取該數(shù)據(jù)。應用程序?qū)⒄{(diào)用DeviceIoControl函數(shù)獲取設備上下文中的時間信息。驅(qū)動程序與應用程序通信的方法有兩種:DeviceIoControl異步完成和WIN32事件通知。本文所述系統(tǒng)采用WIN32事件通知的方法。對于此種方法,應用程序初始化時首先生成一個通知事件,并通過DeviceIoControl函數(shù)的輸入緩沖區(qū)發(fā)送給驅(qū)動程序,驅(qū)動程序創(chuàng)建相應的內(nèi)核事件,同時使能PCI9052的LINT1中斷,當該事件發(fā)生時,驅(qū)動程序會通知應用程序,應用程序的一個子線程不停的循環(huán)等待驅(qū)動程序發(fā)來的事件發(fā)生通知。當設備被卸載時需要撤銷該內(nèi)核事件。具體主要代碼如下:
應用程序生成通知事件:
mhEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
應用程序子線程中等待事件發(fā)生:
while (WaitForSingleObject(mhEvent, 0) != WAIT_OBJECT_0)
{...}
驅(qū)動程序創(chuàng)建相應的內(nèi)核事件:
ObReferenceObjectByHandle(....);
允許PCI中斷,使能PCI9052的本地LINT1中斷,pREG為PCI9052映射的I/O空間的基 地址:
inter = READ_PORT_USHORT(pREG + 0x4c);
inter |=0x43;
WRITE_PORT_USHORT(pREG + 0x4c, inter);
清中斷源,設置PCI9052的CS3引腳有效,通知CPLD清掉LINT1信號:
inter = READ_PORT_USHORT(pREG + 0x50);
inter |= 0x800;
WRITE_PORT_USHORT(pREG + 0x50, inter);
驅(qū)動程序給應用程序發(fā)送事件,通知應用程序讀取數(shù)據(jù):
KeSetEvent(pDevice_context->Event, 0, FALSE);
驅(qū)動程序內(nèi)撤銷內(nèi)核事件:
ObDereferenceObject(...);
3 結(jié)語
驅(qū)動程序是硬件與應用程序通信的橋梁,它對系統(tǒng)性能提升的作用舉足輕重。高效、穩(wěn)定、可靠的驅(qū)動程序可以使系統(tǒng)性能得到很好的提升。
本文簡要介紹了PCI同步時鐘從卡的工作原理,并重點討論了基于WDF模型的PCI設備驅(qū)動程序設計方法。本文所述的PCI同步時鐘卡驅(qū)動程序,在WDK8.1中成功編譯,自動生成SYS文件(驅(qū)動程序代碼)和INF文件(設備安裝信息),成功安裝并且能夠穩(wěn)定可靠地運行。經(jīng)測試,捕獲的時間精度達到誤差小于200us,滿足系統(tǒng)設計要求。涉及本驅(qū)動程序的系統(tǒng)已應用于三峽大壩左岸發(fā)電廠發(fā)變機組的故障錄波系統(tǒng)中,運行穩(wěn)定可靠。總而言之,WDF驅(qū)動模型優(yōu)化并簡化了設備驅(qū)動程序的開發(fā),比傳統(tǒng)的WDM驅(qū)動模型更加穩(wěn)定。
參考文獻
[1]武安河.Windows設備驅(qū)動程序WDF開發(fā)[M].北京:電子工業(yè)出版社,2009.
[2][美]Ronald D. Reeves 著,張猛等 譯.Windows設備驅(qū)動程序開發(fā)[M].北京:人民郵電出版社,2012.
TI公司專門推出了PCI2040橋芯片是專門針對PCI總線和DSP接口用的,本文利用它和DSP來處理視頻信號,并用雙端口RAM實現(xiàn)DSP之間的數(shù)據(jù)傳輸。
1硬件設計
1.1PCI總線控制芯片PCI2040
PCI總線是一種不依附于某個具體處理器的局部總線,它支持32位或64位的總線寬度,頻率通常是33MHz,目前最快的PCI2.0總線工作頻率是66MHz。工作在33MHz、32位時,理論上最大數(shù)據(jù)傳輸速率能達到133MB/s。它支持猝發(fā)工作方式,提高了傳輸速度,支持即插即用,PCI部件和驅(qū)動程序可以在各種不同的平臺上運行[1]。
實現(xiàn)PCI總線協(xié)議一般有兩種方法,一是用FPGA設計實現(xiàn),但PCI協(xié)議比較復雜,因此難度較大;二是采用PCI總線控制芯片,如AMCC公司的S5933、PLX公司的PCI9080等通用的PCI接口芯片。TI公司專門推出了針對PCI總線和DSP接口的芯片PCI2040[2],它不但實現(xiàn)了PCI總線控制的功能,而且提供了和DSP芯片無縫的接口,因而大大簡化了系統(tǒng)設計的復雜度并縮短了開發(fā)時間。
PCI2040是一個PCI-DSP橋接器件,它提供了PCI局部總線和TMS320C54X8位主機接口(HPI)與TMS320C6X16位主機接口的無縫連接。一片PCI2040最多能同時掛接4片DSP芯片。同時,它還提供了一個串行EEPROM接口,一個通用輸入輸出接口(GPIO)和一個16位通用總線接口(為TIJTAG測試總線控制器提供接口)[2]。PCI2040只能作為PCI目標設備使用,不能作為PCI主設備使用;它只支持單字的讀寫,不能提供DMA操作。PCI2040能夠兼容3.3V和5V信號環(huán)境系統(tǒng)中的3.3V和5V信號可以直接從PCI插槽中獲得。
PCI2040和TMS320C6201的接口如圖1所示。
1.2PCI2040寄存器說明
PCI2040橋256字節(jié)的配置頭如圖2所示,HPICSR基地址、控制空間基地址(ControlSpaceBaseAddress)值都是系統(tǒng)自動分配的。所有的PNP器件都是如此它將控制空間映射到主機內(nèi)存,映射的空間大小為32KB。4片DSP芯片的選擇是通過解碼PCI_AD14、PCI_AD13來實現(xiàn)的,其對應關(guān)系如表1所示。而DSPHPI寄存器的地址則是由PCI_AD12和PCI_AD11來決定的,其對應關(guān)系如表2所示。
圖1PCI2040和TMS320C6201的接口
表1DSP選擇
AD[14:13]
TMS320C6xDSP
00
HCS0(選擇第一塊DSP)
01
HCS1(選擇第二塊DSP)
10
HCS2(選擇第三塊DSP)
11
HCS3(選擇第四塊DSP)
表1HPI寄存器映射
AD[12:11]
TMS320C6xHPIRegister
00
HPI控制寄存器
01
HPI地址寄存器
10
HPI自增數(shù)據(jù)寄存器
11
HPI數(shù)據(jù)寄存器
因此,DSP與主機交換數(shù)據(jù)的過程,也就是讀寫HPI寄存器的過程。也就是說,通過主機訪問DSP板上資源,只需要將相應地址賦予HPIA寄存器中,然后讀寫數(shù)據(jù)就可以通過HPID寄存器。具體描述如下:
(1)初始化PCI2040內(nèi)部配置寄存器,指向特定的DSP(因為本系統(tǒng)有兩塊DSP和PCI2040相連),指定數(shù)據(jù)傳輸寬度為16位。
(2)分配HPICSR基地址和控制空間基地址,允許PCI2040進行內(nèi)存映射或I/O端口映射。值得注意的是,PCI2040控制空間只能映射在主機的內(nèi)存空間里,不能映射在I/O空間。以上兩步都由驅(qū)動程序完成。
(3)脫離復位狀態(tài)后,PCI2040解碼從PCI總線來的地址,以此來做出響應。若落入32KB的控制空間中,則根據(jù)PCI_AD12、PCI_AD11及PCI_AD14、PCI_AD13片選情況訪問相應HPI寄存器。
(4)設定HPI控制寄存器中的BOB位,選擇正確的高低16位排列方式。
(5)主機開始對HPI寄存器進行讀寫。
1.3雙DSP系統(tǒng)硬件設計
本文所采用的雙DSP系統(tǒng)主要用來處理視頻信號及高速數(shù)據(jù)采集,該系統(tǒng)是基于TMS320C6201DSP和PCI2040而設計的。此卡的主要功能是:(1)采集視頻信號或其他模擬信號經(jīng)A/D轉(zhuǎn)換后,交給DSP進行相應處理,然后將處理后的數(shù)據(jù)通過PCI2040經(jīng)PCI總線存放在計算機硬盤上或者直接存儲到板上RAM中,然后通過PCI總線將視頻數(shù)據(jù)傳送到主機后顯示。(2)兩塊DSP之間的通信可以通過McBSP或雙端口RAM。
該系統(tǒng)的特點有:兩塊TMS320C6201DSP,處理能力可達3200MIPS;每片C6201帶512KSBSRAM,256KBFLASH;16KB高速雙口RAM用于兩塊C6201之間進行數(shù)據(jù)交換;12位ADC;32位高速FIFO。系統(tǒng)硬件框圖如圖3所示。
2基于WDM的PCI驅(qū)動程序設計
WDM是新一代的驅(qū)動程序構(gòu)架,它是一個跨平臺的驅(qū)動程序模型,在WINDOWS98以上的操作系統(tǒng)中都實現(xiàn)了全面兼容。不僅如此,WDM驅(qū)動程序還可以在不修改源代碼的情況下經(jīng)過重新編譯后在非Intel平臺上運行,因而為驅(qū)動程序開發(fā)人員提供了極大的方便。
WDM驅(qū)動程序是分層的,即不同層上的驅(qū)動程序有著不同的優(yōu)先級,而Windows9x下的VxD則沒有此結(jié)構(gòu)。另外,WDM還引入了功能設備對象FDO(FunctionalDeviceObject)與物理設備對象PDO(PhysicalDeviceObject)兩個新概念來描述硬件。PDO代表實際存在的硬件設備,它是在總線驅(qū)動程序(BUSDRIVER)下枚舉并建立的,負責與真實硬件進行I/O操作。FDO是由用戶驅(qū)動程序建立的,一般來說,它是用戶與真實硬件進行I/O操作的一個窗口,是Win32賴以溝通內(nèi)核的一個橋梁。對于驅(qū)動程序開發(fā)者,真正需要做的就是開發(fā)FDO。至于PDO,則由BUSDRIVER建立,并在需要的時候作為參數(shù)由I/OManager或其它系統(tǒng)組件傳給你的FDO。
在應用層與底層進行通訊時,操作系統(tǒng)為每一個用戶請求打包成一個IRP(IORequestPacket)結(jié)構(gòu),將其發(fā)送至驅(qū)動程序,并通過識別IRP中的PDO來識別是發(fā)送給哪一個設備的。另外,WDM不是通過驅(qū)動程序名稱,而是通過一個128位的全局惟一標識符(GUID)來識別驅(qū)動程序的[3]。
WDM驅(qū)動程序都有一個初始化入口點,即DriverEntry,它相當于C語言中的main函數(shù)。當WDM驅(qū)動程序被裝入時,內(nèi)核調(diào)用DriverEntry例程。另外WDM設備驅(qū)動程序還需要一個即插即用模塊,即AddDevice。AddDevice例程就是PnP管理器在用戶插入新設備時調(diào)用它來創(chuàng)建WDM設備對象的。
本文主要采用Windows2000DDK來設計該驅(qū)動程序。調(diào)試工具為SOFTICE。驅(qū)動程序的主要工作集中在:
(1)DriverEntry(),這是驅(qū)動程序的入口點,驅(qū)動程序被裝入時首先執(zhí)行DriverEntry例程。主要工作是建立驅(qū)動程序這所需的函數(shù)。
(2)dspPciAddDevice(),在這個例程里驅(qū)動程序主要是創(chuàng)建設備。
(3)dspPciPnp(),在這個例程中驅(qū)動程序主要是啟動設備和停止設備等,并且從PnP管理器讀出為雙DSP所分配的硬件資源,包括HPICSR基地址和HPI控制空間基地址,對PCI配置空間進行初始化。初始化中斷等。需要注意的是,在初始化中斷之前禁止卡向主機發(fā)中斷,因此應有屏蔽中斷的操作。
(4)dspPciDeviceControl(),在這個例程中可以定制自己的函數(shù)來達到Ring3層和Ring0層相互通訊的目的。通過IOCTL_CODE可以區(qū)分不同的請求。
(5)Isr_Irq(),這個例程是用來處理中斷的。Windows2000的中斷處理機制是假定多個設備可以共享一個硬件中斷。因此,Isr的首要工作就是找出哪一個設備發(fā)生了中斷。如果沒有,則應該立刻返回FALSE,以便HAL能把中斷送往其它設備驅(qū)動程序。中斷服務例程Isr執(zhí)行在提升的IRQL上,在DIRQL級別上運行的代碼需要盡可能快地運行。通常情況下,若判斷中斷是由自己的設備產(chǎn)生的,則調(diào)用一個在DISPATCH_LEVEL級別上運行的延遲過程調(diào)用(DpcFor_Irq)。
中圖分類號:TP311.52
文獻標識碼:B
文章編號:1004―373X(2008)04―063―03
開發(fā)驅(qū)動程序的軟件主要有:MicroSoft公司的DDK,Jungo公司的Windriver和Compuware NuMega公司的Driver Studio三種。DDK是最基本的驅(qū)動程序開發(fā)工具,比較復雜,適于專業(yè)的驅(qū)動程序開發(fā)人員,不適于硬件開發(fā)人員開發(fā)驅(qū)動程序。Windriver開發(fā)驅(qū)動程序不需要熟悉操作系統(tǒng)內(nèi)核知識,針對硬件PCI/ISA/PCM―CIA/USB開發(fā)驅(qū)動程序比較方便,但驅(qū)動程序的效率不高、缺乏靈活性。Driver Studio把DDK用類的形式進行封裝,簡化設備驅(qū)動程序的開發(fā),方便又不失靈活性。所以這里選擇Driver Studio作為驅(qū)動程序的開發(fā)工具。
在結(jié)合PCM高速遙測數(shù)據(jù)發(fā)送卡的基礎(chǔ)上,本文介紹WDM驅(qū)動程序的結(jié)構(gòu)特點和PCM高速遙測數(shù)據(jù)發(fā)送卡的硬件結(jié)構(gòu),并闡述針對數(shù)據(jù)發(fā)送卡的特點,詳細地討論驅(qū)動程序關(guān)鍵部分的設計。
1 PCM遙測數(shù)據(jù)發(fā)送卡的硬件結(jié)構(gòu)
圖1為遙測數(shù)據(jù)發(fā)送卡的原理框圖。碼型變換器的功能是根據(jù)原始PCM數(shù)據(jù)產(chǎn)生3種輸出碼型:NRZ―L,NRZ―M及NRZ―S之一,以適應更加廣泛的測試目的。多電平驅(qū)動器將來自FPGA的LV TTL電平的PCM數(shù)據(jù)和時鐘信號轉(zhuǎn)換為3種電平接口輸出,分別是TTL,EIA422及MLVDS。同步FIFO作為硬件數(shù)據(jù)幀緩存存儲由PCI總線寫入的數(shù)據(jù)幀,然后由序列生成器讀出。序列生成器根據(jù)PCM時鐘速率產(chǎn)生串行移出的PCM原始數(shù)據(jù)將來自FIFO的32位并行數(shù)據(jù)轉(zhuǎn)換為串行輸出,同時根據(jù)移位寄存器的狀態(tài)產(chǎn)生發(fā)向FIFO的讀數(shù)請求:
2 WDM驅(qū)動程序的結(jié)構(gòu)及特點
WDM(Windows Driver Model)是在原有的NT內(nèi)核模式驅(qū)動程序的基礎(chǔ)上發(fā)展來的,他增加了PnP(Plugand Play)、電源管理、WMI(Windows Management Instru―mentation)等功能。WDM模型的層次結(jié)構(gòu)如圖2所示。
層次結(jié)構(gòu)可以使I/O請求過程更加清晰。影響設備的每一個操作都使用I/O請求包(IRP),通常IRP被送到設備堆棧的最上層,然后逐漸過濾到下層驅(qū)動程序。每處理1個IRP,I/O管理器就調(diào)用1次StartIO例程,從而著手IRP處理工作;如何處理完全取決于具體的設備,調(diào)用驅(qū)動程序中相應的例程。驅(qū)動程序處理完IRP后,會將結(jié)果返回給I/O管理器,再由I/O管理器返回給用戶應用程序。
3 PCM遙測數(shù)據(jù)發(fā)送卡WDM驅(qū)動程序的設計
在設備的驅(qū)動程序設計中,需要處理PCI設備的硬件讀寫、中斷處理、DMA等功能??梢园羊?qū)動程序視為一個框架和若干例程的結(jié)合體,各個例程處理不同的IRP,而框架負責在IRP到來時調(diào)用相應的例程。利用Driver―Works的驅(qū)動程序向?qū)?Driver Wizard)新建一個PCI設備驅(qū)動程序框架,然后在這個框架基礎(chǔ)上添加必要的實現(xiàn)功能的處理代碼,就可以完成整個驅(qū)動程序的設計。下面以PCM遙測數(shù)據(jù)發(fā)送卡為例討論其主要的功能驅(qū)動程序例程的實現(xiàn)。
3.1硬件初始化例程
OnStartDevice(KIrp I)參數(shù)例程中包含2種系統(tǒng)分配的資源配置信息:原始的資源配置信息(AllocatedRe―sources);轉(zhuǎn)換后的資源配置信息(AllocatedResourcesTranslated)。因為I/O總線和CPU在尋址物理硬件的方式不同,所以存在2種資源列表。從注冊表、PCI配置空間和其他地方獲取原始的資源值和轉(zhuǎn)換這些值的操作全部由PnP管理器完成,WDM驅(qū)動程序需要做的僅是從設備啟動IRP中獲取這些資源。
3.2 中斷服務例程
中斷服務例程運行在DIRQL級別上,需要盡可能快地運行。本設計在中斷服務例程中,首先判斷中斷是否自己設備產(chǎn)生的,如果是,則調(diào)用一個在DISPATCH_LEV―EL級別上運行的延遲過程調(diào)用(DPC)。當中斷服務例程完成后,一旦處理器獲得DISPATH_LEVEI。運行權(quán),就會運行DPC。中斷服務例程流程圖如3所示。
3.3 中斷延遲調(diào)用例程
在延遲調(diào)用例程中,判斷中斷原因如果是DMA中斷就啟動DMA繼續(xù)發(fā)送。如果是發(fā)送通道中斷,則判斷通道號,并把相應軟件FIFO里面的待發(fā)送數(shù)據(jù)傳送到硬件FIFO里。在此過程中需要檢查在將軟件FIFO中的數(shù)據(jù)寫入硬件FIFO中后,如果軟件FIFO已被讀空,則應禁止通道中斷,否則通道中斷因為優(yōu)先級高,會一直于有效狀態(tài),導致系統(tǒng)死鎖。而在用戶程序?qū)戃浖﨔IFO的處理函數(shù)中,檢查通道中斷,如果被禁止,則應將新寫入軟件FIFO的數(shù)據(jù)讀取一部分寫入硬件FIFO中,然后開啟通道中斷。
3.4應用程序與驅(qū)動程序的通信例程
DeviceControl(KIrp I)主要用于應用程序與驅(qū)動程序之間的通信,如向硬件讀寫數(shù)據(jù)以及軟件FIFO的操作等。DevcieControl響應用戶應用程序DeviceloControl()發(fā)送的IRP,根據(jù)IOCTL代碼來判斷調(diào)用子處理函數(shù)PCI_9054_IOCTL_READ_Handler(I),PCI_9054_IOCTL_WRITE_Handler(I).DEV_IOCTL_TXI_FIFO_WRITE_Handler(I)分別完成對硬件的讀寫和軟件FIFO的寫操作。
3.5 DMA傳輸操作
硬件FIFO半滿時產(chǎn)生通道中斷,在DPC里,判斷是通道中斷,則初始化KDmaTransfer,然后調(diào)用OnD-maReady();在OnDmaReady()中啟動首次DMA傳輸,傳輸時發(fā)生中斷,在DPC中判斷是否DMA中斷,如果是,則調(diào)用Continue()再次啟動下次傳輸,至此全總數(shù)據(jù)傳輸完成。其流程圖如圖4所示。
4 驅(qū)動程序編譯、調(diào)試和安裝
當驅(qū)動程序編寫完成后,必須在DDK環(huán)境下進行編譯,執(zhí)行Rebuild aIl命令,編譯完成后生成*.sys文件和*.inf文件。調(diào)試工具使用Softlce,基本過程如下:
(1)使用Symbol Loader加載驅(qū)動程序*.nms文件,然后激活Softlee,設置斷點跟蹤調(diào)試;
(2)用Genint命令產(chǎn)生虛擬中斷測試,中斷服務例程;
1 USB總線原理
USB 協(xié)議是1994年底由康柏、IBM、英特爾等幾家公司聯(lián)合提出來的外部總線接口協(xié)議。USB就是英文中Universal Serial Bus(通用串行總線)的縮寫。USB總線具有其他總線所不具備的如:熱插拔、數(shù)據(jù)傳輸可靠、擴展方便、成本低等一系列特點,因此在嵌入式系統(tǒng)中被廣泛使用。
一個USB系統(tǒng)一般是由一個USB主機控制器、一個或多個USB集線器和一個或多個USB設備節(jié)點組成。USB系統(tǒng)的物理連接具有層次性。USB總線連接USB設備和USB主機,是一種星型拓撲結(jié)構(gòu)。USB的拓撲結(jié)構(gòu)如圖1所示。
在一個USB系統(tǒng)傳輸數(shù)據(jù)的過程中有兩個非常重要的概念,就是USB傳輸模式和USB描述符。USB傳輸模式是指USB設備傳輸數(shù)據(jù)的形式。USB設備支持四種傳輸模式:控制傳輸模式、同步傳輸模式、中斷傳輸模式和批量傳輸模式??刂苽鬏斈J绞怯脕硖幚鞺SB主端口到USB從端口的數(shù)據(jù)傳輸,主要是設備控制指令、設備查詢狀態(tài)指令和確認指令。同步傳輸模式是指傳輸和時間關(guān)系密切的信息所使用的一種傳輸方式,是一種周期的、連續(xù)的單向傳輸方式。中斷傳輸模式這類傳輸模式主要用于傳輸非周期性的、自然發(fā)生的、數(shù)據(jù)量很小的信息,這類數(shù)據(jù)傳輸?shù)姆较蚴菑脑O備到主機,適用于鍵盤、鼠標、操縱桿等設備上。最后一種是批量傳輸模式,該模式適用于大量的、對時間沒有要求的數(shù)據(jù)傳輸,如U盤或者移動硬盤等設備。
USB設備在邏輯上分為幾個層次,分別是設備層(Device)、配置層(Config)、接口層(Interface)、端點層(Endpoint)。各個層次都有與之相對的描述符,分別是設備描述符、配置描述符、接口描述符和端點描述符。
2 Linux下的USB驅(qū)動框架
USB設備的設備描述符在Linux系統(tǒng)中用usb_device_descriptor結(jié)構(gòu)體表示,它描述了USB設備的一般信息。配置描述符用usb_config_descriptor結(jié)構(gòu)體表示,它給出了USB設備的配置信息。接口驅(qū)動程序是在一個配置內(nèi)給出一個接口信息,它在Linux中由usb_interface_descriptor結(jié)構(gòu)體表示。端口描述符被主機用來決定每個端口的帶寬需求,它在Linux系統(tǒng)中由usb_endpoint_descriptor結(jié)構(gòu)體表示。
編寫一個USB驅(qū)動程序,是從usb_driver結(jié)構(gòu)體開始的。Linux中模塊加載函數(shù)調(diào)用usb_register()和usb_unregister()從而對usb_driver結(jié)構(gòu)體進行加載與卸載。如果某個設備信息與該驅(qū)動中usb_device_id usb_mouse_id_table 結(jié)構(gòu)體的信息相一致,則會調(diào)用usb_driver中探測成員函數(shù)probe(),將初始化USB斷點信息,并對設備做一些初始化工作,分配urb結(jié)構(gòu)體,準備數(shù)據(jù)傳輸。其urb處理大致框架結(jié)構(gòu)如圖2所示。
當鼠標設備在用戶空間打開時,將提交 probe 函數(shù)構(gòu)建的 urb 請求塊,urb 將開始為傳送數(shù)據(jù)而忙碌了。urb 請求塊就像一個裝東西的“袋子”,USB 驅(qū)動程序把“空袋子”提交給 USB core,然后再交給主控制器,主控制器把數(shù)據(jù)放入這個“袋子”后再將裝滿數(shù)據(jù)的“袋子”通過 USB core 交還給 USB 驅(qū)動程序,這樣一次數(shù)據(jù)傳輸就完成了。
3 結(jié)束語
由于USB簡單方便快捷等優(yōu)點,許多外接設備會越來越青睞USB接口,這是一種發(fā)展的趨勢。Linux系統(tǒng)具有開源、安全等特性,用戶也在急劇增加。屆時,會有越來越多的USB驅(qū)動加入Linux內(nèi)核之中。
參考文獻
[1]Jonathan Corbet,Alessandro Rubini,Greg Kroah-Hartman等.LINUX設備驅(qū)動程序[M].北京:中國電力出版社,2006.
[2]Universal Serial Bus Specification Compaq,Intel,Mi―crosoft,NEC Revision 1.1.September 23,1998.
[3]溫卡特斯瓦蘭.精通Linux驅(qū)動程序開發(fā)[M].北京:人民郵電出版,2009.
[4]胡曉軍,張愛成.USB接口卡發(fā)技術(shù)[M].西安:西安電子科技大學出社,2005:15-17.
作者簡介
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)換電路由模擬多路復用器(MUX)、放大器和模數(shù)轉(zhuǎn)換器(ADC)三部分組成。下面描述讀取A/D的三種方法。
圖1所示的是第1種讀取方法。假設A/D轉(zhuǎn)換器的轉(zhuǎn)換時間較慢(5ms以上)。應用程序調(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é)果返回到應用程序(⑤)。
圖2所示的是第2種讀取方法。當模擬轉(zhuǎn)換完成后,ADC產(chǎn)生的個中斷信號。若ADC轉(zhuǎn)換完成,ISR給信號量發(fā)一個信號(⑤),通知驅(qū)動程序,ADC已經(jīng)完成轉(zhuǎn)換。如果ADC在規(guī)定的時限內(nèi)沒有完成轉(zhuǎn)換。信號量超過(③),則驅(qū)動程序不再等待下去。驅(qū)動程序和中斷服務子程序(ISR)的偽代碼如下:
ADRd(ChannelNumber)
{
選擇要讀取的模擬輸入通道;
等待AMUX輸出穩(wěn)定;
啟動ADC轉(zhuǎn)換;
等待來自ADC轉(zhuǎn)換結(jié)束中斷產(chǎn)生的信號量;
if(超時){
*eer=信號錯誤;
return;
}else{
讀取ADC轉(zhuǎn)換結(jié)果并將其返回到應用程序;
}
}
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());
恢復所有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)信號。如果等待時間超過設定的定時值(軟件定時),則結(jié)束等待循環(huán)(循環(huán)等超時)。如果在循環(huán)等待中,檢測到ADC發(fā)出轉(zhuǎn)換結(jié)束的信號(BUSY)時,驅(qū)動程序讀取ADC轉(zhuǎn)換結(jié)果(④)并將結(jié)果返回到應用程序(⑤)。驅(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é)果并將其返回到應用程序;
}
}
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),與標準的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)核具有標準8052的所有外設部件,片上還集成有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(忙標志)的下降沿觸發(fā)中斷,也可用軟件查詢這個狀態(tài)位。
2.3 ADC轉(zhuǎn)換速度
C8051Fxxx系列單片機中ADC的速率都是可編程設置的。表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(復位值)011時鐘頻率>20161xx在C8051F015單片機中,ADC的轉(zhuǎn)換時鐘周期至少在400ns,轉(zhuǎn)換時鐘應不大于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)換時間;不需要增加一個復雜的ISR;轉(zhuǎn)換時信號改變時間更短;CPU的開銷??;循環(huán)檢測程序可被中斷,為中斷信號服務。
圖4 A/D驅(qū)動程序模塊流程圖
3 A/D驅(qū)動程序的編寫
外設驅(qū)動程序是實時內(nèi)核和硬件之間的接口,是連接底層硬件和內(nèi)核的紐帶。編寫驅(qū)動程序模塊應滿足以下主要功能:①對設備初始化;②把數(shù)據(jù)從內(nèi)核傳送到硬件從硬件讀取數(shù)據(jù);③讀取應用程序傳送給設備的數(shù)據(jù)和回送應用程序請求的數(shù)據(jù);④監(jiān)測和處理設備出現(xiàn)的異常。
A/D轉(zhuǎn)換電路作為一個模擬輸入模塊,μC/OS-II內(nèi)核應把它作為一個獨立的任務(以下稱為ADTask())來調(diào)用。A/D驅(qū)動程序模塊流程如圖4所示。ADInit()初始化所有的模擬輸入通道、硬件ADC以及應用程序調(diào)用A/D模塊的參量,并且ADInit()創(chuàng)建任務ADTask()。ADTb1[]是一個模擬輸入通道信息、ADC硬件狀態(tài)等參數(shù)配置以及轉(zhuǎn)換結(jié)果存儲表。ADUpdate()負責讀取所有模擬輸入通道,訪問ADRd()并傳遞給它一個通道數(shù)。ADRd()負責通過多路復用器選擇合適的模擬輸入,啟動并等待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)建任務ADTask()*/
void ADTask (void data);
/*由ADInit()創(chuàng)建,負責更新輸入通道(調(diào)用ADUpdate ())*/
void ADInitI (void);
/*初始化硬件A/D*/
AD_TaskPrio:設置任務ADTask()的優(yōu)先級。
AD_TaskStkSize:設置分配給任務ADTask()的堆棧大小。
AD_MaxNummber:AMUX的輸入通道數(shù)。
AD_TaskDly:設定更新通道的間隔時間。
AD ADTbl[AD_MaxNummber]:AD類型的數(shù)組(AD是定義的數(shù)據(jù)結(jié)構(gòu))。
4 結(jié)論
對于A/D轉(zhuǎn)換器接口電路驅(qū)動程序的編寫歸納出以下幾點:
①在決定采用具體的驅(qū)動方案之前,分析接口電路的特點,尤其是了解A/D的轉(zhuǎn)換速度;
1 PC/104-CAN適配卡的硬件結(jié)構(gòu)
PC/104-CAN適配卡主要由CAN控制器(SJA1000)、光電隔離(6N137),收發(fā)驅(qū)動器(82C250)及譯碼電路組成。編程主要了解的是控制器SJA1000。CAN適配卡原理如圖1所示。
2 CAN地址譯碼和中斷選擇
系統(tǒng)104主板的CPU為486DX,其對接口板訪問有兩種方式:內(nèi)存映射和I/O訪問。I/O尋址采用專門的指令,每次只能傳送單個字節(jié)。內(nèi)存映射方式可以訪問較大的地址空間并且指令豐富,便于實現(xiàn)快速交換數(shù)據(jù)。本文討論的CAN卡采用存映射模式工作,與486DX接口是104總線,它與ISA總線兼容。對于Intel X86體系的CPU,ISA可以映射的空間為0xC8000~0xEFFFF。使用比較器和地址選擇開關(guān)組成可選端口地址譯碼電路,通過開關(guān)選通內(nèi)存映射基地址(C8000H、C9000H、CA000H、…、EF000H),以避免與其它器件沖突。CAN偏移地址分配如下:
00~FFH SJA1000的寄存器;
100H~1FFH 對該范圍內(nèi)的任意地址進行寫操作,均可導致CAN硬件復位。
SJA1000的INT引腳通過跳線選擇IRQ3~7、IRQ9~12或IRQ15中的一個,避免與其它的適配卡沖突。
3 PC/104-CAN適配卡驅(qū)動實現(xiàn)
3.1 VxWorks驅(qū)動概述
VxWorks操作系統(tǒng)有兩種方式實現(xiàn)驅(qū)動。第一種方式是,把設備驅(qū)動程序作為獨立任務實現(xiàn),直接在頂層任務中實現(xiàn)硬件操作,完成特有專用的驅(qū)動程序。第二種方式是,VxWorks的I/O系統(tǒng)將設備程序作為內(nèi)核過程實現(xiàn)。這種方式便于實現(xiàn)I/O子系統(tǒng)的層次模型,便于文件系統(tǒng)一起把設備作為特殊文件處理,提供統(tǒng)一的管理、統(tǒng)一的界面和統(tǒng)一的使用方法,并把設備、文件及網(wǎng)絡通信組織成為一致的更高層次的抽象,為用戶提供統(tǒng)一的系統(tǒng)服務和用戶接口。我們和這種驅(qū)動方式。
作為I/O系統(tǒng)和硬件設備之間的連接層,VxWorks驅(qū)動就是屏蔽硬件操作,為I/O系統(tǒng)提供服務。實現(xiàn)一個完整的驅(qū)動,必須了解VxWorks下I/O的三個基本元素:File、Driver和Dervice。File是為用戶提供訪問設備的統(tǒng)一接口;Driver是實現(xiàn)具體的基本控制函數(shù),也就是實現(xiàn)I/O系統(tǒng)所需要的接口;而Device則是一個抽象的硬件設備,是一系列的結(jié)構(gòu)體、變量和宏定義對實際物理設備的定義。一般而言,實現(xiàn)一個驅(qū)動應該有三個基本的步驟:①用編程語言完成對實際物理設備的抽象;②完成系統(tǒng)所需要的各類接口及自身的特殊接口;③將驅(qū)動集成到操作系統(tǒng)中。之后還有一些調(diào)試工作。
3.2 VxWorks I/O系統(tǒng)驅(qū)動程序框架
VxWorks為各種設備(包括字符設備、塊設備、虛擬設備及網(wǎng)絡設備)提供統(tǒng)一的訪問接口,包括七種基本的I/O函數(shù):open(filename、flags、mode),create(filename、flags),read(fd、&buf、nBytes),write(fd、&buf、nBytes),ioctl(fd、command、arg),close(fd)及remove(filename)。I/O系統(tǒng)所起的作用就是,把用戶請求分配到與設備對應的驅(qū)動例程中去。VxWorks系統(tǒng)中有一個驅(qū)動程序列表,其形式如表1所列。
表1 設備驅(qū)動列表(調(diào)試時可利用iosDrvShow()查看)
驅(qū)動號碼createremoveopenclosereadwriteioctl1
2ca OpenNULLca Openca Closeca Readca Writeca IoctlI/O系統(tǒng)的可動態(tài)調(diào)用iosDrvInstall()函數(shù)將設備的驅(qū)動例程(即XXOpen()、XXClose()、XXRead()等)加入到設備驅(qū)動列表中,如圖2所示。
同樣,系統(tǒng)中有一個設備列表,每個設備對應于設備列表中的一項,每一項包括設備名稱和設備驅(qū)動號,同時包括一個設備描述的結(jié)構(gòu)。該結(jié)構(gòu)第一個變量是DEV_HDR類型的變量DEV_HDR。
DEV_HDR的定義如下:
Typedef struct
{
DL_NODE node; /*設備列表節(jié)點*/
short drvNum; /*驅(qū)動號碼*/
char *name; /*設備名*/
}DEV_HDR;
系統(tǒng)調(diào)用iosDevAdd(),可以將設備加入到設備列表中。系統(tǒng)中將驅(qū)動和設備聯(lián)系起來的就是文件描述符列表,每個文件描述符列表除了包括驅(qū)動號、設備ID外,還包括文件名、可用標志和指向DEV_HDR的指針。系統(tǒng)每次成功執(zhí)行open(),返回一個文件描述符,這樣對于設備的read()、write()及ioctl()就可以通過文件描述符進行。
文件描述符表(調(diào)試時調(diào)用iosFdShow()查看)如下:
I/O系統(tǒng)的整體結(jié)構(gòu)如圖3所示。系統(tǒng)啟動時(一般掛接在usrroot()),XXDrv()和XXDevCreade()便將設備及其驅(qū)動加入相應的列表中。
3.3 設備驅(qū)動程序的訪問過程
下面以CAN驅(qū)動程序為例,說明驅(qū)動程序的訪問過程。(假定設備名“/can/1”并且以CAN設備驅(qū)動程序為例,上述中的XX在這里用Can代替。)
①fd=open(“/can/1”,O_RDWR,0644)
②I/O系統(tǒng)在設備列表中尋找設備名為/can/1的設備項,找到相應的設備驅(qū)動號。
③I/O系統(tǒng)在文件描述符中保留一個文件描述符空間。
④I/O系統(tǒng)在設備驅(qū)動列表中找到對應的CanOpen(CAN_DEV*PCAN_DEV,UBYTE*remainder,int flags),該驅(qū)動例程返回設備描述符的指針。
⑤I/O系統(tǒng)將設備描述符的指針存儲在文件描述符列表的Device ID,同時將對應的設備驅(qū)動號存儲在文件描述符的Driver num項。最后I/O系統(tǒng)返回該描述符項的索引(即為fd)。
⑥這樣應用程序中的read()和write()等函數(shù)調(diào)用就可以根據(jù)fd找到相應的設備驅(qū)動號,進而找到相應的驅(qū)動例程。
4 CAN驅(qū)動程序的實現(xiàn)
CAN驅(qū)動程序的實現(xiàn)即是完成下面七個函數(shù)的編寫。下面簡要介紹其完成的功能,并用偽指令進行說明。
int drv_num; ;/*驅(qū)動號碼*/
typedef struct {
DEV_HDR pCANHDR; /*這個數(shù)據(jù)結(jié)構(gòu)必須放在設備描述符的最初部分*/
/*其余與驅(qū)動有關(guān)數(shù)據(jù)*/
}CAN_DEV; /*CAN設備描述符*/
CAN_DEV can_chan_dev;
STATUS CanDrv(void){
完成驅(qū)動的一些初始化;
intconnect(); /*連接所選的IRQ與中斷處理函數(shù)*/
sysIntEnablePIC(); /*486DX允許中斷*/
drv_num=iosDrvInstall(CanOpen,NULL,CanOpen,CanClose,CanRead,CanWrite,CanIoctl);/*將設備驅(qū)動例程裝入設備列表中*/
}
/*iosDrvInstall()將設備的CAN驅(qū)動例程加入設備驅(qū)動列表中,7個參數(shù)為7個驅(qū)動例程的進入點(entry point),如果沒有某個例程,則傳遞NULL。*/
STATUS CanDevCreate(){
完成一些設備初始化
iosDevAdd (&Can_chan_dev.pCANHDR,“can0”,drv_num);/*將設備放入設備驅(qū)動列表中*/
}
int CanOpen(CAN_DEV *pCan_Dev,UBYTE *remainder,int flags){
CAN卡硬件復位
CAN卡關(guān)中斷
CAN卡進入軟件復位模式
設置CAN卡工作寄存器,如接收碼寄存器和屏蔽碼寄存器等
CAN卡開中斷和進入操作模式
Return((int)pCan_Dev); /*注意必須返回設備描述結(jié)構(gòu)指針*/
}
int CanRead(int CAN_DEV_ID,UBYTE * buf,int nBytes){
等待信號量(該信號量由中斷處理例程釋放)
從接收緩沖區(qū)讀取數(shù)據(jù)
釋放接收緩沖
返回接收數(shù)據(jù)數(shù)量
}
int CanWrite(int CAN_DEV_ID,UBYTE* buf,int nbyte){
查詢發(fā)送緩沖是否可用
向發(fā)送緩沖區(qū)寫數(shù)據(jù)
命令發(fā)送
查詢發(fā)送完成標志
返回發(fā)送數(shù)據(jù)數(shù)量
}
void interrupt_handle_routin(int arg){
處理中斷事件
發(fā)送(釋放)信號量
}
限于篇幅,其它函數(shù)略。
圖3 I/O系統(tǒng)整體結(jié)構(gòu)
5 CAN驅(qū)動調(diào)試
硬件驅(qū)動的調(diào)試是件十分麻煩的事,經(jīng)驗十分重要。這里簡要介紹幾個幫助調(diào)試的函數(shù)。
①可以調(diào)用iosDrvShow()、iosDevShow()及iosFdShow()查看相關(guān)內(nèi)容,判斷并將驅(qū)動及設備中入相應列表。
②使用logMsg()現(xiàn)實相關(guān)內(nèi)容,以定位錯誤。
初期調(diào)試,示波器和信號燈是非常有用的,可以確定硬件的工作狀況,從而有助于發(fā)現(xiàn)程序中的錯誤。
§1.1.1 windows nt網(wǎng)絡體系結(jié)構(gòu)
windows nt的網(wǎng)絡體系結(jié)構(gòu)是基于國際標準化(iso)制定的標準模型──開放式系統(tǒng)互連(open system interconnection:osi)參考模型分層建立的,這種方式有利于隨時擴展其它功能和服務。
windows nt網(wǎng)絡模型開始于mac子層,網(wǎng)卡驅(qū)動程序就駐留在其中。它通過相關(guān)的網(wǎng)卡把windows nt與網(wǎng)絡連接起來,圖中的多個網(wǎng)卡表明在一臺運行windows nt的計算機上能使用多種網(wǎng)卡。
這一網(wǎng)絡體系結(jié)構(gòu)包括兩個重要接口──ndis接口與傳輸驅(qū)動
程序接口(tdi)。這兩個接口把兩個層隔離開來,辦法是相鄰的部件只允許按單一的標準來寫,不允許多重標準。例如一個網(wǎng)卡驅(qū)動程序(在ndis接口的下面)就不需要特地按每個傳輸協(xié)議來寫它的代碼塊,恰恰相反,該驅(qū)動程序是寫給ndis接口的,它通過符合ndis的相應傳輸協(xié)議來請求服務。這些接口包含在windows nt的網(wǎng)絡體系結(jié)構(gòu)中,以容納可移植、可互換的模塊。
在兩個接口之間,是傳輸協(xié)議。它在網(wǎng)絡中起著組織者的作用。一個傳輸協(xié)議規(guī)定了數(shù)據(jù)以何種方式呈遞給下一個接收層,以及如何對數(shù)據(jù)相應地進行打包。它通過ndis把數(shù)據(jù)傳給網(wǎng)卡驅(qū)動程序,并通過tdi把數(shù)據(jù)傳給轉(zhuǎn)發(fā)程序(redirector)
tdi之上是轉(zhuǎn)發(fā)程序,它把本地的網(wǎng)絡資源申請轉(zhuǎn)送給網(wǎng)絡。
為了能和其他廠商的網(wǎng)絡互連,windows nt允許有多個轉(zhuǎn)發(fā)程序。對于每一個轉(zhuǎn)發(fā)程序windows nt計算機必須也有一個相應的供應者(provider)(由網(wǎng)絡廠商提供)。多供應者路由選擇程序決定適當?shù)墓?,然后借助于供應者,對應用請求到相應的轉(zhuǎn)發(fā)程序做出選擇。windows nt支持兩種類型的網(wǎng)絡驅(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)絡硬件相關(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ū)動程序為了響應數(shù)據(jù)接收,需要保持本身的捆綁信息,而miniport就可以由ndis接口庫來實現(xiàn)。
在windows nt的早期版本中,full網(wǎng)卡驅(qū)動程序要求開發(fā)者實現(xiàn)許多底層操作,來處理多處理器的核心問題以及處理器、線程的同步,這樣不同的開發(fā)者在大量重復著許多相同的工作。
而miniport網(wǎng)卡驅(qū)動程序允許開發(fā)者僅僅寫一些與網(wǎng)絡硬件相關(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設備對象的通信由i/o子系統(tǒng)來管理,描述網(wǎng)卡的設備對象包括相關(guān)的網(wǎng)絡信息如名字、網(wǎng)絡地址和網(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ū)動程序不透明。 當miniport網(wǎng)卡驅(qū)動程序初始化一塊網(wǎng)卡時,它創(chuàng)立自己的內(nèi)部數(shù)據(jù)結(jié)構(gòu)來描述網(wǎng)卡,記錄需要它管理的與設備相關(guān)的狀態(tài)信息。當miniport網(wǎng)卡驅(qū)動程序調(diào)用ndismsetatttibutes或ndismsetattributesex兩ndis庫函數(shù)時,它傳遞一個句柄給這數(shù)據(jù)結(jié)構(gòu)。這樣,當調(diào)用miniport驅(qū)動程序入口點時,它就傳遞這個句柄來驗證驅(qū)動程序所對應的網(wǎng)卡的正確性。這個數(shù)據(jù)結(jié)構(gòu)為miniport網(wǎng)卡驅(qū)動程序所擁有并維護。miniport nic驅(qū)動程序還需要維護一組對象,這些對象是系統(tǒng)定義的對象標識符(object idetifier:oid)來標識,以描述驅(qū)動程序的性能和當前狀態(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的設置。典型的miniport nic驅(qū)動程序必須有一些函數(shù)來通過ndis接口實現(xiàn)上層驅(qū)動程序與硬件的通信。這些函數(shù)稱為上邊緣服務函數(shù)。
這些上邊緣服務函數(shù)由驅(qū)動程序的開發(fā)者根據(jù)驅(qū)動程序面向的特定低層網(wǎng)絡類型和硬件以及相應環(huán)境,可以有選擇地實現(xiàn),但必須保證驅(qū)動程序最基本的功能,這些基本功能包括初始化、發(fā)送、中斷處理、重置、參數(shù)查詢與設置和報文接收。
miniportinitialize:操作系統(tǒng)根據(jù)系統(tǒng)配置信息,檢測出網(wǎng)卡已安裝時,由ndis接口在初始化時調(diào)用,主要完成低層網(wǎng)絡類型確定,對應于物理網(wǎng)卡的邏輯網(wǎng)卡初始化,中斷信息注冊,網(wǎng)卡與主機通訊方式的確認。i/o端口的申請與注冊,內(nèi)存映像,mib的初始化,物理網(wǎng)卡的驗證與初始化等。
miniportreconfigure:支持網(wǎng)卡參數(shù)動態(tài)變化,和miniportinitilize一樣由ndis接口以初始化級別調(diào)度執(zhí)行(不能屏蔽中斷,必須由驅(qū)動程序承認并清除在此期間產(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),例如組地址的設置。
miniportreset:包括網(wǎng)卡硬件重置和驅(qū)動程序軟件重置,軟件重置包括驅(qū)動程序狀態(tài)重置,以及一些相關(guān)的參數(shù)重置,還需考慮有些參數(shù)的恢復,重置時不必完成所有正在活躍的外部請求,但必須釋放已占用的外部資源。
miniporthalt:掛起網(wǎng)卡并釋放該網(wǎng)卡驅(qū)動程序占用的所有資源,在此期間不屏蔽中斷。
miniportisr:高優(yōu)先級的中斷處理程序,進行的工作包括初始中斷處理類型,決定是否進行中斷轉(zhuǎn)交,對卡上中斷進行處理 等,該服務類型只在以下情況被調(diào)用:
ndis接口調(diào)用miniportinitialize和miniporthalt兩函數(shù)時。
.中斷處理類型設為每此中斷處理過程都調(diào)用時。
為使系統(tǒng)能及時響應所有硬件中斷,高優(yōu)先級的硬件中斷處理程序應盡可能的減少運行時間,防止長時間的屏蔽低優(yōu)先級中斷,避免造程中斷丟失。
miniporthandleinterrupt:由中斷延時處理程序在中斷延時處理時進行調(diào)用。ndis排隊所有的延時處理,該服務主要處理發(fā)送完成、報文接收、描述符用盡、溢出、網(wǎng)卡異常等中斷。
miniportsend:ndis收到上層發(fā)送請求時經(jīng)過若干協(xié)議處理再向下調(diào)用此服務過程,發(fā)送的packet已含有l(wèi)lc和mac頭,該服務過程進行邊界對齊、packet約束重整、描述符映射和報文發(fā)送、以及發(fā)送資源和packet緩沖隊列管理。
miniporttransferdata:多個已和網(wǎng)卡捆綁的協(xié)議驅(qū)動程序在接收到報文到達指示后,向網(wǎng)卡驅(qū)動程序發(fā)出傳送請求以拷貝各自所需的報文數(shù)據(jù)部分,網(wǎng)卡驅(qū)動程序根據(jù)各協(xié)議驅(qū)動程序?qū)蝹€packet是否進行多次拷貝,以決定是否暫存只允許單次拷貝的packet等。
miniportcheckhandle:ndis每秒調(diào)用此服務函數(shù)一次,驅(qū)動程序發(fā)現(xiàn)網(wǎng)卡異常時報告給ndis由ndis調(diào)用miniportreset進行硬件重恢復。
miniportenableintrrupt:中斷使能。
miniportdisableinterrupt:中斷屏蔽。
另外,每個網(wǎng)卡驅(qū)動程序必須有一個初始化入口點,由driver entry函數(shù)實現(xiàn),它和系統(tǒng)相關(guān),由操作系統(tǒng)在裝入驅(qū)動程序時調(diào)用,主要完成初始化ndis wrapper,再由wrapper初始生成驅(qū)動程序管理塊并完成相應各種初始化工作,登錄網(wǎng)卡驅(qū)動程序所有上邊緣服務入口點,同時寫入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)卡相應硬件信息和驅(qū)動程序在windows nt注冊庫中的注冊,使windows nt能夠正確識別網(wǎng)卡,了解所必需的軟硬件信息并能在windows nt啟動時加載相應驅(qū)動程序。
網(wǎng)卡驅(qū)動程序安裝時,首先在主群組的控制面板中選擇“網(wǎng)絡”,然后添加網(wǎng)卡,指定相應信息文件──oemsetup.inf的路徑,以完成以下兩個必要的操作:
復制驅(qū)動程序到相應的系統(tǒng)目錄(windows nt根目錄system32drivers)中;
在windows nt注冊庫中存入相應軟硬件信息。
下面主要以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)卡的標記,也是編程時確定pci槽號的標識;
cfid: 0x01;
介質(zhì)類型:光纖(3) ……括號中的數(shù)字表示光纖在ndis中的介質(zhì)類型代碼;
是否支持全雙工:支持。
對于其它的硬件信息在此inf配置信息文件中可有可無,如若配置,則可在驅(qū)動程序的編寫時利用這些信息,方便編程,同時有利于其它應用對其參數(shù)的確定和使用。網(wǎng)卡驅(qū)動程序的安裝通常將創(chuàng)建登錄表中的四個不同子鍵:
software registrion鍵,對應于驅(qū)動程序,存在于hkey_local_machinesoftwarecompany productnameversion中。我們的fddi網(wǎng)卡驅(qū)動程序所對應的是hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;
網(wǎng)卡的軟件登錄鍵,存在于hkey_local_machinesoftwaremicrosoft windows ntnt3.51networkcardsyhfddi1;
驅(qū)動程序的服務登錄鍵,存在于hkey_local_machinesystemcurrentcontrolsetservices
網(wǎng)卡的服務登錄鍵,存在于hkey_local_machinesystemcurrentcontrolsetservices
對于每一個網(wǎng)絡部件,一個名為netrules的特殊子鍵在鄰近的驅(qū)動程序或網(wǎng)卡登錄子鍵里創(chuàng)建,netrules標識網(wǎng)絡部件為網(wǎng)絡整體的一部分。
fddi網(wǎng)卡驅(qū)動程序?qū)臉藴受浖卿洷眄棇⒊霈F(xiàn)在以下路徑:
hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;
驅(qū)動程序?qū)臉藴薯椀闹禐椋?/p>
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)卡的標準項包括以下這些值:
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)所有部件的配置文件,當然也可以用以書寫網(wǎng)絡系統(tǒng)各部件的配置文件,該配置文件描述了網(wǎng)絡部件安裝、配置、刪除的執(zhí)行過程。當網(wǎng)絡部件進行初始安裝或二次安裝(通常通過ncpa進行)時,安裝程序讀取部件對應的配置文件,進行解釋執(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ù)需要可以在配置文件中編寫相應代碼,使得用戶和系統(tǒng)之間能進行交互,并且由用戶決定一些配置參數(shù)。
nt網(wǎng)卡配置文件有其一套規(guī)范,驅(qū)動程序開發(fā)者必須按規(guī)范編寫配置文件,一般來說,一個配置文件至少應該提供下面三個節(jié):
安裝入口點:[identify]shell節(jié)。該節(jié)主要功能是給出安裝部件的類型名,系統(tǒng)通過它識別該部件屬于哪一大類(display,mouse,scsi,network等)中的哪一類(網(wǎng)絡adapter,driver,transport,service,network和netprovidor),同時,還需要給出映像文件和配置文件所在的源介質(zhì)及標識。
[returnoption]shell節(jié)。系統(tǒng)執(zhí)行安裝identify節(jié)后,執(zhí)行該節(jié)。它主要功能是檢查所需安裝的部件是否支持的硬件平臺和語言,并給出網(wǎng)卡名(有些配置文件支持多類網(wǎng)卡,此時必須讓用戶進行選擇,并獲得選擇結(jié)果)。
[installoption]shell節(jié)。該節(jié)是配置文件得主體,也是上次安裝完后再次進行配置、刪除、更新的入口點。主要功能是拷貝映像文件和配置文件,生成配置的各種選項,創(chuàng)建該部件在注冊庫中對應的各種登錄子樹并更新重寫。
第二節(jié) 驅(qū)動程序的加載過程
嵌入式系統(tǒng)的組成一般有硬件設備、應用程序、嵌入式微處理器和嵌入式操作系統(tǒng)四個框架。隨著嵌入式技術(shù)的不斷發(fā)展,在移動通信、工業(yè)控制和信息家電等諸多領(lǐng)域都得到了良好的運用。為了滿足嵌入式系統(tǒng)發(fā)展和運用的需要,必須對嵌入式系統(tǒng)軟件的開發(fā)提出更高程度上的要求。
一、不同環(huán)境下嵌入式通信系統(tǒng)的設計標準
(一)在Linux操作系統(tǒng)環(huán)境下的驅(qū)動程序
在Linux操作系統(tǒng)環(huán)境下的驅(qū)動程序要求無論是什么樣的設備都要提供相同的接口,通常情況下是把一個設備映射成為一個設備文件。Linux驅(qū)動程序支持硬件設備下的兩個標準接口:
字符特別設備文件和塊特別設備文件。字符設備接口支持面向?qū)ο笫亲址妮斎?輸出端口的操作,規(guī)定輸入/輸出端口請求的長度一定是設備要求的基本塊長度的倍數(shù)。塊設備接口僅支持輸入/輸出上的操作,而能支持任意位置和長度上的輸入/輸出請求,能滿足隨機存取的要求。其中,Linux設備驅(qū)動程序能分成三個最主要的部分:中斷服務子程序、自動配置和初始化的子程序;服務于輸入/輸出請求的子程序。在Linux系統(tǒng)的內(nèi)部,輸入/輸出數(shù)據(jù)的存取需通過一組特定的入口進行操作,這組入口就是由每個設備的驅(qū)動程序來提供的。
(二)在Windows操作系統(tǒng)環(huán)境下的驅(qū)動程序
微軟公司中的WindowsXP操作系統(tǒng)和Windows2000系列均采取了WDM技術(shù)設備的驅(qū)動程序模型,由原來的Window3.0到現(xiàn)在的WindowsXP和Windows2000,都依據(jù)其特定環(huán)境下的驅(qū)動程序制定了具有標準化的體系結(jié)構(gòu),同時為了滿足驅(qū)動程序開發(fā)時所要調(diào)用的程序,程序員提供了完全的系統(tǒng)數(shù)據(jù)結(jié)構(gòu)和函數(shù)封裝。
在驅(qū)動程序中,每個硬件設備在WDM模型下都至少存在兩個驅(qū)動程序:總棧驅(qū)動程序和功能驅(qū)動程序。而設備還可能在過濾驅(qū)動程序下通過其選擇的特性來改變標準的設備驅(qū)動程序,其中驅(qū)動程序服務于同一個設備的被組成了一個鏈表,叫做設備棧。
例如:在一個驅(qū)動設備程序結(jié)構(gòu)棧中,處于數(shù)據(jù)結(jié)構(gòu)棧最底層的是物理設備對象的物理驅(qū)動程序,被用來描述物理總棧和設備之間的關(guān)系,在物理驅(qū)動程序上是功能設備對象的功能驅(qū)動程序,被用來描述設備中的邏輯功能。在功能驅(qū)動程序周圍,存在很多過濾設備對象中的過濾驅(qū)動程序。因而數(shù)據(jù)結(jié)構(gòu)棧中的每一個對象都有其特定的驅(qū)動程序,其中物理設備對象屬于功能驅(qū)動程序,過濾驅(qū)動設備對象屬于過濾驅(qū)動程序。
(三)嵌入式通信設備下的驅(qū)動程序
不同于上述兩種操作環(huán)境下的驅(qū)動設備程序。
第一,嵌入式系統(tǒng)擁有高效的實時性,在應對外部突發(fā)事件時要求要以微秒級的速度相應,這就需要嵌入式操作系統(tǒng)不能有過于繁瑣的上下文切換和頻率過高的堆棧操作來響應事件操作,故一般嵌入式系統(tǒng)都沒有十分復雜的分層構(gòu)造。
第二,通信設備下的嵌入式系統(tǒng)還具有可配置性和高可靠性以及可裁剪性。這些特性就要求整個系統(tǒng)要有微內(nèi)核結(jié)構(gòu),才能保證模塊間具有很高的獨立性。上述的這些特性共同決定了嵌入式系統(tǒng)不具有供驅(qū)動程序調(diào)用的函數(shù)封裝和定義的設備驅(qū)動模型。但因在標準化的輸入/輸出設備中,只分為塊設備和字符設備,具有局限性,而嵌入式系統(tǒng)所使用的芯片大都為HDLC、TSI等,大部分屬于控制型的芯片,不屬于塊設備和字符設備,無法納入標準的輸入/輸出體系結(jié)構(gòu)中。
第三,嵌入式的設備驅(qū)動程序直接面向的對象是硬件,任何對硬件的不正當操作都可能導致驅(qū)動系統(tǒng)發(fā)生崩潰。所以,在嵌入式系統(tǒng)的開發(fā)過程中,需要制定一套完善的驅(qū)動程序的規(guī)范指導工作人員的開發(fā)工作。
二、關(guān)于通信系統(tǒng)下嵌入式驅(qū)動程序設計的標準化探討
(一)嵌入式系統(tǒng)標準化設計的分層結(jié)構(gòu)
制定關(guān)于通信系統(tǒng)下嵌入式驅(qū)動程序的標準,最終的目的是要制定出一套清晰的驅(qū)動程序的構(gòu)造,用來統(tǒng)一上層應用以及用來管理程序接口,在一定程度上提高驅(qū)動程序的健壯性和可移植性,從而減少重復開發(fā)的可能。設備驅(qū)動程序在結(jié)構(gòu)上可大致分為兩層:接口封裝層和硬件控制層。
接口封裝層是負責把硬件控制層封裝變?yōu)闃藴实膽媒涌?,對其上層的管理軟件提供一致的接口。在接口封裝層,硬件設備中的差異大部分會被屏蔽掉,僅僅體現(xiàn)在應用程序接口的函數(shù)數(shù)據(jù)在結(jié)構(gòu)上的解析;
接口硬件控制層就是把硬件中的各個模塊按功能分給各個控制的接口,處于驅(qū)動程序結(jié)構(gòu)中的最底層,以此來完成對所有硬件設備的配置和控制工作。因硬件控制層是直接面向硬件的,因而與硬件的相關(guān)性最大,也是在所有結(jié)構(gòu)中最為靈活的一層。硬件控制層將所有的硬件設備的作用體現(xiàn)在控制接口上,并由接口封裝層進行了調(diào)用。在考慮了硬件設備的多樣性之后,控制接口的設計并沒有明確的規(guī)范定義接口,但控制接口一般情況下可分為四類:硬件設備的屬性控制、硬件設備初始化、時鐘中斷和設備的輸入/輸出操作。
(二)嵌入式設備驅(qū)動程序標準化設計的要求
接口封裝層對上層軟件提供的所有操作都被叫做元語操作,要特別注意的是接口的重入問題。首先,對控制層的接口來說,均為同步非阻塞函數(shù)的調(diào)用,對輸入/輸出型設備在得到用戶允許的情況下可以提供阻塞的同步接口。嵌入式設備驅(qū)動程序一定要求能夠進行單獨編譯,設計時要優(yōu)先引用操作系統(tǒng)下的抽象層的函數(shù);其次,接口封裝層要盡可能對封裝操作系統(tǒng)庫函數(shù)做出調(diào)用;然后,驅(qū)動程序設計時要充分考慮硬件的特點,不考慮任何狀態(tài)下的同步。
三、結(jié)語
綜上所述,要想實現(xiàn)通信系統(tǒng)下嵌入式驅(qū)動程序的設計,需要一套驅(qū)動程序的標準來規(guī)范,因此提出基于嵌入式通信設備驅(qū)動程序設計標準化的構(gòu)想,定義了較為清晰的分層結(jié)構(gòu),在一定程度上使得通信系統(tǒng)下的嵌入式驅(qū)動程序的設計變得愈加標準化和規(guī)范化。
參考文獻
[1]陳鑫旺,姜秀杰.基于嵌入式Linux和FPGA的數(shù)據(jù)通信系統(tǒng)設計[J].微計算機信息,2013(06).
中圖分類號:TP274.2 文獻標識碼:A 文章編號:1007-9416(2016)04-0000-00
在針對新一代多普勒氣象雷達實現(xiàn)多功能、多模式的目標實現(xiàn)上同時獲得更高質(zhì)量的數(shù)據(jù),對獲取雷達數(shù)據(jù)的速率和容量的要求越來越高。而伴隨軟件無線電技術(shù)的突破,雷達作業(yè)系統(tǒng)將有可能要直接從射頻采樣中獲得更豐富的數(shù)據(jù)。這些氣象雷達領(lǐng)域技術(shù)的發(fā)展,都對雷達高速數(shù)據(jù)采集傳輸提出了新的需求,現(xiàn)有的氣象雷達數(shù)據(jù)傳輸帶寬已經(jīng)不能滿足需要了。對基于計算機平臺的氣象雷達作業(yè)系統(tǒng),提出了關(guān)鍵部件商品斷檔和已有技術(shù)須適應計算機硬件環(huán)境的挑戰(zhàn)。鑒于現(xiàn)階段的各個類型的氣象雷達中,雷達數(shù)據(jù)還主要基于PCI總線進行傳輸,數(shù)據(jù)帶寬已經(jīng)不能適應現(xiàn)代氣象雷達的發(fā)展,為保障已有氣象雷達設備能夠得到后續(xù)升級技術(shù)的儲備,研究氣象雷達數(shù)據(jù)在PCI-Express總線上的技術(shù)[1],將能解決主流計算機淘汰的PCI接口對氣象雷達數(shù)據(jù)處理后續(xù)發(fā)展的問題。
1 氣象雷達信號處理器介紹
該信號處理器是氣象雷達視頻I/Q數(shù)據(jù)采集和系統(tǒng)參數(shù)控制的核心板卡,其主要完成了PC機對中頻I/Q數(shù)據(jù)采集,接收機、發(fā)射機控制功能,其性能的好壞直接影響到了整個雷達系統(tǒng)的正常運行。通過接收串行格式的中頻數(shù)據(jù),并將數(shù)據(jù)按照預先設定進行儲存,經(jīng)由PCI-Express接口定時通知計算機獲取數(shù)據(jù)。也能通過它發(fā)送大量參數(shù)到外部串行接口,對硬件進行指定的參數(shù)傳遞。該雷達信號處理器采用美國PERICOM公司的PI7C9X130作為本地總線和PCI-Express總線的接口。PI7C9X130是一款x4的PCI-Express to PCI-X/PCI橋接芯片,本地端總線頻率最高可達133MHZ,數(shù)據(jù)位寬64bit。PI7C9X130擁有4KB的配置空間,其中前256字節(jié)是和PCI設備功能上是兼容的,其余是PCI-Express擴展配置空間[2]。
2 驅(qū)動程序設計
總線驅(qū)動程序由系統(tǒng)提供,本文只設計了PI7C9X130的功能驅(qū)動程序,它主要由驅(qū)動程序初始化、雙緩沖數(shù)據(jù)傳輸模塊兩部分組成?;舅枷胧牵候?qū)動內(nèi)設置DMA緩存和數(shù)據(jù)緩存(比DMA緩存大),采用中斷方式獲取板卡數(shù)據(jù),當驅(qū)動收到一個外部數(shù)據(jù)中斷時,啟動DMA讀取乒乓FIFO中的數(shù)據(jù)到DMA緩存,每次讀完后,都復制DMA緩存到數(shù)據(jù)緩存區(qū),以匹配DMA傳輸與上層應用程序Read數(shù)據(jù)的速度。
2.1 WDF驅(qū)動程序設計
DriverEntry是驅(qū)動程序的入口函數(shù),負責初始化和構(gòu)造驅(qū)動程序?qū)ο蟆O到y(tǒng)啟動時,如果檢測到PI7C9X130的存在,I/O管理器會創(chuàng)建一個未初始化的驅(qū)動程序?qū)ο蟛⑺鳛橐粋€參數(shù)傳給DriverEntry。DriverEntry根據(jù)這個對象創(chuàng)建WDFDRIVER對象,并注冊DeviceAdd例程并在此例程中進行設備驅(qū)動初始化,包括創(chuàng)建設備擴展對象并分配初始化各個子對象,包括WDFINTERRUPT、WDFQUEUE、WDFDPC、 WDFDMAENABLR等[3]。
2.2 雙緩存數(shù)據(jù)傳輸
功能驅(qū)動正常裝載后,應用程序就可以向驅(qū)動發(fā)起打開中斷請求,數(shù)據(jù)卡在中斷開啟的情況下在獲得數(shù)據(jù)后會產(chǎn)生外部中斷,在驅(qū)動中斷處理服務例程中,排隊一個DMA傳輸DPC(Delayed Procedure Call)事件,進行數(shù)據(jù)傳輸。當DMA完成傳輸,產(chǎn)生DMA完成中斷,通過中斷服務例程排隊一個數(shù)據(jù)復制事件,把DMA緩存的數(shù)據(jù)復制到數(shù)據(jù)緩存中。應用程序只要調(diào)用Read,就可以讀取數(shù)據(jù)緩存中的雷達中頻數(shù)據(jù),而不用擔心因為進程切換等系統(tǒng)因素導致的DMA數(shù)據(jù)傳輸和應用層Read速度不匹配問題。
2.3 內(nèi)核驅(qū)動程序調(diào)試
本文采用微軟隨WDK一起的調(diào)試工具WinDbg調(diào)試驅(qū)動程序。WinDbg是一種內(nèi)核模式和用戶模式的調(diào)試器,可以用來分析故障存儲文件和執(zhí)行驅(qū)動程序代碼。采用雙機調(diào)試:目標機(氣象雷達信號處理器)和主機(運行WinDbg的機器),用串口線連接,主機控制和監(jiān)視目標機上的活動[4]。設置好主機和目標機后,通過WinDbg的命令窗口可以設置斷點、觀察調(diào)試輸出信息或分析目標機藍屏產(chǎn)生的故障存儲文件。
3 結(jié)語
本文介紹了基于PCI-Express總線的氣象雷達信號處理器的驅(qū)動程序開發(fā)。經(jīng)實測,該數(shù)據(jù)處理器穩(wěn)定傳輸速度達到530Mbyte/s,超越原基于PCI總線的數(shù)據(jù)處理器速度,適應氣象雷達大幅度增長的探測原始信息量,為新一代多普勒氣象雷達關(guān)鍵技術(shù)的發(fā)展提供了可行的方案。
參考文獻
[1] 何建新.現(xiàn)代天氣雷達[M].四川:電子科技大學出版社,2004-05.
[2] 孟會,劉雪峰.PCI Express總線技術(shù)分析[J].計算機工程,2006(32):252-258.
[3] 武安河.Windows設備驅(qū)動程序WDF開發(fā)[M].北京.電子工業(yè)出版社,2009
中圖分類號:TP3-4 文獻標識碼:A 文章編號:1007-9599?。?012) 19-0000-02
1 引言
計算機軟件技術(shù)的發(fā)展日新月異,給高等院校相關(guān)專業(yè)的教學帶來了很大的挑戰(zhàn),為了更好地適應不斷變化的社會就業(yè)需求,就必須在傳統(tǒng)的計算機專業(yè)教學模式的基礎(chǔ)上開辟出一條新路。
在這樣的背景下,樂山師范學院計算機科學學院早在2005年就開始開展校企合作辦學,與企業(yè)聯(lián)合培養(yǎng)校企合作方向的學生,至今已是第八屆。相比普通班,校企合作教改班所開設的專業(yè)課程更符合于當前計算機人才市場的需求,典型的特點就是注重對學生的專業(yè)技能尤其是程序設計和軟件開發(fā)能力的系統(tǒng)性培養(yǎng),嚴格按照軟件工程師的培養(yǎng)模式來開展相關(guān)的理論和實踐教學環(huán)節(jié),這在很大程度上改變了以往只注重專業(yè)理論教學的局限性。
在對近幾年教改學生的就業(yè)情況進行分析以后,明確肯定了校企合作教學模式為我院本科人才培養(yǎng)體系的改革起到了決定性的促進作用,學生的專業(yè)技能有了明顯的增強,也大大提高了畢業(yè)生的就業(yè)率。
但與此同時也認識到存在的一些問題:首先,傳統(tǒng)的以程序設計語言語法描述為主線的教學方式,以及模式化的實驗內(nèi)容,使教師在教學過程中容易將重點偏向理論,降低了對學生實踐能力的鍛煉和考核;其次,我們的軟件工程師主要是在教室和機房這樣的環(huán)境下培養(yǎng)出來的,缺乏真刀真槍的實踐鍛煉機會;最后,雖然校企合作人才培養(yǎng)方案的整體實施效果不錯,但也很難培養(yǎng)出高層次的計算機專業(yè)人才。
如果以上幾點不能有效地解決,那么校企合作辦學的成效和前景將受到限制,因此迫切地需要一種途徑去驅(qū)動程序設計類專業(yè)課程的教學模式改革,經(jīng)過長期、反復的思考和摸索,我們認為通過開展學科專業(yè)競賽活動來推動課程教學改革是比較可行的。而在種類繁多的計算機學科專業(yè)競賽中,最權(quán)威、級別最高的就是《ACM/ICPC國際大學生程序設計競賽》。
本教改項目結(jié)合ACM競賽來促進計算機專業(yè)教學體系特別是程序設計類課程的教學改革,教改實施對象主要為計算機科學學院軟件工程專業(yè)方向的學生。首先針對程序設計類課程教學存在的問題以及問題產(chǎn)生的原因進行分析,然后在ACM競賽模式和特點的基礎(chǔ)上,嘗試通過結(jié)合ACM競賽來改革課程開設體系和課程教學模式,最后提出了解決問題的具體措施,并在實際教學應用中取得了一定的成效。
2 當前程序設計類課程教學存在的問題
2.1 人才培養(yǎng)模式陳舊,實踐教學比例不足
在傳統(tǒng)的被動教學模式中,學生缺乏學習主動性、創(chuàng)新性和行業(yè)競爭力。而計算機專業(yè)課程大多屬于實踐型課程,強調(diào)動手能力。為了加深對理論知識的理解,必須提高實踐教學質(zhì)量,理論和實踐教學的學時分配要作適當調(diào)整。
2.2 實踐內(nèi)容模板化,缺乏創(chuàng)新能力的培養(yǎng)
首先,設計性、綜合性實驗偏少,很難培養(yǎng)學生的創(chuàng)造性思維;其次,實驗內(nèi)容嚴重脫離了現(xiàn)代軟件工程過程,更談不上對綜合型應用問題的解決;最后,在實踐教學過程中,教師干預太多,學生處于被動完成實驗任務的角色。
2.3 缺乏互助學習能力,團隊協(xié)作意識較差
當前軟件項目的開發(fā)都是以團隊形式實施的,團隊成員之間需要合理分工和無障礙溝通。但在傳統(tǒng)教學模式中,以項目組為單位來開展教學活動的機會非常少,更談不上互助學習和團隊協(xié)作了。
2.4 課程考核模式單一,缺乏激勵機制
課程考核主要采用傳統(tǒng)考核模式,考核內(nèi)容受限于教材知識點,缺乏對學生知識結(jié)構(gòu)與實踐技能的綜合考察,不利于學生綜合實踐能力和創(chuàng)新能力的培養(yǎng),最終形成“高分低能”的現(xiàn)象。
3 改革措施
本教改項目主要通過以下幾個方面來實施以ACM競賽促進程序設計類課程教學改革的方案。
3.1 改革課程開設計劃
全面分析了目前程序設計類專業(yè)課程教學中存在的一些問題(比如教法和學法等方面),結(jié)合ACM的競賽大綱和競賽模式來調(diào)整開課計劃,把原計劃一學期的《程序設計基礎(chǔ)》課程的教學時間調(diào)整為一學年,第一學期是程序設計的入門教學,主要介紹高級程序設計語言編程基礎(chǔ);第二學期是程序設計的進階教學,主要介紹算法設計與分析。
3.2 改革課程實踐教學模式[1]
(1)實驗內(nèi)容分級化:
將實驗內(nèi)容分成知識型(單一算法)、應用型(算法和實際問題結(jié)合)和綜合型(若干小算法的綜合,用于解決一個較大規(guī)模的問題)。不同級別題型的權(quán)值不同,每一級別中又包含若干個相同權(quán)值的題目,學生可以根據(jù)自身情況選擇不同級別的題型和題目數(shù)量,這樣既考慮到了不同層次學生的學習需求,又達到了統(tǒng)一的實驗目的。
(2)實驗題目趣味化:
傳統(tǒng)的程序設計類實驗題目普遍比較枯燥,難以調(diào)動學生的學習興趣和設計思路。參考ACM的海量題集,由任課教師將實驗題目生活化和趣味化,使學生自主選擇合理的數(shù)據(jù)結(jié)構(gòu)和算法來解題,這樣可以充分激發(fā)學生的學習主動性和積極性,將被動學習轉(zhuǎn)化為主動學習,更好地達到了實踐教學的目的。
(3)實驗時間分散化:
考慮到實驗課時非常有限,可參照ACM競賽平臺來構(gòu)建“程序設計在線評測系統(tǒng)”,功能包括用戶管理、題庫管理、在線提交、在線排名、在線討論等。學生注冊后可在任何時間登陸該系統(tǒng)進行選題、提交、評測和討論等自主學習環(huán)節(jié),將有限的課內(nèi)練習時間延續(xù)到課外。
3.3 開發(fā)資源網(wǎng)站
在全面搜集ACM競賽相關(guān)資源的前提下,以程序員協(xié)會的學生會員為主力設計并開發(fā)了“ACM資源網(wǎng)站”,并掛靠在學院的Web服務器上,以該資源網(wǎng)為平臺來開展競賽的宣傳、組織、培訓等活動,同時也為相關(guān)課程的理論實踐教學和學生自主學習提供了一個優(yōu)質(zhì)的信息化平臺。
3.4 建設學生梯隊
依托于樂山師范學院第二課堂課程《ACM程序設計》的開設,以樂山師范學院三星級社團“程序員協(xié)會”為活動主體,在全校范圍內(nèi)吸納對計算機編程和競賽感興趣的學生,成立“ACM競賽興趣小組”,通過舉辦專業(yè)講座、學生科研、協(xié)會內(nèi)部競賽、協(xié)會沙龍等活動,為本專業(yè)學生提供一個進一步增強職業(yè)技能的交流和學習平臺,同時也要在興趣小組中發(fā)現(xiàn)適合參加ACM競賽的后備人才,面向各年級構(gòu)建ACM競賽梯隊。
3.5 建立激勵機制
增設創(chuàng)新學分,設置創(chuàng)新環(huán)節(jié),搭建創(chuàng)新實踐的平臺,讓學生有更多的機會展示自己的專業(yè)特長。將參加ACM等學科競賽納入學生的綜合測評,通過設立競賽獎學金制度來引導學生積極參加課外科技活動、不斷提高自身的創(chuàng)新素質(zhì)。
3.6 組織參賽
在本教改項目的實施過程中,還要積極組織學生參加各個級別的ACM賽事。對于每一次競賽,首先成立競賽領(lǐng)導小組,分析官方公布的競賽大綱,及時、準確地改革專業(yè)教學體系目標和課程開設計劃;其次根據(jù)往屆參賽經(jīng)驗,結(jié)合本次競賽的具體情況制定出競賽活動方案,將競賽的宣傳、組織、選拔、培訓、參賽、獎勵等環(huán)節(jié)制度化;然后選拔ACM參賽隊伍,指派經(jīng)驗豐富且取得過優(yōu)異成績的教練對參賽隊員進行長期、深入、全方位的強化培訓和指導;最后通過對競賽成績的分析再次調(diào)整專業(yè)課程開設計劃和教學模式。[2]
3.7 改革考核手段
ACM模式的重要特色之一是完善而嚴謹?shù)目己藱C制,所以我們大膽嘗試將ACM的考核方式借鑒到程序設計類課程的考核環(huán)節(jié)中,采用ACM模式的黑箱測試,將學生在“程序設計在線評測系統(tǒng)”中獲得的成績以50%的權(quán)重加入到課程考核指標當中。這一方面減少了教師的工作量,降低了考核錯誤率,另一方面做到了客觀、公正,更好地發(fā)掘了學生的創(chuàng)新能力,提高其對知識點的掌握程度。
4 要解決的關(guān)鍵問題
4.1 課程教學形式的改革,特別是如何處理實踐教學和理論教學的比重關(guān)系,以及如何讓學生能夠真正地解決問題,而不是按照設定好的思路去模仿著解決問題。
4.2 課程評價體系的改革,尤其是目前的實踐環(huán)節(jié)評價機制弊端明顯,嚴重束縛了學生的創(chuàng)新能力,錯誤地引導學生把自己改造為一個受制于理論教材的傀儡。
4.3 差異化教學,考慮到ACM競賽的難度較大,所以必須考慮到在將ACM融入到專業(yè)課程教學過程之后,如何確保整體教學質(zhì)量并解決好部分學生學習能力較差的問題。
4.4 在ACM競賽中取得更好的成績,必須建立有效的組織、選拔、培訓、參賽、總結(jié)等相關(guān)機制。
5 結(jié)語
ACM競賽對程序設計類專業(yè)課程的教學改革起到了積極的推動作用,從教學隊伍建設的角度來看,它在提高教師的教學水平、科研能力、促進專業(yè)的對外交流等方面都起到了重要的作用;從學生培養(yǎng)的角度來看,它在提高學生的學習興趣、自學能力、創(chuàng)新能力、求真務實的科學態(tài)度上有很大的幫助。
總之,通過合理的應用ACM競賽這個平臺,可以使我們的計算機專業(yè)教學更趨科學化、規(guī)范化,可以讓我們的學生開拓視野,促進實踐型、創(chuàng)新型人才的培養(yǎng),提高學生的就業(yè)競爭力。
參考文獻:
[1]常子楠.基于ACM模式的程序設計類課程實踐教學探索[J].計算機教育,2010(16):144-146.
[2]項煒.以學科競賽促進計算機專業(yè)教學改革的探索[J].改革與開放,2009(12):207.