ARM9外接晶片读写的验证-以8255为范例

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

1ARM9外接晶片讀寫的驗証-以8255為範例外接8255主要目的是透過位址線及資料線做外接晶片讀寫的驗証。ARM9可透過如圖1所示的轉接訊號線擴充其他的晶片功能。DATA15DATA13DATA11DATA9DATA7DATA5DATA3DATA1DATA14DATA12DATA10DATA8DATA6DATA4DATA2DATA0A0A2A4A6A8A10A12A14nGCS2nRESET+5V+5VA1A3A5A7A9A11A13A15nOEnWEKBDINTP13圖1.ARM-9的轉接訊號線解碼位址圖2代表ARM-9的外接記憶體解碼位址分佈,共分8個區段(bank)。這些區段分別由nGCS0-nGCS7來解碼,每個區段(bank)共有128MB的記憶體空間。Bank0及Bank1分別由快閃記憶體(Flashmemory)及隨機讀取記憶體(SDRAM)所佔用。Bank2的解碼致能線nCGS2位於透過ARM-9發展板轉接槽的第34個接腳,如圖1所示。nCGS2解碼位址分佈於0x10000000-0x18000000,如圖2所示。2圖2.nGCS2的解碼位址分佈圖3中ARM9的記憶體區段(Bank)的解碼線nGCS2接8255的/CS;(A1,A0)分別接8255的(A1,A0);DATA7-DATA0分別接8255的D7-D0,如圖3所示。所以8255的(PORTA,PORTB,PORTC,CTL)的寫入位址定義如下:PORTA=0x10000000;PORTB=0x10000001;PORTB=0x10000002;CTL=0x10000003;3VDDCSRDWR330GNDRSTD0D1D2D3D4D5D6D7A0A1PA7PA6PA5PA4PA3PA2PA1PA0PB7PB6PB5PB4PB3PB2PB1PB02665368927282930313233343573738394012342524232221201918+5V4.7k+5V8255DIPDATA7-DATA0DATA0DATA7nGCS2nWEA1+5VnOEA0圖3.8255與ARM-9的連接方法ARM-9的資料線共有32位元(DATA31-DATA0)。然而外接記憶體(或I/O)可規劃為8位元、16位元及32位元共三種模式。究竟選擇那種模式,可透過規劃BWSCON暫存器的內容來決定。BWSCON暫存器的位址為0x48000000。規劃Bank2的外接記憶體(或I/O)資料線讀寫位元數為8位元,可規劃BWSCON暫存器的(bit9,bit8)為00,如圖4所示。程式規劃的參考方法如下圖4.BWSCON暫存器的bit10-bit0所規劃的功能4ARM-9外接記憶體(或I/O)的讀寫時序如圖6所示。圖6中讀寫的各項時間參數(Tacs,Tcos,Tacc,Tacp,Tcoh,Tcah)可由BANKCONx暫存器(x=0,1..5)來調整。BANKCON2暫存器的位址為0x4800000c,如圖5所示。圖5.BANKCON2暫存器的位址圖6.ARM-9外接記憶體(或I/O)的讀寫時序58255驅動程式之建立在Linux核心中,驅動程式扮演特殊的「黑盒子」角色,它們能駕馭硬體裝置,並且隱藏硬體的實際作業細節,使硬體的回應方式符合一組嚴謹規定的程式介面,讓應用程式能透過一套標準化的系統呼叫來間接操作硬體。以實際的硬體動作來實現系統呼叫所定義的功能,正是驅動程式所扮演的角色。由於系統呼叫這層軟體介面的存在,使得驅動程式與核心的其餘部分可以分開製作,並且在需要時,才在執行期將驅動程式「安插」到核心裡。這種模組化的設計,不僅降低了Linux驅動程式的設計難度,也使得核心不必為了支援新硬體而頻頻改版。裝置驅動程式大致分為區塊驅動程式、字元驅動程式及網路介面驅動程式。區塊驅動程式是以固定大小長度來傳送轉移資料,且大致是可以隨機存取資料的設備,如硬碟機或光碟機;字元裝置是可被當成一連串位元組(串流)來存取的裝置,也就是說這類裝置的存取方式就像檔案一樣。字元裝置驅動程式的主要任務,正是實現這種行為。這類驅動程式至少會實作四項系統呼叫,分別是open()、close()、read()和write()。我們所熟悉的操控台與序列埠(/dev/console、/dev/ttyS0…),就是典型的字元裝置,因為它們都可順利化身成「串流」。字元裝置必須透過檔案系統節點(filesystemnode)來存取;檔案系統節點俗稱為裝置檔(devicefile),例如/dev/tttyS0、/dev/console。字元裝置與一般正常檔案之間的最大差異,是一般檔案容許你任意改變存取點(檔案指標),但字元裝置大部分都只是資料通道,只能被循序存取。61模組程式的基本觀念一個驅動程式必須被撰寫成模組的型態,才能夠具備供使用者載入與移除的特性。因此一個驅動程式必然會具有載入模組函式與移除模組這兩個函式。故此兩個函式就分別載入驅動程式與移除驅動程式的角色。應用程式在啟動之後,從頭到尾都只執行同一件任務。另一方面,模組在被載入核心之後,必須先向核心註冊它自己,以便服務未來的request,而其”main”函式這時候就立即結束了。換言之,init_module()函式(模組的入口)的任務,是將模組的功能(函式)準備好,使這些功能可在事後被調用。模組的第二個入口點是cleanup_module(),它在模組被卸載之前會被叫用一次,其作用就是告訴核心:『我要離開了,別再叫我做任何事』。圖7描繪模組如何利用「函式呼叫」與「函式指標」,將新功能加到運行中的核心。應用程式則是在「使用者空間」(userspace)內運作。每當應用程式發出系統呼叫,或是發生硬體中斷時,LINUX便會將執行模式從user-space切換到kernel-space。驅動程式碼必須在kernel-space內運作。7圖7將模組連結至核心2主標號(Majornumber)與次標號(Minornumber)當使用者要存取字元裝置時,必須透過檔案系統裡的代表名稱,這些特殊檔是集中在/dev/目錄之下。使用指令ls-l/dev得到如圖8的結果。可看出在日期欄之前可以發現兩個以逗號隔開的數值,在逗號左方的數值是該裝置檔的「主編號」(majornumber),而逗號右方的數值是「次編號」(minornumber)。「主編號」代表裝置所配合驅動程式。當核心收到open()系統呼叫時,就是依據「主編號」來選擇驅動程式。另一方面,「次編號」的意義只有驅動程式自己才知道,核心會將使用者給定的次編號轉交給驅動8程式,核心本身用不到次編號。一般而言,驅動程式以次編號來辨識同類裝置的個體。圖8主編號與次標號要增加一個新驅動程式到系統,等於指派一個主編號給它。這項指派應該在驅動程式(模組)的初使期,藉由呼叫<linux/fs.h>所定義的register_chrdev()函式來完成:intregister_chrdev(unsignedintmajor,constchar*name,structfile_operation*fops);此函數的傳回值代表註冊動作的成功與否。負值表示失敗,0或正值表示成功。major引數是驅動程式想要註冊的主標號;name是裝置的名稱(如果註冊成功,這名稱將會出現在/proc/devices檔案的內容裡);fops是一個指標,指向一個「函式指標陣列」(arraryoffunctionpointers),此陣列紀錄了驅動程式各個入口點(作業方法)的位置。在驅動程式向核心完成了註冊之後,驅動程式的各項「作業方法」(operation)就與給定的主編號產生了關連性。每當有人對字元裝置檔進行某項操作時,核心就能從該裝置檔的主編號找出對應的驅動程式,並透過其file_operations結構來呼叫對應的作業方法。下一個問題是如何給應用程式一個名稱,讓它們能利用此9名稱來啟動驅動程式。這個名稱必須安插在/dev/目錄下,而且必須關連到驅動程式的主編號與次編號。在檔案系統製作節點的命令是mknod,你必須有特權身分(root)才能使用此工具。mknod至少需要四個參數,例如:mknod/dev/c8255_driverc420第一個引數是節點名稱,其後的三個引數分別是裝置類型(c代表chardevice)、主編號、以及次編號。就像任何儲存在磁碟上的普通檔案一樣,mknod所產生的裝置節點會被保存下來,除非刻意用rm命令刪除它們。我們在驅動程式主程式中做以下定義及宣告:#defineCHDRV_MAJOR42charCHDRV_NAME[]=c8255_driver;而我們系統實作時的驅動程式註冊的動作是在一個init_module程式中實現:intinit_module(void){if(register_chrdev(CHDRV_MAJOR,CHDRV_NAME,&c8255_chdrv_fops)){printk(kernel:%s:Unabletoregistercharacterdevice\n,CHDRV_NAME);return-EIO;}.................在模組被卸載之前,它必須先釋放主標號,而這個動作可由unregister_chrdev()完成,我們在模組的清理函式裡呼叫它:10voidcleanup_module(void){unregister_chrdev(CHDRV_MAJOR,CHDRV_NAME);printk(unloaded..\n);return;}CHDRV_MAJOR引數是要被釋放的主編號,CHDRV_NAME是當初註冊的裝置名稱。這兩個引數必須與當初呼叫register_chrdev()所用的引數一致,否則unregister_chrdev()將傳回-EINVAL。2檔案作業與file結構驅動程式內部以一個file結構來代表一個已開啟的裝置,核心透過一個file_operations結構來存取驅動程式內部的作業函式(method)。這結構定義在<linux/fs.h>。file_operations結構包括指向驅動程式的各種系統呼叫,例如read,write,open,release...。操作檔案結構的各種系統呼叫,其實際動作就是靠驅動程式內部的作業系統來達成的。file_operations結構宣告範例如下:staticstructfile_operationsc8255_chdrv_fops={NULL,/*lseek*/read:c8255_chdev_read,/*read*/write:c8255_chdev_write,/*write*/NULL,/*readdir*/NULL,/*POLL*/NULL,/*ioctl*/NULL,/*mmap*/open:c8255_chdev_open,/*open*/11NULL,/*FLUSH*/release:c8255_chdev_release,/*release*/NULL,/*fsync*/NULL,/*fasync*/NULL,/*lock*/NULL,/*readv*/NULL,/*writev*/NULL,/*sendpage*/NULL,/*getunmappedarea*/};習慣上,我們以變數名稱(例如c8255_chdrv_fops)來表示file_operations結構。在file_operations結構中每一個欄位,都必須指向驅動程式中負責特定作業方法,對於驅動程式不需要的作業項目,其對應欄位需指向NULL。我們在此文中所使用到的作業方法包括有read()、write()、open()及release(),在此做一個簡單的介紹。1.open()範例如下:intc8255_chdev_open(structinode*inode,structfile*file){printk(c8255_open\n);MOD_INC_USE_COUNT;return0;}這是裝置操作的第一步,一般會在此函

1 / 16
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功