緒論:寫作既是個人情感的抒發,也是對學術真理的探索,歡迎閱讀由發表云整理的11篇驅動程序設計范文,希望它們能為您的寫作提供參考和啟發。
中圖分類號:TP316文獻標識碼:A文章編號:1009-3044(2011)22-5418-02
Design of USB Device Drver Program on linux
SUN Yong-gang, JIAO Li-fei
(College of Science, GuiZhou University, Guiyang 550025, China)
Abstract:USB interface, with its efficient, reliable and widely is used in various embedded products. However, existing data on linux operating system, more studies USB Host, USB Device driver rarely is done. Therefore this paperthrough a simpleintroduction of USB protocol, as well as analysis of USB driver architecture about linux, is about an design of USB Device driver of linux systemfor embedded microprocessor S3C2440 .
Key words: USB agreement; linux driver;USB device driver
嵌入式產品通過的USB接口品可以很方便與PC的USB進行通信以完成數據的傳輸與交互。ARM嵌入式處理器性以其性能高、功耗低而被廣泛地應用于消費電子、工業控制等眾多領域。以ARM內核為核心集成了USB功能的處理器使得產品更簡潔、更靈活、更方便。S3C2440集成了ARM920T內核,帶MMU功能,可運行linux操作系統,同時帶有兩個USB Host一個USB Device控制器,因此在此基礎上完成Linux 下的USB Device驅動程序有著重要的意義。本文是以此處理器為核心的嵌入式智能終端的Linux下的USB Device驅動程序設計。
1 USB體系結構及協議
1.1 USB硬件系統結構
USB接口是由+5V電源線、電源地線、信號線D+、信號線D-四根電纜線組成接口。其中+5V電源是向設備提供電源,信號線作用是傳輸數據, 為了提高信號傳輸的抗干擾能力這兩根數據線采用差分傳輸。主機可以通過D+和D-線的電平高低來確設備是高速設備還是全速設備。
1.2 USB數據傳輸通道
USB主機與USB設備由很多端點構成,它們之間通過端點進行通訊。通過設置與些端點相對應的寄存器,可以為這些端點分配唯一的地址(由端點號和傳輸方向組成)。USB總線支持四種傳輸類型,他們分別是控制傳輸、同步傳輸、中斷傳輸、批量傳輸。端點O只支持控制傳輸。
1.3 USB總線枚舉
USB總線枚舉就是當USB設備連接到USB主機時,主機通過缺省管道以控制傳輸方式來獲取USB設備發來的設備描述符、配置描述符、接口描述符、端點描述符信息,并根據這些描述相關內容對USB設備進行相應的配置。
2 Linux USB 驅動程序
在Linux系統中,USB驅動程序可以分為USB Host驅動程序和USB Device驅動程序。Linux USB Host驅動程序和USB Device驅動程序總體架構如圖1所示。
從圖1可以知,在Linux USB Host中,USB控制器驅動是運行在USB 控制器硬件上面的的驅動動程序。該驅動實現了對USB 控制器硬件進行控制,一般稱為USB固件驅動程序。USB設備驅動處于USB驅動的最頂層,它主要實現USB設備如何與主機進行通信。處在USB主機控制器驅動與USB設備驅動之間的是USB核心層,起到驅動程序橋梁的作用,該核心層為USB主機USB主機控制器驅動提供編程接口。
Linux系統中, USB Device驅動分為UDC驅動、Gadget API、Gadget驅動三個層次結構。UDC驅動處USB Device控制器硬件之上,該驅動程序控制USB控制器硬件工作,同時向上層提供操作USB控制器硬件的回調函數。處在中間層的是Gadget API層,該API向下層和上層提供統一的編程接函數的封裝。Gadget驅動程序完成設備功能的實現。通過編寫不同Gadget驅動程序可以使設備具有不同的功能。
3 S3C2440 USB Device驅動
3.1 S3C2440 USB接口特性
S3C2440嵌入式微處理器集成了一個設備控制器。該設備控制器具有以下特征:
1) 完全兼容USB1.1的協議。設備全速運行時可達到了12Mb/s。
2) 支持控制、中斷和批量傳輸,批量傳輸支持DMA接口。
3) 自帶5個的端點。端點EP0帶有16byte的FIFO,該端點為雙向的控制端點,其余4個端點都帶有128字節輸入/輸出的FIFO(異步雙端口RAM)的,支持中斷或DMA批量傳輸。
3.2 S3C2440 USB Device驅動程序設計
一個完整的S3C2440 USB Device驅動程序由S3C2440_UDA驅動和gadget驅動兩部分構成。S3C2440_UDA驅動是用來控制S3C2440的USB Device硬件控制器器,并把對硬件控制操作抽象為函數接口供上層調用。USB gedget驅動程序運行在S3C2440_UDA驅動程序之上的,不同的gedget驅動程序使該設備具有不同的功能。
Linux gadget驅動程序主要涉及到2個重要的結構體usb_gadget_driver和struct file_operations結構。其中usb_gadget_driver結構體包括bind、setup、disconnect等一些函數。Linux Gadget提供usb_gadget_register_driver函數對Gaget驅動進行注冊。當Gadget驅動被注冊后,Linux內核就會調用結構體usb_gadget_driver中的bind函數把Gadget驅動與UDA驅動進行綁定,這樣就可以在Gadget驅動中使用UDA提供的統一接口函數。
bind函數中需要完成以下工作:
1) 使用usb_ep_autoconfig函數申請以后用到的傳輸端點。
2) 通過usb_ep_alloc_request函數為Gadget驅動分配一個請求。
3) 通過調用register_chrdev_region注冊設備驅動程序。
Bind函數完成這后當有USB Host 向USB設備發出請求時,Linux系統將調用setup函數來響應請求。Setup函數把設備的設備描述符、配置描述符、接口描述符以及以后需要使用的幾個端點描述符發送給USB Host,這些配置信息的發送都是通過usb_ep_queue函數來完的。
struct file_operations結構包含有open、read、write等函數。通過該結構體定義的變量被register_chrdev_region函數注冊后該設備就可以像字符設備那樣使有了。該結構中的一些函數完成的功能如下:
1) open函數通過init_waitqueue_head完成等待隊列初始化。
2) read函數通過alloc_ep_req函數分配一個讀請求變量,并為該變量中的complete設置一個請求完成函數,調用usb_ep_queue函數向端點提交I/O讀請求。當內核從USB Device讀到數據時就會調有剛才的完成函數。在完成讀數據之前可以通過add_wait_queue和schedule()函數讓進程掛起,在完成函數中喚醒掛起的進程。
3) write函數通過alloc_ep_req函數分配一個寫請求變量,并為該變量中的complete設置一個請求,調用usb_ep_queue函數向端點提交I/O寫請求。當內核向USB Device寫完數據時就會調有剛才的完成函數。在完成寫數據之前可以通過add_wait_queue和chedule()函數讓進程掛起,在完成函數中喚醒掛起的進程。
至此整個驅動程序就設計完成了,圖2為USB Host 與 USB Device 通信測試效果。
4 結束語
USB Device 為眾多電子產品提供了一個與PC信息交互的更好的方案。本文通過對USB協議介紹,以及對Linux下USB驅動程序進行分析,在此基礎上實現了USB Device驅動程序進行設計。實踐表明該設計是可行的。
參考文獻:
[1] 馮國進.嵌入式Linux驅動程序設計從入門到精通[M]北京:清華大學出版社,2008.
[2] 薛園園.USB應用開發技術大全[M].北京:人民郵電出版社,2007.
[3] 劉少峰,韋克平.USB軟件系統的開發[J].計算機應用研究,2002,19(30).
中圖分類號: TN964?34 文獻標識碼: A 文章編號: 1004?373X(2013)18?0051?04
0 引 言
設備互聯(PCI)總線是一種先進的高性能局部總線,可同時支持多組設備[1]。CPCI總線應用于工業和嵌入式領域,其規范改進自PCI規范,CPCI規范在電氣方面兼容PCI規范,只是在封裝結構上進行了加強,CPCI板的封裝結構基于IEC 60297?3,IEC 60297?4以及IEEE 1101.10定義的歐式板卡外形[2]。既然電氣特性上兼容PCI規范,因此CPCI驅動程序的設計本質就是PCI驅動程序設計。
當前Windows環境下用于PCI設備驅動開發的工具主要是DDK,DriverStudio以及WinDriver。前兩者功能強大,但是開發者需要熟知操作系統的體系結構、匯編語言和設備驅動程序結構體系方法,還需要具備豐富的驅動程序開發經驗,否則可能造成軟件不穩定甚至系統崩潰,另外前兩者開發周期長。而Jungo公司開發的WinDriver改變了傳統的驅動程序開發方法,其整個驅動程序中的所有函數都是工作在用戶態下,使開發者不需要掌握前兩者所需的預備知識就可以開發出與之相媲美的程序[3]。
為了實現在主控計算機和信號處理板之間快速通信,采用了CPCI并行總線技術,信號處理板采用內嵌PCI模塊的DSP6416芯片。軟件開發基于Windows平臺和VC++6.0編程環境,為了便于應用程序調用驅動程序,按照模塊化的軟件設計思想,驅動程序以DLL動態鏈接庫的形式封裝。為提高工作效率、縮短開發周期,開發工具選用WinDriver。
1 WinDriver簡介
WinDriver是一套設備驅動程序開發組件,它的目的就是方便程序員快速開發出PCI,ISA,CPCI,PCIE等設備的Windows驅動程序[4]。
1.1 WinDriver原理
WinDriver的體系架構分為兩種模式:用戶模式和內核模式。對硬件進行操作時,開發者應用程序調用WinDriver用戶模式的庫函數,用戶模式的庫函數再調用WinDriver內核,WinDriver內核再調用操作系統底層函數實現對硬件的最終訪問。其與硬件模板、用戶驅動程序、用戶應用程序之間的關系即體系架構見圖1[5?6]。對于某些在用戶模式下不能實現的高性能硬件驅動程序,可通過WinDriver的內核插件功能實現:在用戶模式下完成編程和調試,不做任何修改,直接將該高性能要求的程序模塊植入內核插件,WinDriver即從內核模式下調用該程序模塊。
1.2 WinDriver特點
作為一款實用的驅動程序開發工具包,WinDriver的主要優點和特征如下:
(1)通過內核插件功能(Kernel PlugIn)能夠實現用戶模式的易用和內核模式的高性能;
(2)友好的驅動向導允許不寫一行代碼即可實現硬件診斷;
(3)支持所有PCI/PCMCIA/CardBus/ISA/EISA/CompactPCI/PCIExpress設備,與制造商無關;
(4)可以利用常見的軟件開發平臺包括MSDEV/VisualC/C++,Borland Delphi,Visual Basic6.0等;
(5)開發者不需要知道DDK,ETK,DDI及任何其他系統層面的編程知識;
(6)支持I/O、DMA中斷處理和直接訪問板卡映射的存儲器;
(7)支持多CPU及多PCI總線平臺。
1.3 用WinDriver開發驅動程序
利用WinDriver開發驅動程序有2種方式:通過驅動程序向導生成驅動程序框架,再對框架程序進行修改和調試;直接編寫驅動程序。
通過驅動程序向導開發步驟:板卡檢測、診斷;生成驅動程序框架;調試、編譯驅動程序。
直接編寫代碼方式步驟:
(1)包含WinDriver相關的頭文件;
(2)WinDriver庫函數調用,WinDriver庫函數典型調用流程見圖2[7]。
2 CPCI信號處理板卡驅動程序設計
2.1 硬件環境
實現PCI總線協議一般有2種方法:一是用FPGA設計實現,由于PCI協議比較復雜,實現較困難;二是采用專業PCI總線控制芯片,如AMCC公司的S5933、PLX公司的PCI 9080等通用PCI接口芯片[8]。本信號處理板采用第二種方法,選用自帶PCI接口模塊的DSP6416,主控計算機上的應用程序通過驅動程序將控制命令字主動寫入DSP內存,實現主控計算機對信號處理板的控制;信號處理板結果數據處理完畢后,向主控計算機發中斷,驅動程序響應該中斷,并主動讀取指定DSP內存獲取結果數據。
結果數據和模塊狀態信息存入L2緩存單元,主控計算機下發的命令字也寫入L2緩存單元。結果數據緩存劃分為大小各為28 KB的Block1和Block2兩塊區域;模塊狀態信息緩存大小為24字節;控制命令緩存大小為1 B。DSP中與PCI操作有關的緩存定義見表1。
表1 DSP中與PCI操作有關的緩存定義
當Block1緩存填滿后,新的結果數據存入Block2緩存,同時DSP給主控計算機發PCI中斷,主控計算機通過PCI接口讀取Block1;同理當Block2填滿后,新的結果數據存入Block1緩存,主控計算機通過PCI讀取Block2。Block1和Block2緩存交替接收結果數據。
2.2 CPCI驅動程序DLL接口設計
為了便于應用程序訪問驅動程序,按照模塊化的軟件設計思想,驅動程序以DLL動態鏈接庫的形式進行封裝,應用程序通過與驅動程序DLL之間的接口來訪問信號處理模塊的板上資源,下發控制命令、獲取結果數據。主要接口及其功能描述如下:
(1)DSP6416DLL_Init(CWnd* pMainWnd):打開并注冊WDC庫、打開設備,初始化中斷;
(2)DSP6416DLL_SendCmd(BYTE BCommand):主控計算機中的控制命令數據寫入DSP中命令存儲區;
(3)DSP6416DLL_ReadState(BYTE *StateData):從DSP的狀態存儲區讀取信號處理板的狀態數據;
(4)DSP6416DLL_ReadResult(BYTE *ResultData):從DSP的Block1或Block2數據緩存區讀取結果數據;
(5)DSP6416DLL_Exit():關閉中斷,關閉設備,關閉WDC庫。
2.3 CPCI驅動程序實現
在硬件環境和接口、驅動程序封裝形式及其軟件接口確定后,剩下的工作就是CPCI驅動程序的實現。該工作主要內容為驅動程序DLL各接口函數的編碼實現和WinDriver庫函數調用。
2.3.1 文件包含
包含與WinDriver相關的頭文件:windrvr.h,windrvr_int_thread.h,wdc_lib.h。
2.3.2 驅動程序初始化
驅動程序初始化主要工作和步驟包括:打開WinDriver,WinDriver授權、版本號檢查、板卡檢測、板卡信息獲取、模塊配置、板卡注冊和PCI中斷使能,驅動程序初始化流程見圖3。
2.3.3 驅動程序向DSP內存寫數據
DSP6416的PCI接口支持四種類型的數據交換[9?10]:從模式寫,外部PCI主設備通過PCI接口寫數據到DSP;從模式讀,外部PCI主設備通過PCI接口讀取DSP中的數據;主模式寫,DSP主設備通過PCI接口向外部設備寫數據;主模式讀,DSP主設備通過PCI接口向外部設備讀數據。
4 結 語
通過實際應用,發現用WinDriver開發的本驅動程序運行穩定可靠,達到了主控計算機對信號處理板實時控制,特別是信號處理板中大容量數據實時上傳的目的。由于系統方案確定了CPCI并行總線作為通信手段,硬件設計時采用了自帶主從式PCI接口模塊的DSP6416芯片,驅動開發工具選擇了快速高效的WinDriver工具包,以及對驅動程序形態進行DLL封裝,本驅動程序從需求設計到完成編碼和調試不到一個月的時間,在保證軟件質量的同時,縮短了研制周期,提高了開發效率。
參考文獻
[1] 李貴山,戚德虎.PCI局部總線開發者指南[M].西安:西安電子科技大學出版社,1997.
[2] PICMG. Compact PCI core specification PICMG 2.0 R3.0 [R]. [S.l.]: PICMG, 1999.
[3] 王磊,魯新平,李吉成.WinDriver在開發基于PLX9056芯片的PCI設備驅動程序中的應用[J].現代電子技術,2006,29(18):77?79.
[4] 李靜,趙保軍.基于TMS320C6416內嵌PCI設備驅動程序開發[J].微機發展,2005,15(10):135?137.
[5] Jungo Ltd. WinDriver PCI/ISA/CardBus v8.02 user’s guide [R]. US: Jungo Ltd, 2005.
[6] 簡育華.基于WinDriver的 PCI驅動程序開發[J].火控雷達技術,2011,40(1):68?70.
[7] Jungo Ltd. WinDriver PCI/PCMCIA/ISA v8.02 Low?Level API Reference[R]. US: Jungo Ltd, 2005.
近年來電力行業為了快速部署變電站,采用了建造整體變電所的方法:在生產基地將變電站的內部設備安裝、調試完成,只留下與外界的接口,整體運到變電站所在地后進行安裝和簡單調試即可投入運行。其內部設備通過CAN總線進行通信,系統原有的監控軟件基于DOS系統,維護調試比較困難,因此想要尋求更方便、友好的系統支持。經過比較,嵌入式操作系統市場上風頭正勁的Windows CE .NET成為最終選擇。微軟的最新產品Windows CE.NET提供了端對端的開發、調試手段,可以不拆卸設備的情況下通過Telnet登錄到WindowsCE上進行調試和維護,其系統本身為嵌入式市場進行重新設計,包括創建一個基于WindowsCE的定制設備所需的一切。這樣就需要將原來DOS下的程序移植到WindowsCE.NET下,但是各個硬件廠商目前還沒有提供CAN通信卡在Windows CE.NET下的驅動,所以開發Windows CE.NET下的CAN卡驅動成為項目推行中的關鍵一環。
本文主要針對研華的雙口CAN卡PCM3680進行分析,介紹在WindowsCE.ENT系統下進行底層設備驅動開發的方法并提供CAN通信的實例。
1 CAN總線通信協議及CAN通信卡介紹
CAN總線是德國Bosch公司20世紀80年代初為解決現代汽車中眾多的控制與測試儀器之間的數據交換而開的一種串行數據通信協議。它是一種多主總線,廢除了傳統的站地址編碼,而代之以對通信數據塊進行編碼。這種方法使網絡內節點個數在理論上不受限制,擴展格式中的29位的標識碼便可以定義2 29個不同的數據塊。
在本項目中使用的是研華的PCM3680,這是一塊嵌入式PC104的雙口CAN總線通信卡;CAN控制器采用Philips的獨立CAN控制器SJA1000芯片;CAN收發器采用Philips的P82C250,可以同時操作兩個CAN網絡,提供高達1Mb/s的傳輸速度。PCM3680支持很寬的中斷范圍:中斷3、4、5、6、7、9、10、11、12、15,同時1000V的光電隔離提供系統高可靠性。在CAN卡通信中,要用到CAN控制器中的很多寄存器,各個寄存器的含義和作用可以參考控制芯片的說明書。圖1列出驅動程序設計中用到最主要的寄存器結構。
2 CAN卡驅動底層函數設計
本方案設計CAN驅動是放在Windows CE操作系統的內核下層,位于OEM adaptation layer(OAL)層的一個真正的驅動,而不是在主程序中的串口操作。在Windows CE的設備管理器可以看到CAN1和CAN2兩個端口,并且可以查看其工作的正常與否和對其進行配置。如:中斷號和I/O地址。
2.1 CAN卡寄存器讀寫函數
CAN卡的通信是通過操作CAN卡上的CAN控制器進行的。在CAN控制器中有很多寄存器,如控制寄存器、命令寄存器、狀態寄存器、中斷寄存器等,通過讀寫這些寄存器中的命令狀態字可以檢測和控制CAN卡的行為。在Windows CE.NET下,通過調用DOK中的API函數HalTranslateBusAddress,將CAN卡分配的物理地址映射為邏輯地址。這樣各個寄存器對應的就是CAN卡基地址的偏移地址,因此,對寄存器的讀寫就轉化為對內存地址的讀寫。下面是CAN卡寄存器的讀寫函數:
*在偏移量為off的地址讀取一個字節的數據inline BYTE CANR(LPCAN_HW_OPEN_INFO hCan,DWORD off)
{
return hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off];
*將一個字節數據寫到偏移量為off的地址中inline VOID CANW(LPCAN_HW_OPEN_INFO hCan,DWORD off,BYTE val)
{
hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off]=val;
}
參數LPCAN_HW_OPEN_INFO定義的是CAN卡的數據結構,其中成員lpMappeBaseAddr[0]表示的是映射后基地址,lpMappedBaseAddr[1]就是基地址+1的地址,對應CAN卡的寄存器是命令寄存器。通過上述兩個函數可操作CAN卡上的所有寄存器。
2.2 CAN卡初始化
CAN卡的控制器比較復雜,在通信前必須確認硬件信息正確性、初始化各寄存器。初始化函數的基本流程如圖3所示。
第一步,檢查端口號和硬件信息的正確性,主要是CAN卡中斷號是否有效。
第二卡,設置CAN卡默認參數:
CanCardConfigInfo CAN_DEFAULT_SETTING=
{0X00,0XFF,0X03,0X1C};/*設置默認波特率為125Kbps*/
DWORD dwThreadID =0;
PHYSICAL_ADDRESS phyAddr={hwInfo->dwIOBaseAddr *16,0 };
第三卡,用WinCE API函數LocalAlloc為CAN卡驅動中用到的數據結構分配緩沖區;通過HalTranslateBusAddress和MmMapIoSpace函數映射I/O地址,提供直接訪問設備的虛擬地址:
if(!HalTranslateBusAddress(Isa,0,phyAddr,0,&phyAddr))
goto _ExitInit;
hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr=
(LPBYTE)MmMapIoSpace(phyAddr,CANCARDADDRLEN,FALSE);
if(!hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr)
goto _ExitInit;
如果分配內存或映射邏輯地址失敗,則退出初始化程序,CAN卡初始化失敗。
第四步,初始化讀寫屬性、共享模式、讀超時時間和第二個CAN口的基地址。
第五步,創建CAN卡事件和數據接收事件:hCan->lpCanHWInfo->hCanEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
hCan->lpCanHWInfo->hRecvMsgEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
第六步,初始化中斷,如果CAN卡有復位請求就退出初始化程序。設置好中斷后啟動數據接收線程,設置線程優先級繼續線程處理;最后配置CAN卡參數,進入正常運行狀態。
2.3 CAN卡信息發送
CAN卡的信息發送分為兩個步驟。在對CAN卡基本信息進行檢查后,首先設置發送緩沖的ID號。CAN標準模式的ID號為11位,偏移地址10中存放的是ID號的高8位,偏移地址11的高3位存放的是ID號的低3位,剩下5位分別是RTR位(遠程傳送請求位)和數據長度。通過CANW函數將處理后的數據寫入到相應的偏移地址,設置完相應的地址數據后,通過循環將偏移地址12~19的數據采集回來存到數組中。然后,設置CAN卡的傳輸請求為允許并不斷偵測狀態寄存器的變化,當傳輸緩沖滿標志或傳輸結束標志為1時通出程序,完成一次數據采集。傳輸緩沖區的寄存器如表1所列。
表1
ID號10ID.10ID.9ID.8ID.7ID.6ID.5ID.4ID.3RTR,數據長度碼11ID.2ID.1ID.0RTRDLC.3DLC.2DLC.1DLC.0數據1~812~19數據數據數據數據數據數據數據數據表2
ID號20ID.10ID.9ID.8ID.7ID.6ID.5ID.4ID.3RTR,數據長度碼21ID.2ID.1ID.0RTRDLC.3DLC.2DLC.1DLC.0數據1~822~29數據數據數據數據數據數據數據數據CAN消息發送函數的實現如下:
BOOL CAN_SendMessage(LPCAN_HW_OPEN_INFO hCan,LPCanCardMessageBuflpMsg)
{
BOOL bSuc=FALSE;
ASSERT(hCan && lpMsg && lpMsg->dwMessageLen <=8); /*防錯處理*/
if(0= =(hCan->dwAccessCode & GENERIC_WRITE))
return FALSE;
:: EnterCriticalSection(&hCan->lpCanHWInfo->
TransmitCritSec); /*進入臨界區*/
BYTE byV=static_cast<BYTE>(1pMsg->dwMsgID>>3);
CANW(hCan,10,byV); /*設置ID值高8位*/
byV=static_cast<BYTE>=((lpMsg->dwMsgID & 7)<<5);
if(lpMsg->bRTR) byV|=0x10;
byV+=static_cast<BYTE>(lpMsg->dwMessageLen);
CANW(hCan,11,byV);/*設置ID值低3位、RTR及數據長度*/
for(UINT i=0;<lpMsg->dwMessageLen;++i)
{
CANW(hCan,12+i,lpMsg->byMsg[i]);
} /*采集數據*/
CANW(hCan,1,1);/*重置傳輸請求*/
while(TRUE)
{byV=CANR(hCan,2);
if(byV & 0X40) /*傳輸緩沖區滿,退出*/
{break;}
if(byV & 0X8){ /*傳輸結束,正確返回退出*/
bSuc = TRUE;
break;}
}
::LeaveCriticalSection(&hCan->lpCanHWInfo->TransmitCritSec); /*離開臨界區*/
return bSuc;
}
2.4 CAN卡信息接收
CAN卡的信息接收是發送的逆過程,當接收緩沖區標志為1時,表示緩沖區已滿可以接收數據,將數據接收到數組后釋放接收緩沖區,然后對接收到的數據進行分解并存儲到CAN卡信息緩沖區的結構體。接收緩沖區的寄存器結構如表2所列。
CAN消息接收函數的實現如下:
BOOL CAN_RecvRecvMessage(LPCAN_HW_OPEN_INFO
HCan,OUT LPCanCardMessageBuflpMsg)
{……
if(CANR(hCan,2)&1){ /*判斷接收緩沖區是否已滿*/
for(UINT i=0;i<10;++i)
recvBuf[i]=CANR(hCan,20+i);/*將數據暫存到臨時緩沖區*/
CANW(hCan,1,4); /*釋放接收緩沖區*/
LpMsg->dwMsgID=recvBuf[0]<<3; /*取出ID的高8位*/
BYTE byV =recvBuf[1];
LpMsg->dwMsgID+=byV >>5;/*取出ID低3位,然后和高8位合并*/
LpMsg->bRTR =byV &0x10?TRUE:/*返回RTR狀態*/
LpMsg->dwMessageLen = byV &0XF; /*返回數據長度*/
……
}
else
{++hCan->lpCanHWInfo->dwErrorMsgCount;}/*沒有收到數據,錯誤計數加1*/
::LeaveCriticalSection(&hCan->lpCanHWInfo->
ReceiveCritSec); /*離開臨界區*/
Return bSuc;
}
2.5 CAN卡事件處理
CAN卡事件處理函數是CAN卡驅動程序中很重要的部分。驅動設計要求具有消息通知的功能,當事件發生時及時捕獲事件并進行消息處理。
下面是事件處理函數的實現:
staric DWORD WINAPI CAN_EventHanle(LPVOID lpParam)
{
ASSERT(lpParam);
LPCAN_HW_OPEN_INFO hCan=(LPCAN_HW_OPEN_INFO)lpParam;
CanCardMessageBuf bufMsg;
while(TEUE)
{ /*循環等待CAN卡消息產生,然后進行處理*/
::WaitForSingleObject(hCan->lpCanHWInfo->hCanEvent,0XFFFFFFFF);
if(hCan->lpCanHWInfo->bKillCanThread) break; /*若CAN線程已關閉則中斷*/
if(CAN_RecvMessage(hCan,&hufMsg)){ /*正確接收數據后*/
CAN_RecvBufPush(hCan,&bufMsg);} /*將數據壓入緩沖*/
BYTE byV=CANR(hCan,3); /*將3號寄存器讀出然后立即寫入*/
CANW(hCan,3,byV);/*能夠獲取每次中斷*/
InterruptDone(hCan->lpCanHWInfo->lpCanObj->dwSysIrqt);
} /*本次中斷結束,等待下次中斷*/
return 0;
}
2.6 其它函數
為了提供更多的功能和更方便地使用CAN卡進行通信,在CAN卡驅動程序中還設計了一些函數如CAN_Config用CAN卡信息配置、CAN_RecvBufPop用于處理接收緩沖區、CAN_Reset用于復位CAN卡、CheckHWInfo用于硬件信息檢查等。這些函數提供了對CAN通信卡的設置、檢查等功能,在這里不再詳述了。
3 CAN卡驅動封裝設計
CAN卡底層驅動函數雖然功能完整,但是對于用戶使用比較復雜并且一般用戶不需要了解底層實現的機制。為了便于使用,最后對CAN卡的驅動進行了封裝,提供CanOpenFile、CanSendMsg等五個函數用于CAN總線的通信,以動態連接庫(DLL)的形式提供給用戶調用。封裝函數及功能如下:
*CanOpenFile;初始化并打開CAN卡的一個端口。
*CanCloseFile;關閉由CanOpenFile打開的CAN卡端口。
*CanRecvMsg;接收CAN卡數據,打開CAN卡時必須具有GENERIC_READ權限。
*CanSendMsg;通過CAN卡發送數據。打開CAN卡時必須具有GENERIC_WRITE權限。
*CanIOControl;設置或獲取CAN卡I/O參數支持的I/O控制包括:IOCTL_CAN_CONFIG,IOCTL_CAN_RESET,IOCTL_CAN_TIMEOUT,IOCTL_CAN_SENDREADY,IOCTL_CAN_RECVREADY。
下面是CanSendMsg函數實現的代碼:
BOOL CanSendMSg(
HANDLE hCan,
LPCanCardMessageBuflpMsg)
{
if(!hCan||INVALID_HANDLE_VALUE= =hCan||
!lpMsg||lpMsg->dwMessageLen>8)return FALSE;
return CAN_SendMessage(LPCAN_HW_OPEN_INFO)
hCan,lpMsg);
該函數就是通過封裝CAN卡的底層驅動函數SendMessage來實現的,這樣將功能集中的五個函數更方便了用戶使用。
中圖分類號:TP311.52
文獻標識碼:B
文章編號:1004―373X(2008)04―063―03
開發驅動程序的軟件主要有:MicroSoft公司的DDK,Jungo公司的Windriver和Compuware NuMega公司的Driver Studio三種。DDK是最基本的驅動程序開發工具,比較復雜,適于專業的驅動程序開發人員,不適于硬件開發人員開發驅動程序。Windriver開發驅動程序不需要熟悉操作系統內核知識,針對硬件PCI/ISA/PCM―CIA/USB開發驅動程序比較方便,但驅動程序的效率不高、缺乏靈活性。Driver Studio把DDK用類的形式進行封裝,簡化設備驅動程序的開發,方便又不失靈活性。所以這里選擇Driver Studio作為驅動程序的開發工具。
在結合PCM高速遙測數據發送卡的基礎上,本文介紹WDM驅動程序的結構特點和PCM高速遙測數據發送卡的硬件結構,并闡述針對數據發送卡的特點,詳細地討論驅動程序關鍵部分的設計。
1 PCM遙測數據發送卡的硬件結構
圖1為遙測數據發送卡的原理框圖。碼型變換器的功能是根據原始PCM數據產生3種輸出碼型:NRZ―L,NRZ―M及NRZ―S之一,以適應更加廣泛的測試目的。多電平驅動器將來自FPGA的LV TTL電平的PCM數據和時鐘信號轉換為3種電平接口輸出,分別是TTL,EIA422及MLVDS。同步FIFO作為硬件數據幀緩存存儲由PCI總線寫入的數據幀,然后由序列生成器讀出。序列生成器根據PCM時鐘速率產生串行移出的PCM原始數據將來自FIFO的32位并行數據轉換為串行輸出,同時根據移位寄存器的狀態產生發向FIFO的讀數請求:
2 WDM驅動程序的結構及特點
WDM(Windows Driver Model)是在原有的NT內核模式驅動程序的基礎上發展來的,他增加了PnP(Plugand Play)、電源管理、WMI(Windows Management Instru―mentation)等功能。WDM模型的層次結構如圖2所示。
層次結構可以使I/O請求過程更加清晰。影響設備的每一個操作都使用I/O請求包(IRP),通常IRP被送到設備堆棧的最上層,然后逐漸過濾到下層驅動程序。每處理1個IRP,I/O管理器就調用1次StartIO例程,從而著手IRP處理工作;如何處理完全取決于具體的設備,調用驅動程序中相應的例程。驅動程序處理完IRP后,會將結果返回給I/O管理器,再由I/O管理器返回給用戶應用程序。
3 PCM遙測數據發送卡WDM驅動程序的設計
在設備的驅動程序設計中,需要處理PCI設備的硬件讀寫、中斷處理、DMA等功能。可以把驅動程序視為一個框架和若干例程的結合體,各個例程處理不同的IRP,而框架負責在IRP到來時調用相應的例程。利用Driver―Works的驅動程序向導(Driver Wizard)新建一個PCI設備驅動程序框架,然后在這個框架基礎上添加必要的實現功能的處理代碼,就可以完成整個驅動程序的設計。下面以PCM遙測數據發送卡為例討論其主要的功能驅動程序例程的實現。
3.1硬件初始化例程
OnStartDevice(KIrp I)參數例程中包含2種系統分配的資源配置信息:原始的資源配置信息(AllocatedRe―sources);轉換后的資源配置信息(AllocatedResourcesTranslated)。因為I/O總線和CPU在尋址物理硬件的方式不同,所以存在2種資源列表。從注冊表、PCI配置空間和其他地方獲取原始的資源值和轉換這些值的操作全部由PnP管理器完成,WDM驅動程序需要做的僅是從設備啟動IRP中獲取這些資源。
3.2 中斷服務例程
中斷服務例程運行在DIRQL級別上,需要盡可能快地運行。本設計在中斷服務例程中,首先判斷中斷是否自己設備產生的,如果是,則調用一個在DISPATCH_LEV―EL級別上運行的延遲過程調用(DPC)。當中斷服務例程完成后,一旦處理器獲得DISPATH_LEVEI。運行權,就會運行DPC。中斷服務例程流程圖如3所示。
3.3 中斷延遲調用例程
在延遲調用例程中,判斷中斷原因如果是DMA中斷就啟動DMA繼續發送。如果是發送通道中斷,則判斷通道號,并把相應軟件FIFO里面的待發送數據傳送到硬件FIFO里。在此過程中需要檢查在將軟件FIFO中的數據寫入硬件FIFO中后,如果軟件FIFO已被讀空,則應禁止通道中斷,否則通道中斷因為優先級高,會一直于有效狀態,導致系統死鎖。而在用戶程序寫軟件FIFO的處理函數中,檢查通道中斷,如果被禁止,則應將新寫入軟件FIFO的數據讀取一部分寫入硬件FIFO中,然后開啟通道中斷。
3.4應用程序與驅動程序的通信例程
DeviceControl(KIrp I)主要用于應用程序與驅動程序之間的通信,如向硬件讀寫數據以及軟件FIFO的操作等。DevcieControl響應用戶應用程序DeviceloControl()發送的IRP,根據IOCTL代碼來判斷調用子處理函數PCI_9054_IOCTL_READ_Handler(I),PCI_9054_IOCTL_WRITE_Handler(I).DEV_IOCTL_TXI_FIFO_WRITE_Handler(I)分別完成對硬件的讀寫和軟件FIFO的寫操作。
3.5 DMA傳輸操作
硬件FIFO半滿時產生通道中斷,在DPC里,判斷是通道中斷,則初始化KDmaTransfer,然后調用OnD-maReady();在OnDmaReady()中啟動首次DMA傳輸,傳輸時發生中斷,在DPC中判斷是否DMA中斷,如果是,則調用Continue()再次啟動下次傳輸,至此全總數據傳輸完成。其流程圖如圖4所示。
4 驅動程序編譯、調試和安裝
當驅動程序編寫完成后,必須在DDK環境下進行編譯,執行Rebuild aIl命令,編譯完成后生成*.sys文件和*.inf文件。調試工具使用Softlce,基本過程如下:
(1)使用Symbol Loader加載驅動程序*.nms文件,然后激活Softlee,設置斷點跟蹤調試;
(2)用Genint命令產生虛擬中斷測試,中斷服務例程;
1 WDM模式驅動程序
1.1 WDM模式(Windows Driver Model)
Windows2000對驅動程序的編寫不再基于以往的Win3.x和Win9x下的VxD(虛擬設備驅動程序)結構,而是基于一種新的驅動模型——WDM(Windows Driver Model)。
WDM為Windows98/2000/XP操作系統的設備驅動程序的設計提供了統一的框架。WDM來源于Windows NT的分層32位設備驅動程序模型(layered 32-bit device driver model)。它支持更多的特性,如即插即用(PnP)、電源管理、WMI和NT事件。
1.2 設備驅動程序
設備驅動程序是操作系統的一個組成部分,它由I/O管理器(I/O Manager)管理和調動。Windows2000操作系統下的I/O管理器功能描述如圖1所示。
I/O管理器每收到一個來自用戶應用程序的請求就創建一個I/O請求包(IRP)的數據結構,并將其作為參數傳遞給驅動程序。驅動程序通過識別IRP中的物理設備對象(PDO)來區別是發送給哪一個設備。IRP結構中存放請求的類型、用戶緩沖區的首地址、用戶請求數據的長度等信息。驅動程序處理完這個請求后,在該結構中填入處理結果的有關信息,調用IoCompleteRequest將其返回給 I/O管理器,用戶應用程序的請求隨即返回。訪問硬件時,驅動程序通過調用硬件抽象層的函數實現。
1.3 DriverStudio工具簡介
NuMega Lab公司開發的DriverStudio是一整套開發、調試和檢測Windows平臺下設備驅動程序的工具軟件包。它把DDK(Device Development Kit)封裝成完整的C++函數庫,根據具體硬件通過向導生成框架代碼,并且提供了一套完整的調試和性能測試工具SoftICE、DriverMonitor等。
2 應用實例
本文利用PCI專用接口芯片PCI9052設計了一個數據傳輸控制卡。卡上主要的芯片有PCI9052、FIFO(CY7C4221)、CPLD(MAX7064S)和A/D轉換器(MAX1197)。傳輸卡硬件框圖如圖2所示。面陣CCD得到的視頻信號經過調理電路,生成的視頻調理信號通過A/D轉換器進行數字化處理,送入FIFO中。在CPLD的控制下,數據經過PCI9052送入PCI總線,再傳送到計算機內存中,并顯示在監視器上。驅動程序必須實現如下幾個基本功能:(1)硬件中斷;(2)能支持應用程序獲取數據;(3)能根據外部FIFO(CY7C4221)的狀態啟動或停止突發傳輸。
在數據輸入過程中,最重要的是對數據進行實時控制,因此需要硬件中斷。在中斷程序中,根據外部FIFO狀態完成數據的讀入。
2.1 用DriverWizard生成驅動程序框架
DriverStudio中的DriverWorks軟件為開發WDM程序提供了一個完整的框架。它包含一個可快速生成WDM驅動程序框架的代碼生成向導工具DriverWizard,而且還帶有許多類庫。在用DriverWizard生成的程序框架中寫入相對于設備的特定代碼,編譯后即可得到所需的驅動程序。
在利用DriverWorks V2.7的向導Driver Wizard完成驅動程序的框架時共有11個步驟,其中關鍵步驟有:
(1)在第四步中選中PCI,并在VendorID和DeviceID中分別輸入廠商號和設備號,還需填入PCI Subsystem ID和PCI Revision ID。這四項可以用網上的免費軟件PCITree或PCIView瀏覽PCI設備,用這兩個軟件也可以得到BAR0~BAR5的資源分配情況和中斷號。
(2)第七步IRP隊列排隊方法,它決定了驅動程序檢查設備的方式。本設計選SystemManaged,則所有的IRP排隊都由系統(即I/O管理器)完成。
(3)第九步是最關鍵的一步。首先在Resources中添加資源,在name中輸入變量名,在PCI Base Address中輸入0~5的序列號。0~5和BAR0~BAR5一一對應。在設置中斷對話框中,在name欄寫入中斷服務程序的名稱,選中創建中斷服務程序ISR?穴Create ISR?雪,不選創建延遲程序調用DPC(Create DPC),選中Make ISR/DPC class functions,使ISR/DPC成為設備類的成員函數。
其次選中Buffer以選取讀寫方式,用于描述與I/O操作相關的數據緩沖區。本設計需要快速傳送大量數據,因此采用Direct I/O方式。
(4)在第十步中,需要加入與應用程序或者其他驅動程序通信的I/O控制代碼參量。
2.2 驅動程序模塊框圖和代碼分布
PCI設備驅動程序模塊包括配置空間的訪問模塊、IO端口模塊、內存讀寫模塊和終端模塊等。各模塊之間是對等的。驅動程序模塊框圖如圖3所示。
驅動程序初始化模塊代碼段放在#pragma code_seg(″INT″)和#pragma code_seg()之間。在系統初始化完成后,這部分代碼從內存中釋放,防止占用系統寶貴的內存資源。#pragma code_seg()之后是驅動程序和系統的許多模塊的實現部分。這部分在驅動程序運行后不會從內存中釋放。
2.3 驅動程序主要模塊的實現
(1)配置空間的訪問模塊
DriverWorks的KPciConfiguration類封裝了訪問PCI設備配置空間的所有操作。首先初始化這個類的實例:
KpciConfiguration PciConfig()m_Lower.TopOfStack());
/?觹m_Lower是 KpnpLowerDevice類的對象。m_LowerTopOfStack()返回當前設備堆棧頂部的設備對象。*/
初始化完后可以直接利用成員函數 ReadHeader/ WriteHeader函數訪問所有的配置寄存器。
為了確定映射空間的類型和大小,先向目標基地址寄存器寫入0Xffffffffh,然后回讀該寄存器的值。如果最低位為1,表示映射于I/O空間,反之為存儲空間;如果映射于存儲空間,從第四位開始計算0的個數可以確定內存空間的大小;如果是I/O方式,從第二位開始計算0的個數可確定I/O空間的大小,最大為256字節。如果設備的存儲空間超過256字節,要實現設備的整個存儲部分的訪問,就必須采用內存映射。
(2)I/O操作模塊
Driverworks的KIoRange類封裝了I/O端口訪問的操作。部分代碼如下:
{……
KIORange DevIoPort () ;//創建實例
NTSTATUS status= DevIoPort ().Initialize ( pResListTranslated,pResListRaW,PciConfig.BaseAddressIndexToOrdinal(0));
/* 第一個參數為轉換后的資源列表指針;第二個參數為原始資源列表指針;第三個參數中的0為 I/O口對應的基地址,用來轉換成特定端口資源的序數?*/
If(NT _SUCCESS(status))
{……
DevIoPort.inb(0,LineBuf1,10);
/*成功初始化后可分別用KIoRange類的成員函數inb(/outb)從端口中讀/寫字節 */
}
else{Invalidate();return status;
/*未能初始化成功,錯誤信息在status中*/
{
……}
(3)內存讀寫模塊
DriverWorks的 KMemoryRange類封裝了端口訪問的操作。
status=m_MemoryRange().Initialize(pResListTranslated,pResListRaw, PciConfig.BaseAddressIndexToOrdinal(0));
此函數的參數、意義及具體用法與I/O端口的操作基本相同。
內存對象也用來發送控制字,以控制CPLD的開始和停止等。實際上控制字是通過PCI9052發送的。該控制字地址已被映射成PCI的內存空間。所以定義一個指向內存空間的內存對象,通過該對象即可發送控制字。
(4)中斷模塊
在中斷模塊,首先要激活PCI9052中斷使能位,然后判斷硬件中斷響應是否產生,如果有,則進行突發傳輸,讀入FIFO中的數據。
BOOLEAN TranCard::Isr_MyIrq(void)
{ if (// 中斷未產生)
{……
return FALSE;}
else
{/* 如果產生硬件中斷,設置命令寄存器,進行突發數據傳輸 */
return TRUE;}
}
為了將硬件中斷與編寫的中斷服務程序連接在一起,采用InitializeAndConnect方法,部分代碼如下:
NTSTATUS TranCardDevice?押?押OnStartDevice(KIrp I )
{……
status=m_MyIrq. InitializeAndConnect(
pResListTranlated,
LinkTo(Isr_MyIrq),
This;)
……}
2.4 驅動程序的調用
編寫驅動程序本身不是最終目的,最終目的是調用驅動程序管理資源,并為用戶應用程序使用。驅動程序加載以后,它的許多進程處于Idle狀態,實際上需要用戶應用程序去調用激活。應用程序利用Win32 API直接調用驅動程序,實現驅動程序和應用程序的信息交互。
首先用CreateFile()打開設備,獲得一個指向設備對象的句柄。使用CreateFile函數時應注意:由于驅動程序是*.sys,所以第一個參數應該是這個設備對象的標志連接(symbolic link)。該標志連接名有一個設置數據文件搜索路徑的數字號,而這個數字號通常是零。如果這個連接名是″TranCard″,則傳遞給CreateFile的宇符串就是:″\\\\.\\ TranCard0″。例如:
HANDLE hDevice=CreateFile(″\\\\.\\TranCard0″)GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ, NULL?, OPEN_EXISTING,0,NULL);
然后用 DeviceIoControl()進行數據的傳送。最后用CloseHandle( )關閉設備句柄。
下面是應用DeviceIoControl()程序片段。
{……
m_b=DeviceIoControl(hDevice,TRANCARD_IOCTL_
RECEIVE(buffer, sizeof,buffer, NULL,0,&buffersize,NULL);
……}
2.5 驅動程序的調試
中圖分類號:TP305文獻標識碼:B 文章編號:1009-3044(2011)16-3952-03
CAN_NODE Bus Drivers Design Based on Atmega128
LIU Bin, LIU Jun-liang, MA Jin-bo, WANG Jun-qing
(2332 Laboratory, College of Engineering, Ocean University of China, Qingdao 266100, China)
Abstract: CAN_NODE is a powerful 8-bit AVR microcontroller experiment board, it is based on AVR RISC structure 8-bit low-power CMOS microprocessor ATmega128. This paper briefly expounds the profile of the fieldbus technology, hardware structure of CAN_NODE experimental board and characteristic of ATmega128, then the CAN bus drivers based on the experimental board is focused on.
Key words: CAN_NODE experiment board; ATmega128; CAN bus drivers
1 概述
現場總線(Fieldbus)技術是當前自動化技術的熱點之一。現場總線技術集先進的嵌入式系統、現代通信、自控理論、網絡技術于一身,充分體現出先進技術的進步能夠為人類帶來的便利。
CAN:全稱為“Controller Area Network”,即控制器局域網,是國際上應用最廣泛的現場總線之一。最初,CAN被設計作為汽車環境中的微控制器通訊,在車載各電子控制裝置ECU之間交換信息,形成汽車電子控制網絡,比如,發動機管理系統、變速箱控制器、儀表裝備、電子主干系統中,均嵌入CAN控制裝置。
AVR單片機是1997年由ATMEL公司研發出的增強型內置Flash的RISC(Reduced Instruction Set CPU) 精簡指令集高速8位單片機。AVR的單片機可以廣泛應用于計算機外部設備、工業實時控制、儀器儀表、通訊設備、家用電器等各個領域。
2 CAN_NODE實驗板硬件結構
CAN_NODE實驗板上提供了CAN總線通訊所需要的硬件,和一些按鍵,LED,USB接口等常用的功能部件,還提供了為系統擴展而預留的擴展功能接口,也提供了SPI接口和JTAG接口以方便下載和調試。
2.1 CAN_NODE實驗板功能框圖
圖1為系統結構框圖。
2.2 ATmega128的特點
其先進的指令集以及單周期指令執行時間, 使得ATmega128 的數據吞吐率高達1 MIPS/MHz。同時ATmega128具有:128K 節的系統內可編程Flash(具有在寫的過程中還可以讀的能力,即RWW)、4K 字節的EEPROM、4K 字節的SRAM、53 個通用I/O 口線、32個通用工作寄存器、實時時鐘RTC、4 個靈活的具有比較模式和PWM 功能的定時器/ 計數器(T/C)、兩個USART、面向字節的兩線接口TWI、8 通道10 位ADC(具有可選的可編程增益)、具有片內振蕩器的可編程看門狗定時器、SPI 串行端口、與IEEE 1149.1 規范兼容的JTAG 測試接口(此接口同時還可以用于片上調試)。
3CAN總線驅動程序設計
軟件開發采用的是ImageCraft公司開發的ICCAVR,軟件的下載采用雙龍ATMEL_ISP下載軟件。ICCAVR是一種使用符合ANSI 標準的 C 語言來開發ATMEL公司生產的微控制器(MCU)程序的一個工具,它有以下幾個主要特點:
1)ICCAVR 是一個綜合了編輯器和工程管理器的集成工作環境(IDE),其可在Windows9X/NT下工作,源文件可被組織到工程中,文件的編譯和工程的構筑也是在這個環境中完成。
2)編譯錯誤顯示在狀態窗口中,并且當你用鼠標單擊編譯錯誤時,光標會自動跳轉到編輯窗口中引起錯誤的那一行。這個工程管理器還能直接產生您希望得到的可以直接使用的INTELHEX 格式文件,INTEL HEX 格式文件可被大多數的編程器所支持,用于下載程序到芯片中去。
集成開發環境如圖2所示。
CAN總線驅動程序主要包括四個部分:CAN控制器初始化、接收數據、發送數據和總線異常處理。
圖3為主程序流程圖。
主要程序設計如下所示:
3.1 初始化
Can控制器初始化的操作包括:中斷控制,硬件使能,軟件復位,工作模式等。
初始化程序如下
unsigned char can_state;
IOWR(CAN_IP_0_BASE,CAN_IER,0x00);//禁止中斷
IOWR(CAN_IP_0_BASE,CAN_MOD,0x09);//進入復位模式,單驗收濾波器
can_state=(unsigned char)IORD(CAN_IP_0_BASE,CAN_MOD);
while((can_state&0x01)==0x00)//檢測是否進入復位模式
{
IOWR(CAN_IP_0_BASE,CAN_MOD,0x09);//進入復位模式,單驗收濾波器
can_state=(unsigned char)IORD(CAN_IP_0_BASE,CAN_MOD);
}
IOWR(CAN_IP_0_BASE,CAN_CDR,0xC1);//peliCAN,禁止時鐘輸出,禁止TX1,RX1c8
IOWR(CAN_IP_0_BASE,CAN_ACR0,local_code1);//驗收碼1
IOWR(CAN_IP_0_BASE,CAN_ACR1,local_code2);//驗收碼2
IOWR(CAN_IP_0_BASE,CAN_ACR2,local_code3);//驗收碼3
IOWR(CAN_IP_0_BASE,CAN_ACR3,local_code4);//驗收碼4
IOWR(CAN_IP_0_BASE,CAN_AMR0,0xff);//屏蔽碼1
IOWR(CAN_IP_0_BASE,CAN_AMR1,0xff);//屏蔽碼2
IOWR(CAN_IP_0_BASE,CAN_AMR2,0xff);//屏蔽碼3
IOWR(CAN_IP_0_BASE,CAN_AMR3,0xff);//屏蔽碼4
IOWR(CAN_IP_0_BASE,CAN_BTR0,0x01);//同步跳轉3個周期,系統時鐘4倍周期
IOWR(CAN_IP_0_BASE,CAN_BTR1,0x1C);//采樣點3,段一6,段二3
IOWR(CAN_IP_0_BASE,CAN_OCR,0x1A);//控制寄存器
IOWR(CAN_IP_0_BASE,CAN_MOD,0x08);//進入工作模式,單驗收濾波器
can_state=(unsigned char)IORD(CAN_IP_0_BASE,CAN_MOD);
while((can_state&0x01)==0x01)//檢測是否進入復位模式
{
IOWR(CAN_IP_0_BASE,CAN_MOD,0x08);//進入工作模式,單驗收濾波器
can_state=(unsigned char)IORD(CAN_IP_0_BASE,CAN_MOD);
}
IOWR(CAN_IP_0_BASE,CAN_IER,0x01);//開接收中斷
}
CAN是一種基于廣播的通訊機制,廣播通訊依靠報文(Message)的傳送機制來實現,因此CAN并未定義站及站地址,而僅僅定義了報文,這些報文依靠報文確認區(Identifier)來進行識別,一個消息報文確認區在一個網絡中必須是唯一的,它不但描述了某一報文的意義,而且還定義了報文的優先級,當很多站都在訪問總線時,優先級是很重要的,因此,CAN是通過報文的確認區來決定報文的優先級的。
CAN節點之間的數據傳輸采用的協議是報文格式,其29位的幀標識符和報文數據部分的規定如圖4所示。
3.2 數據接收
接收數據可以采用查詢方式或中斷方式。在某一段時間內CAN總線并不是總在活動,為了提高效率,可采用中斷方式。
程序如下:
alt_u8 can_irq_reg;
//can_irq_reg=IORD(CAN_IP_0_BASE,CAN_IR);
//if ((can_irq_reg & 0x01)==1)
{
can_rx_reg[0]=IORD(CAN_IP_0_BASE,CAN_TX_SFF_EFF_H);//發送幀
can_rx_reg[1]=IORD(CAN_IP_0_BASE,CAN_TX_SFF_EFF_C1);//驗收碼1
can_rx_reg[2]=IORD(CAN_IP_0_BASE,CAN_TX_SFF_EFF_C2);//驗收碼2
can_rx_reg[3]=IORD(CAN_IP_0_BASE,CAN_TX_EFF_C3);//驗收碼3
can_rx_reg[4]=IORD(CAN_IP_0_BASE,CAN_TX_EFF_C4);//驗收碼4
can_rx_reg[5]=IORD(CAN_IP_0_BASE,21);
can_rx_reg[6]=IORD(CAN_IP_0_BASE,22);
can_rx_reg[7]=IORD(CAN_IP_0_BASE,23);
can_rx_reg[8]=IORD(CAN_IP_0_BASE,24);
can_rx_reg[9]=IORD(CAN_IP_0_BASE,25);
can_rx_reg[10]=IORD(CAN_IP_0_BASE,26);
can_rx_reg[11]=IORD(CAN_IP_0_BASE,27);
can_rx_reg[12]=IORD(CAN_IP_0_BASE,28);
}
can_rx_flag=1;
IOWR(CAN_IP_0_BASE,CAN_CMR,0X04);//釋放接收緩沖區
can_irq_reg=IORD(CAN_IP_0_BASE,CAN_IR);
while ((can_irq_reg & 0x01 )==0x01)
{
IOWR(CAN_IP_0_BASE,CAN_CMR,0X04);
can_irq_reg=IORD(CAN_IP_0_BASE,CAN_IR);
}
3.3 數據發送
將待發送的數據打包成符合CAN協議的幀格式后,寫入發送緩沖區,然后發送。
程序如下所示:
if(can_rx_flag==1)
{
can_tx_count=0;
can_rx_flag=0;
//IOWR(CAN_IP_0_BASE,21,0x55);
//IOWR(CAN_IP_0_BASE,21,0xaa);
//data_reg=IORD(CAN_IP_0_BASE,21);
IOWR(CAN_IP_0_BASE,CAN_TX_SFF_EFF_H,0x88);//發送幀
IOWR(CAN_IP_0_BASE,CAN_TX_SFF_EFF_C1,local_code1);//驗收碼1
IOWR(CAN_IP_0_BASE,CAN_TX_SFF_EFF_C2,local_code2);//驗收碼2
IOWR(CAN_IP_0_BASE,CAN_TX_EFF_C3,local_code3);//驗收碼3
IOWR(CAN_IP_0_BASE,CAN_TX_EFF_C4,local_code4);//驗收碼4
IOWR(CAN_IP_0_BASE,21,can_rx_reg[5]);//數據
IOWR(CAN_IP_0_BASE,22,can_rx_reg[6]);//數據
IOWR(CAN_IP_0_BASE,23,can_rx_reg[7]);//數據
IOWR(CAN_IP_0_BASE,24,can_rx_reg[8]);//數據
IOWR(CAN_IP_0_BASE,25,can_rx_reg[9]);//數據
IOWR(CAN_IP_0_BASE,26,can_rx_reg[10]);//數據
IOWR(CAN_IP_0_BASE,27,can_rx_reg[11]);//數據
IOWR(CAN_IP_0_BASE,28,can_rx_reg[12]);//數據
IOWR(CAN_IP_0_BASE,CAN_CMR,0x01);//發送
}
3.4 異常情況處理
總線發生故障時,下行的CAN節點可能脫離總線。可通過讀取錯誤計數器對計數器遞減計數的情況進行監測并作相應處理。若前面傳輸到CAN控制器的數據未被讀出,而接收緩沖區又沒有及時釋放,就有可能引起后面信息的丟失。這時必須通過寫命令寄存器來清除CANSR的數據溢出位。這兩種異常可通過異常中斷來處理,只要在中斷子程序中加入處理代碼即可。其他的總線異常處理可根據使用情況決定是否在軟件中處理。
4 結束語
本設計對CAN模塊軟硬件結構及ATmega128的特點進行簡要的描述,主要對基于ATmega128單片機的CAN_NODE總線驅動程序的進行設計。現場總線技術以其獨有的技術優勢和特點,在現代分布式測量與控制技術領域中應用已愈來愈廣泛。各種現場總線的主控制器一般都內嵌有相當完善的、開放式的互聯通信協議,它具有通信速度快、誤碼率低、開發設計簡單及網絡使用維護方便等諸多特點,是實現網絡化現場測量與控制技術的一個發展方向。
參考文獻:
[1] 周立功.iCAN現場總線原理與應用[M].北京:北京航空航天大學,2007.
[2] 范偉成.基于ATmegal28單片機的CAN總線接口設計及應用[M].上海:上海齊耀動力技術有限公司,2008.
1 PC/104-CAN適配卡的硬件結構
PC/104-CAN適配卡主要由CAN控制器(SJA1000)、光電隔離(6N137),收發驅動器(82C250)及譯碼電路組成。編程主要了解的是控制器SJA1000。CAN適配卡原理如圖1所示。
2 CAN地址譯碼和中斷選擇
系統104主板的CPU為486DX,其對接口板訪問有兩種方式:內存映射和I/O訪問。I/O尋址采用專門的指令,每次只能傳送單個字節。內存映射方式可以訪問較大的地址空間并且指令豐富,便于實現快速交換數據。本文討論的CAN卡采用存映射模式工作,與486DX接口是104總線,它與ISA總線兼容。對于Intel X86體系的CPU,ISA可以映射的空間為0xC8000~0xEFFFF。使用比較器和地址選擇開關組成可選端口地址譯碼電路,通過開關選通內存映射基地址(C8000H、C9000H、CA000H、…、EF000H),以避免與其它器件沖突。CAN偏移地址分配如下:
00~FFH SJA1000的寄存器;
100H~1FFH 對該范圍內的任意地址進行寫操作,均可導致CAN硬件復位。
SJA1000的INT引腳通過跳線選擇IRQ3~7、IRQ9~12或IRQ15中的一個,避免與其它的適配卡沖突。
3 PC/104-CAN適配卡驅動實現
3.1 VxWorks驅動概述
VxWorks操作系統有兩種方式實現驅動。第一種方式是,把設備驅動程序作為獨立任務實現,直接在頂層任務中實現硬件操作,完成特有專用的驅動程序。第二種方式是,VxWorks的I/O系統將設備程序作為內核過程實現。這種方式便于實現I/O子系統的層次模型,便于文件系統一起把設備作為特殊文件處理,提供統一的管理、統一的界面和統一的使用方法,并把設備、文件及網絡通信組織成為一致的更高層次的抽象,為用戶提供統一的系統服務和用戶接口。我們和這種驅動方式。
作為I/O系統和硬件設備之間的連接層,VxWorks驅動就是屏蔽硬件操作,為I/O系統提供服務。實現一個完整的驅動,必須了解VxWorks下I/O的三個基本元素:File、Driver和Dervice。File是為用戶提供訪問設備的統一接口;Driver是實現具體的基本控制函數,也就是實現I/O系統所需要的接口;而Device則是一個抽象的硬件設備,是一系列的結構體、變量和宏定義對實際物理設備的定義。一般而言,實現一個驅動應該有三個基本的步驟:①用編程語言完成對實際物理設備的抽象;②完成系統所需要的各類接口及自身的特殊接口;③將驅動集成到操作系統中。之后還有一些調試工作。
3.2 VxWorks I/O系統驅動程序框架
VxWorks為各種設備(包括字符設備、塊設備、虛擬設備及網絡設備)提供統一的訪問接口,包括七種基本的I/O函數: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系統所起的作用就是,把用戶請求分配到與設備對應的驅動例程中去。VxWorks系統中有一個驅動程序列表,其形式如表1所列。
表1 設備驅動列表(調試時可利用iosDrvShow()查看)
驅動號碼createremoveopenclosereadwriteioctl1
2ca OpenNULLca Openca Closeca Readca Writeca IoctlI/O系統的可動態調用iosDrvInstall()函數將設備的驅動例程(即XXOpen()、XXClose()、XXRead()等)加入到設備驅動列表中,如圖2所示。
同樣,系統中有一個設備列表,每個設備對應于設備列表中的一項,每一項包括設備名稱和設備驅動號,同時包括一個設備描述的結構。該結構第一個變量是DEV_HDR類型的變量DEV_HDR。
DEV_HDR的定義如下:
Typedef struct
{
DL_NODE node; /*設備列表節點*/
short drvNum; /*驅動號碼*/
char *name; /*設備名*/
}DEV_HDR;
系統調用iosDevAdd(),可以將設備加入到設備列表中。系統中將驅動和設備聯系起來的就是文件描述符列表,每個文件描述符列表除了包括驅動號、設備ID外,還包括文件名、可用標志和指向DEV_HDR的指針。系統每次成功執行open(),返回一個文件描述符,這樣對于設備的read()、write()及ioctl()就可以通過文件描述符進行。
文件描述符表(調試時調用iosFdShow()查看)如下:
I/O系統的整體結構如圖3所示。系統啟動時(一般掛接在usrroot()),XXDrv()和XXDevCreade()便將設備及其驅動加入相應的列表中。
3.3 設備驅動程序的訪問過程
下面以CAN驅動程序為例,說明驅動程序的訪問過程。(假定設備名“/can/1”并且以CAN設備驅動程序為例,上述中的XX在這里用Can代替。)
①fd=open(“/can/1”,O_RDWR,0644)
②I/O系統在設備列表中尋找設備名為/can/1的設備項,找到相應的設備驅動號。
③I/O系統在文件描述符中保留一個文件描述符空間。
④I/O系統在設備驅動列表中找到對應的CanOpen(CAN_DEV*PCAN_DEV,UBYTE*remainder,int flags),該驅動例程返回設備描述符的指針。
⑤I/O系統將設備描述符的指針存儲在文件描述符列表的Device ID,同時將對應的設備驅動號存儲在文件描述符的Driver num項。最后I/O系統返回該描述符項的索引(即為fd)。
⑥這樣應用程序中的read()和write()等函數調用就可以根據fd找到相應的設備驅動號,進而找到相應的驅動例程。
4 CAN驅動程序的實現
CAN驅動程序的實現即是完成下面七個函數的編寫。下面簡要介紹其完成的功能,并用偽指令進行說明。
int drv_num; ;/*驅動號碼*/
typedef struct {
DEV_HDR pCANHDR; /*這個數據結構必須放在設備描述符的最初部分*/
/*其余與驅動有關數據*/
}CAN_DEV; /*CAN設備描述符*/
CAN_DEV can_chan_dev;
STATUS CanDrv(void){
完成驅動的一些初始化;
intconnect(); /*連接所選的IRQ與中斷處理函數*/
sysIntEnablePIC(); /*486DX允許中斷*/
drv_num=iosDrvInstall(CanOpen,NULL,CanOpen,CanClose,CanRead,CanWrite,CanIoctl);/*將設備驅動例程裝入設備列表中*/
}
/*iosDrvInstall()將設備的CAN驅動例程加入設備驅動列表中,7個參數為7個驅動例程的進入點(entry point),如果沒有某個例程,則傳遞NULL。*/
STATUS CanDevCreate(){
完成一些設備初始化
iosDevAdd (&Can_chan_dev.pCANHDR,“can0”,drv_num);/*將設備放入設備驅動列表中*/
}
int CanOpen(CAN_DEV *pCan_Dev,UBYTE *remainder,int flags){
CAN卡硬件復位
CAN卡關中斷
CAN卡進入軟件復位模式
設置CAN卡工作寄存器,如接收碼寄存器和屏蔽碼寄存器等
CAN卡開中斷和進入操作模式
Return((int)pCan_Dev); /*注意必須返回設備描述結構指針*/
}
int CanRead(int CAN_DEV_ID,UBYTE * buf,int nBytes){
等待信號量(該信號量由中斷處理例程釋放)
從接收緩沖區讀取數據
釋放接收緩沖
返回接收數據數量
}
int CanWrite(int CAN_DEV_ID,UBYTE* buf,int nbyte){
查詢發送緩沖是否可用
向發送緩沖區寫數據
命令發送
查詢發送完成標志
返回發送數據數量
}
void interrupt_handle_routin(int arg){
處理中斷事件
發送(釋放)信號量
}
限于篇幅,其它函數略。
圖3 I/O系統整體結構
5 CAN驅動調試
硬件驅動的調試是件十分麻煩的事,經驗十分重要。這里簡要介紹幾個幫助調試的函數。
①可以調用iosDrvShow()、iosDevShow()及iosFdShow()查看相關內容,判斷并將驅動及設備中入相應列表。
②使用logMsg()現實相關內容,以定位錯誤。
初期調試,示波器和信號燈是非常有用的,可以確定硬件的工作狀況,從而有助于發現程序中的錯誤。
PCI總線規范是為提高微機總線的數據傳輸速度而制定的一種局部總線標準。在設計自行開發的基于PCI總線的數據傳輸設備時,需要開發相應的設備驅動程序。通常開發PCI設備驅動程序有多種模式,在Windows2000環境下,主要采用WDM模式。本文針對自行開發的基于PCI總線的CCD視頻信號傳輸控制卡,編寫了符合WDM模式的驅動程序。
1WDM模式驅動程序
1.1WDM模式(WindowsDriverModel)
Windows2000對驅動程序的編寫不再基于以往的Win3.x和Win9x下的VxD(虛擬設備驅動程序)結構,而是基于一種新的驅動模型——WDM(WindowsDriverModel)。
WDM為Windows98/2000/XP操作系統的設備驅動程序的設計提供了統一的框架。WDM來源于WindowsNT的分層32位設備驅動程序模型(layered32-bitdevicedrivermodel)。它支持更多的特性,如即插即用(PnP)、電源管理、WMI和NT事件。
1.2設備驅動程序
設備驅動程序是操作系統的一個組成部分,它由I/O管理器(I/OManager)管理和調動。Windows2000操作系統下的I/O管理器功能描述如圖1所示。
I/O管理器每收到一個來自用戶應用程序的請求就創建一個I/O請求包(IRP)的數據結構,并將其作為參數傳遞給驅動程序。驅動程序通過識別IRP中的物理設備對象(PDO)來區別是發送給哪一個設備。IRP結構中存放請求的類型、用戶緩沖區的首地址、用戶請求數據的長度等信息。驅動程序處理完這個請求后,在該結構中填入處理結果的有關信息,調用IoCompleteRequest將其返回給I/O管理器,用戶應用程序的請求隨即返回。訪問硬件時,驅動程序通過調用硬件抽象層的函數實現。
1.3DriverStudio工具簡介
NuMegaLab公司開發的DriverStudio是一整套開發、調試和檢測Windows平臺下設備驅動程序的工具軟件包。它把DDK(DeviceDevelopmentKit)封裝成完整的C++函數庫,根據具體硬件通過向導生成框架代碼,并且提供了一套完整的調試和性能測試工具SoftICE、DriverMonitor等。
2應用實例
本文利用PCI專用接口芯片PCI9052設計了一個數據傳輸控制卡。卡上主要的芯片有PCI9052、FIFO(CY7C4221)、CPLD(MAX7064S)和A/D轉換器(MAX1197)。傳輸卡硬件框圖如圖2所示。面陣CCD得到的視頻信號經過調理電路,生成的視頻調理信號通過A/D轉換器進行數字化處理,送入FIFO中。在CPLD的控制下,數據經過PCI9052送入PCI總線,再傳送到計算機內存中,并顯示在監視器上。驅動程序必須實現如下幾個基本功能:(1)硬件中斷;(2)能支持應用程序獲取數據;(3)能根據外部FIFO(CY7C4221)的狀態啟動或停止突發傳輸。
在數據輸入過程中,最重要的是對數據進行實時控制,因此需要硬件中斷。在中斷程序中,根據外部FIFO狀態完成數據的讀入。
2.1用DriverWizard生成驅動程序框架
DriverStudio中的DriverWorks軟件為開發WDM程序提供了一個完整的框架。它包含一個可快速生成WDM驅動程序框架的代碼生成向導工具DriverWizard,而且還帶有許多類庫。在用DriverWizard生成的程序框架中寫入相對于設備的特定代碼,編譯后即可得到所需的驅動程序。
在利用DriverWorksV2.7的向導DriverWizard完成驅動程序的框架時共有11個步驟,其中關鍵步驟有:
(1)在第四步中選中PCI,并在VendorID和DeviceID中分別輸入廠商號和設備號,還需填入PCISubsystemID和PCIRevisionID。這四項可以用網上的免費軟件PCITree或PCIView瀏覽PCI設備,用這兩個軟件也可以得到BAR0~BAR5的資源分配情況和中斷號。
(2)第七步IRP隊列排隊方法,它決定了驅動程序檢查設備的方式。本設計選SystemManaged,則所有的IRP排隊都由系統(即I/O管理器)完成。
(3)第九步是最關鍵的一步。首先在Resources中添加資源,在name中輸入變量名,在PCIBaseAddress中輸入0~5的序列號。0~5和BAR0~BAR5一一對應。在設置中斷對話框中,在name欄寫入中斷服務程序的名稱,選中創建中斷服務程序ISR?穴CreateISR?雪,不選創建延遲程序調用DPC(CreateDPC),選中MakeISR/DPCclassfunctions,使ISR/DPC成為設備類的成員函數。
其次選中Buffer以選取讀寫方式,用于描述與I/O操作相關的數據緩沖區。本設計需要快速傳送大量數據,因此采用DirectI/O方式。
(4)在第十步中,需要加入與應用程序或者其他驅動程序通信的I/O控制代碼參量。
2.2驅動程序模塊框圖和代碼分布
PCI設備驅動程序模塊包括配置空間的訪問模塊、IO端口模塊、內存讀寫模塊和終端模塊等。各模塊之間是對等的。驅動程序模塊框圖如圖3所示。
驅動程序初始化模塊代碼段放在#pragmacode_seg(″INT″)和#pragmacode_seg()之間。在系統初始化完成后,這部分代碼從內存中釋放,防止占用系統寶貴的內存資源。#pragmacode_seg()之后是驅動程序和系統的許多模塊的實現部分。這部分在驅動程序運行后不會從內存中釋放。
2.3驅動程序主要模塊的實現
(1)配置空間的訪問模塊
DriverWorks的KPciConfiguration類封裝了訪問PCI設備配置空間的所有操作。首先初始化這個類的實例:
KpciConfigurationPciConfig()m_Lower.TopOfStack());
/?觹m_Lower是KpnpLowerDevice類的對象。m_LowerTopOfStack()返回當前設備堆棧頂部的設備對象。*/
初始化完后可以直接利用成員函數ReadHeader/WriteHeader函數訪問所有的配置寄存器。
為了確定映射空間的類型和大小,先向目標基地址寄存器寫入0Xffffffffh,然后回讀該寄存器的值。如果最低位為1,表示映射于I/O空間,反之為存儲空間;如果映射于存儲空間,從第四位開始計算0的個數可以確定內存空間的大小;如果是I/O方式,從第二位開始計算0的個數可確定I/O空間的大小,最大為256字節。如果設備的存儲空間超過256字節,要實現設備的整個存儲部分的訪問,就必須采用內存映射。
(2)I/O操作模塊
Driverworks的KIoRange類封裝了I/O端口訪問的操作。部分代碼如下:
{……
KIORangeDevIoPort();//創建實例
NTSTATUSstatus=DevIoPort().Initialize(pResListTranslated,pResListRaW,PciConfig.BaseAddressIndexToOrdinal(0));
/*第一個參數為轉換后的資源列表指針;第二個參數為原始資源列表指針;第三個參數中的0為I/O口對應的基地址,用來轉換成特定端口資源的序數?*/
If(NT_SUCCESS(status))
{……
DevIoPort.inb(0,LineBuf1,10);
/*成功初始化后可分別用KIoRange類的成員函數inb(/outb)從端口中讀/寫字節*/
}
else{Invalidate();returnstatus;
/*未能初始化成功,錯誤信息在status中*/
{
……}
(3)內存讀寫模塊
DriverWorks的KMemoryRange類封裝了端口訪問的操作。
status=m_MemoryRange().Initialize(pResListTranslated,pResListRaw,PciConfig.BaseAddressIndexToOrdinal(0));
此函數的參數、意義及具體用法與I/O端口的操作基本相同。
內存對象也用來發送控制字,以控制CPLD的開始和停止等。實際上控制字是通過PCI9052發送的。該控制字地址已被映射成PCI的內存空間。所以定義一個指向內存空間的內存對象,通過該對象即可發送控制字。
(4)中斷模塊
在中斷模塊,首先要激活PCI9052中斷使能位,然后判斷硬件中斷響應是否產生,如果有,則進行突發傳輸,讀入FIFO中的數據。
BOOLEANTranCard::Isr_MyIrq(void)
{if(//中斷未產生)
{……
returnFALSE;}
else
{/*如果產生硬件中斷,設置命令寄存器,進行突發數據傳輸*/
returnTRUE;}
}
為了將硬件中斷與編寫的中斷服務程序連接在一起,采用InitializeAndConnect方法,部分代碼如下:
NTSTATUSTranCardDevice?押?押OnStartDevice(KIrpI)
{……
status=m_MyIrq.InitializeAndConnect(
pResListTranlated,
LinkTo(Isr_MyIrq),
This;)
……}
2.4驅動程序的調用
編寫驅動程序本身不是最終目的,最終目的是調用驅動程序管理資源,并為用戶應用程序使用。驅動程序加載以后,它的許多進程處于Idle狀態,實際上需要用戶應用程序去調用激活。應用程序利用Win32API直接調用驅動程序,實現驅動程序和應用程序的信息交互。
首先用CreateFile()打開設備,獲得一個指向設備對象的句柄。使用CreateFile函數時應注意:由于驅動程序是*.sys,所以第一個參數應該是這個設備對象的標志連接(symboliclink)。該標志連接名有一個設置數據文件搜索路徑的數字號,而這個數字號通常是零。如果這個連接名是″TranCard″,則傳遞給CreateFile的宇符串就是:″\\\\.\\TranCard0″。例如:
HANDLEhDevice=CreateFile(″\\\\.\\TranCard0″)GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL?,OPEN_EXISTING,0,NULL);
然后用DeviceIoControl()進行數據的傳送。最后用CloseHandle()關閉設備句柄。
下面是應用DeviceIoControl()程序片段。
{……
m_b=DeviceIoControl(hDevice,TRANCARD_IOCTL_
RECEIVE(buffer,sizeof,buffer,NULL,0,&buffersize,NULL);
……}
2.5驅動程序的調試
1.1學生感到程序設計較難理解
計算機程序設計的學習困境主要表現在概念難懂,技術難以掌握,理論與實踐的脫節等方面,尤其是在程序語言學習中面向對象程序設計語言時,絕大多數的學生不理解面向對象程序設計思想,不會使用類的思想進行程序設計。往往感到困難重重而方式深入學習,導致學習成績節節下滑,不利于后來其他計算機專業課的學習。
1.2主動學習能力差
學生長期在傳統應試教育環境影響下,形成了被動學習的習慣,缺乏學習的積極性與主動性,另外還有一些學生養成的不良學習習慣,在課堂學習中情緒比較懶散,精神比較散漫,對教師所講的內容沒有興趣,這樣很難提高學生學習成績,影響教學效果的提高。
1.3實踐能力不高
計算機是一門實踐性比較強的學科,不僅需要學生掌握基本的理論知識,更重要的是理論應用于實際的能力,因為學習計算機的目的就是解決實際中遇到的問題。但是在實際教學中,很多教師設計的教學目標脫離學生的應用宗旨,教學過程中理論課比較多,實踐課程比較少,這樣較難培養學生的實際動手操作能力,很難真正提高教學效果。
1.4教學方法單一
過去教師一般采用傳統的教學方法,從程序設計的概念出發,圍繞理論知識點加以講解,過多注重理論知識的講解,而教材中的實力一般與學生實際生活相差較遠,學生在學習的過程中感到生澀難懂,只會比葫蘆畫瓢,不會舉一反三,缺乏獨立思考問題和解決問題的能力。教師在教學過程中忽略了學生的主體地位,較難提高學生學習興趣,同時也達不到較好的學習效果。
2項目驅動教學模式特點
2.1項目實踐環境突出
項目驅動教學過程中,導師帶領學生在學習專業理論知識的同時進行實際應用項目的開發。學生與老師在學習的過程中始終處于一種相互配合、溝通的環境下,強調學生的自主學習、積極溝通、勇于實踐。學生在項目驅動下,帶著問題進行有效的學習,這樣能夠培養學生思維擴散能力、動手操作能力與團結合作精神。
2.2強調教師的引導作用
項目驅動教學模式注重把理論知識轉化為實際技術,在教學過程中教師僅僅起引導學習的作用,課堂的主體是學生。學生按照項目需求被劃分為若干個小組,導師在課堂中主要監督、指導學生行為,在項目學習過程中導師要隨時解答學生的疑問,為學生補充技能知識,實時啟發學生在項目學習中解決問題的正確思路,開發學生思維創造能力,幫助學生掌握項目技能。
2.3培養學生計算機專業能力
項目驅動模式的實施目的是提高學生軟件開發與應用能力,事件性知識一般比較隱蔽,而項目驅動教學能夠通過教學過程中各種功能的實施,使一些隱藏在軟件開發過程中的核心要素顯現出來,通過這種方式的學習,學生將很快的具備軟件應用開的基本能力,提高學生實踐能力與應用能力。
3項目驅動教學實施過程
3.1項目設計
項目驅動模式教學過程中,首先導師要根據程序設計教學內容,設定教學目標,將教學計劃、目標融入到教學項目中,然后將整個教學項目按照學習小組分成若干個獨立的小項目,再把這些小項目按組分配給學生,最后導師圍繞項目內容設計具體教學內容,項目來源一般源自于教師縱橫向教學項目。
3.2實施形式
利用項目驅動模式進行教學的過程中,學生需要進入專門的工作室進行軟件程序的學習與開發。在工作室中,主要的學習方式是自學,教師在這種模式下主要起引導作用,課程知識除了很少部分較深的理論課由導師專門講授以外,其他的課程都是學生圍繞項目進行自主學習、合作學習,主要學習方式包括:小組研討、導師解疑、技術交流、調查研究等形式;課程的具體的實施要根據教學內容以及學生的實際認知情況進行合理的分配。這種教學模式的目的在于各種信息技術及認知提高計算機教學質量和效率,培養學生自主學習能力、創新能力和勇于探索精神以及實踐能力。其中自主學習是由學生自己積極主動的去學習,在學習過程中導師的角色是解答疑問,并不是直接幫學生解決問題,導師可以向學生傳授解決問題的方法和思路,引導學生向正確的解答思路上靠,提供給學生解決問題的資料,引導學生圍繞疑問積極探索。如果學生在學習過程中遇到難以解決的問題,導師首先要積極引導學生找到解決問題的方法,同時教會學生利用移動通信、互聯網、QQ以及電子郵件等先進技術手段進行搜索或者在線討論與交流,尤其要教會學生怎樣使用互聯網查詢資料,豐富程序設計知識,提高深深學習能力。在個人自主學習的基礎上進行小組討論與交流,在交流中不僅擴展知識與視野,而且能培養團隊協作精神,增進同學之間的感情。導師還要積極引導學生發現規律,找到自己的不足,積極改正,不斷超越自我。
3.3項目驅動教學模式中的成績評定
成績評定是項目驅動模式教學的重要組成部分,成績評定一般具有激勵、引導和反饋的作用,能夠全面反映學生的近況。成績評定比較重視學生在學習過程中能否解決實際問題,旨在培養學生動手操作的能力和創新能力以及計算機素養,樹立科學精神和堅韌不拔的性格以及積極向上的人生觀。如果學生成績提高,教師要給予鼓勵和表揚,激勵學生再接再厲。成績評定的方式采用項目答辯的形式進行,每個小組派出一個代表作主辯手,其他學生補充,導師可以隨時提問,最后結合項目答辯情況給出學生最終考核成績。
中圖分類號:TP274.2 文獻標識碼:A 文章編號:1007-9416(2016)04-0000-00
在針對新一代多普勒氣象雷達實現多功能、多模式的目標實現上同時獲得更高質量的數據,對獲取雷達數據的速率和容量的要求越來越高。而伴隨軟件無線電技術的突破,雷達作業系統將有可能要直接從射頻采樣中獲得更豐富的數據。這些氣象雷達領域技術的發展,都對雷達高速數據采集傳輸提出了新的需求,現有的氣象雷達數據傳輸帶寬已經不能滿足需要了。對基于計算機平臺的氣象雷達作業系統,提出了關鍵部件商品斷檔和已有技術須適應計算機硬件環境的挑戰。鑒于現階段的各個類型的氣象雷達中,雷達數據還主要基于PCI總線進行傳輸,數據帶寬已經不能適應現代氣象雷達的發展,為保障已有氣象雷達設備能夠得到后續升級技術的儲備,研究氣象雷達數據在PCI-Express總線上的技術[1],將能解決主流計算機淘汰的PCI接口對氣象雷達數據處理后續發展的問題。
1 氣象雷達信號處理器介紹
該信號處理器是氣象雷達視頻I/Q數據采集和系統參數控制的核心板卡,其主要完成了PC機對中頻I/Q數據采集,接收機、發射機控制功能,其性能的好壞直接影響到了整個雷達系統的正常運行。通過接收串行格式的中頻數據,并將數據按照預先設定進行儲存,經由PCI-Express接口定時通知計算機獲取數據。也能通過它發送大量參數到外部串行接口,對硬件進行指定的參數傳遞。該雷達信號處理器采用美國PERICOM公司的PI7C9X130作為本地總線和PCI-Express總線的接口。PI7C9X130是一款x4的PCI-Express to PCI-X/PCI橋接芯片,本地端總線頻率最高可達133MHZ,數據位寬64bit。PI7C9X130擁有4KB的配置空間,其中前256字節是和PCI設備功能上是兼容的,其余是PCI-Express擴展配置空間[2]。
2 驅動程序設計
總線驅動程序由系統提供,本文只設計了PI7C9X130的功能驅動程序,它主要由驅動程序初始化、雙緩沖數據傳輸模塊兩部分組成。基本思想是:驅動內設置DMA緩存和數據緩存(比DMA緩存大),采用中斷方式獲取板卡數據,當驅動收到一個外部數據中斷時,啟動DMA讀取乒乓FIFO中的數據到DMA緩存,每次讀完后,都復制DMA緩存到數據緩存區,以匹配DMA傳輸與上層應用程序Read數據的速度。
2.1 WDF驅動程序設計
DriverEntry是驅動程序的入口函數,負責初始化和構造驅動程序對象。系統啟動時,如果檢測到PI7C9X130的存在,I/O管理器會創建一個未初始化的驅動程序對象并將它作為一個參數傳給DriverEntry。DriverEntry根據這個對象創建WDFDRIVER對象,并注冊DeviceAdd例程并在此例程中進行設備驅動初始化,包括創建設備擴展對象并分配初始化各個子對象,包括WDFINTERRUPT、WDFQUEUE、WDFDPC、 WDFDMAENABLR等[3]。
2.2 雙緩存數據傳輸
功能驅動正常裝載后,應用程序就可以向驅動發起打開中斷請求,數據卡在中斷開啟的情況下在獲得數據后會產生外部中斷,在驅動中斷處理服務例程中,排隊一個DMA傳輸DPC(Delayed Procedure Call)事件,進行數據傳輸。當DMA完成傳輸,產生DMA完成中斷,通過中斷服務例程排隊一個數據復制事件,把DMA緩存的數據復制到數據緩存中。應用程序只要調用Read,就可以讀取數據緩存中的雷達中頻數據,而不用擔心因為進程切換等系統因素導致的DMA數據傳輸和應用層Read速度不匹配問題。
2.3 內核驅動程序調試
本文采用微軟隨WDK一起的調試工具WinDbg調試驅動程序。WinDbg是一種內核模式和用戶模式的調試器,可以用來分析故障存儲文件和執行驅動程序代碼。采用雙機調試:目標機(氣象雷達信號處理器)和主機(運行WinDbg的機器),用串口線連接,主機控制和監視目標機上的活動[4]。設置好主機和目標機后,通過WinDbg的命令窗口可以設置斷點、觀察調試輸出信息或分析目標機藍屏產生的故障存儲文件。
3 結語
本文介紹了基于PCI-Express總線的氣象雷達信號處理器的驅動程序開發。經實測,該數據處理器穩定傳輸速度達到530Mbyte/s,超越原基于PCI總線的數據處理器速度,適應氣象雷達大幅度增長的探測原始信息量,為新一代多普勒氣象雷達關鍵技術的發展提供了可行的方案。
參考文獻
[1] 何建新.現代天氣雷達[M].四川:電子科技大學出版社,2004-05.
[2] 孟會,劉雪峰.PCI Express總線技術分析[J].計算機工程,2006(32):252-258.
[3] 武安河.Windows設備驅動程序WDF開發[M].北京.電子工業出版社,2009
1 嵌入式Linux系統
1.1 Linux操作系統
Linux是一套可以免費使用和自由傳播的類UNIX操作系統,其實際上只是一個操作系統的內核,主要用于Intel x86系列CPU的計算機上[ ]。
談及Linux的起源,其靈感源自于UNIX。UNIX操作系統于1969年由Bell實驗室設計開發,之后Linus Torvalds設計了Linux,該系統在發展初期就得到了廣大程序員的幫助,逐步發展成為現今這樣一個擁有自己版權的完整的系統。
Linux具有很多特點,如支持多種體系結構,支持大量的設備,具有完善的網絡功能,開放源代碼,軟件資源豐富,內核穩定等,可總結為以下幾點:
(1)強大的編程能力[ ]。由于Linux源自于世界各地成千上萬的程序員和黑客,使得Linux就猶如加入到了一個高手如云的編程組織中,同時,由于GPL的存在,Linux開放源碼,吸引更多專業人士的加入,在這種需求的刺激下,Linux提供的開發工具功能也越來越完善,越來越強大。
(2)完善的組網能力。Linux具有強大的組網能力,它對當前的TCP/IP協議[ ]提供了完全的支持,同時也支持下一代Internet協議IPv6。在安全性方面,Linux內核中包括了IP防火墻代碼、IP防偽及IP服務質量控制等特性。現階段,Linux廣泛用于服務器,其可以作為Windows客戶機的打印和文件服務器,也可用做NT的文件和打印服務器,甚至可作為Macintosh客戶機的文件和打印服務器。另外,Linux還包括了一個Ftp服務器、一個電子郵件傳輸程序以及POP和IMAP郵件服務程序。
(3)Linux是自由開放的。Linux是自由軟件,允許成千上萬的人檢查軟件,修改軟件,最終可以按照用戶自己的意愿來定義自由軟件,可以定制自己的Linux。
(4)系統穩定。Linux提供了完全的內存保護機制,每個進程都運行在各自的虛擬地址空間中,不會損壞進程或內核使用的地址空間。一臺運行Linux的機器啟動一次可以運行數個月。在安全性的較量上,Linux明顯比Windows98和NT占上風。據統計分析,Linux是目前最安全的操作系統。
1.2 嵌入式系統
最早期的8位/16位系統,大多都是沒有操作系統的,然而在進入32位時代之后,系統軟件變得越來越復雜,出現了控制能力不夠,維護成本過高,系統升級困難等問題,促使了操作系統的迅猛發展。而嵌入式操作系統,則被定義為“以應用為中心、以計算機技術為基礎、軟硬件可裁剪、適應應用系統,對功能、可靠性、成本、功耗等方面有嚴格要求的專用計算機系統”。
嵌入式操作系統的特點有:提供較好的內核管理、多任務管理、資源管理、穩定性好、可裁剪和配置、滿足實時性需求、針對性強等。隨著計算機信息技術的不斷發展,嵌入式操作系統也在不斷演化升級,常見的有uC/OSⅡ操作系統,eCOS操作系統,VxWorks嵌入式實時操作系統,WinCE操作系統以及Linux操作系統等。嵌入式Linux利用嵌入式系統實時性、穩定性的特性和Linux相輔相成,很好的彌補了Linux實時性差的缺點,使得Linux在嵌入式領域發展迅速。近年來,嵌入式Linux操作系統的應用相當熱門,已經廣泛應用于筆記本電腦、連網裝置、網絡電視等各式各樣的通信基礎產品中。
2 系統硬件環境
2.1 Intel的XScale系統結構
XScale系統結構是對StrongARM的系統結構的擴充和改進。Intel的第一個StrongARM處理器SA-110實現了ARM系統結構的第4版,即ARMv4內核。StrongARM是ARM公司的注冊商標,最初由ARM公司與當時DEC公司聯合開發,由DEC生產和銷售,但是后來由Intel生產。SA-110是第一個采用哈佛結構的ARM內核,因此,它有兩個獨立的高速緩存和兩個MMU。這樣取指令與讀/寫就不需要在時間上互相錯開,從而提高了訪問高速緩存的速度。
2.2 PXA27x處理器
PXA27x處理器是Intel公司在2004年4月12日正式的當前最新的嵌入式處理器。它的時鐘頻率從312到624MHz,并內建64MB(megabytes)的堆棧型IntelStrataFlash內存。它內置了Intel公司的無線MMX技術,能夠為3D游戲與影片應用提供更高的效能,顯著提升多媒體性能。312MHz的CPU(PXA27x系列中最低時鐘頻率的產品)將達到520MHzARMCPU的多媒體處理效能,而鐘頻達到624MHz則可以具備775MHzARMCPU的表現。
3 系統軟件環境的建立
3.1 嵌入式操作系統的選擇
嵌入式操作系統的選擇主要從以下幾個方面加以考慮。
①操作系統的硬件支持:首先是否支持目標平臺,其次可移植性。②開發工具的支持程度:選擇嵌入式操作系統時必須考慮與之相關的開發工具。在線仿真器(ICE)、編譯器、匯編器、鏈接器、調試器以及模擬器等不同程度的影響到嵌入式軟件的開發。
③能否滿足應用要求:應用對操作系統的要求包括實時性能、不同語言的支持、標準兼容性、技術支持、源代碼還是目標代碼等等。
若找不到一個合適的操作系統或者買不起昂貴的商用操作系統,可以考慮自己建立一個操作系統。
3.2 系統結構設計
Trident PNX8471芯片平臺能夠接收BTSC(Broadcast Television System Committee),該平臺有兩個硬盤接口、一個MII 接口(Media Independent Interface,介質無關接口或稱為媒體獨立接口,它是IEEE-802.3定義的以太網行業標準。它包括一個數據接口,以及一個MAC和PHY之間的管理接口)、2個USB2.0接口、1個USB1.1接口、5路TS輸入接口、2路I2C,支持3D圖形加速。在性能上支持:視頻支持1080P60輸出,支持H.264、MPEG2、VC-1、DiVX、AVS等格式,同時也支持RMVB格式480P的輸出,3DTV支持H.264 MVC 1080P30輸出;音頻支持BTSC、CH3/4,輸出支持YPbPr、RGB、Y/C、CVBS;TS處理方面最大支持5路基帶輸入和4路DMA輸入,最大支持192個Filter。
Trident PNX8471芯片平臺的編譯使用GNU3.81,Perl版本5.8.8,支持Android2.3,Linux內核版本2.6.34。平臺在基于Android的架構上增加了數字電視相關的功能模塊。實現本項目的EPG功能,同時兼顧EPG功能的擴展性,我們需要在硬件抽象層增加Demux模塊,用來接收PSI/SI數據,這個部分將是Program模塊、Event模塊、Time模塊公用的模塊;在Libraries層增加Program模塊、Event模塊、Time模塊,用來實現節目、事件、時間的功能;在應用框架層(Application Framework)增加獲取EPG功能的EPG JNI接口;在應用層增加EPG的呈現。
4 結語
嵌入式系統已成為以高速CPU和嵌入式操作系統為核心的軟硬件綜合系統。系統兼容性好,效率高,而且具備文件和目錄管理、設備支持、多任務、網絡支持、圖形窗口及用戶界面等功能。
參考文獻:
[ ]彭曉明,王強.Linux核心源代碼分析[M].北京:人民郵電大學出版社,2000.
[2]李善平,劉文峰.Linux與嵌入式系統[M].北京:清華大學出版社,2006.3.