




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
Linux設備驅(qū)動廣州嵌入式軟件公共技術支持中心梁老師2007年07月Linux設備驅(qū)動廣州嵌入式軟件公共技術支持中心設備驅(qū)動概述操作系統(tǒng)是通過各種驅(qū)動程序來駕馭硬件設備,它為用戶屏蔽了各種各樣的設備,硬件設備的抽象。設備驅(qū)動程序:處理和管理硬件控制器的軟件。設備驅(qū)動程序是操作系統(tǒng)內(nèi)核和機器硬件之間的接口。設備驅(qū)動概述操作系統(tǒng)是通過各種驅(qū)動程序來駕馭硬件設備,它為用設備驅(qū)動概述設備由兩部分組成,一個是被稱為控制器的電器部分,另一個是機械部分。一組寄存器組被賦予到各個控制器。I/O端口包含4組寄存器,即狀態(tài)寄存器,控制寄存器,數(shù)據(jù)輸入寄存器,數(shù)據(jù)輸出寄存器。狀態(tài)寄存器擁有可以被CPU讀取的(狀態(tài))位,用來指示當前命令是否執(zhí)行完畢,或者字節(jié)是否可以被讀出或?qū)懭耄约叭魏五e誤提示。控制寄存器則用于啟動一條命令(指令)或者改變設備的(工作)模式。數(shù)據(jù)輸入寄存器用于獲取輸入的數(shù)據(jù)。數(shù)據(jù)輸出寄存器則向CPU發(fā)送結(jié)果。處理器和設備之間的基本界面是控制和狀態(tài)寄存器。設備驅(qū)動概述設備由兩部分組成,一個是被稱為控制器的電器部分,設備驅(qū)動概述寄存器擁有在I/O空間明確定義的地址范圍。通常這些地址在啟動時被分配。如果設備是靜態(tài)加載的,各個設備的地址范圍可能被預分配。這意味內(nèi)核包含了已存在設備的驅(qū)動程序。通過運行“cat/proc/ioports”命令檢查其所使用的地址范圍。第一列輸出顯示了端口的范圍而第二列則是擁用這些端口的設備。
設備驅(qū)動概述寄存器擁有在I/O空間明確定義的地址范圍。設備驅(qū)動概述設備驅(qū)動的概念是非常抽象的并且處于一臺計算上所運行軟件的最低層。由于直接到設備的硬件特性的限制。每個設備驅(qū)動都只管理一種單一類型的設備。如果一個應用程序向設備提出(操作)要求。內(nèi)核會聯(lián)系到對應的設備驅(qū)動,設備驅(qū)動接著向特定的設備發(fā)出命令。設備驅(qū)動是一個函數(shù)集合:包含了許多調(diào)用入口,類似于open,close,read,write,ioctl,llseek等。
設備驅(qū)動概述設備驅(qū)動的概念是非常抽象的并且處于一臺計算上所運設備驅(qū)動概述Linux操作系統(tǒng)把設備納入文件系統(tǒng)的范疇來管理。文件操作是對設備操作的組織和抽象。設備操作則是對文件操作的最終實現(xiàn)。每個設備都對應一個文件名,在內(nèi)核中也就對應一個索引節(jié)點。
對文件操作的系統(tǒng)調(diào)用大都適用于設備文件。
從應用程序的角度看,設備文件邏輯上的空間是一個線性空間(起始地址為0,每讀取一個字節(jié)加1)。從這個邏輯空間到具體設備物理空間(如磁盤的磁道、扇區(qū))的映射則是由內(nèi)核提供,并被劃分為文件操作和設備驅(qū)動兩個層次。設備驅(qū)動概述Linux操作系統(tǒng)把設備納入文件系統(tǒng)的范疇來管理設備驅(qū)動概述Linux將設備分成兩大類。一類像鍵盤那樣以字符(字節(jié))為單位,逐個字符進行輸入/輸出的設備,稱為字符設備。一類是像磁盤那樣以塊或扇區(qū)為單位,成塊進行輸入/輸出的設備,稱為塊設備。文件系統(tǒng)通常都建立在塊設備上。設備驅(qū)動概述Linux將設備分成兩大類。設備驅(qū)動概述文件操作和設備驅(qū)動是對一個具體的設備操作的不同層次。從這種觀點出發(fā),從概念上可以把一個系統(tǒng)劃分為應用、文件系統(tǒng)和設備驅(qū)動三個層次。設備驅(qū)動概述文件操作和設備驅(qū)動是對一個具體的設備操作的不同層設備驅(qū)動概述設備驅(qū)動概述設備驅(qū)動概述要使一項設備可以被應用程序訪問,首先要在系統(tǒng)中建立一個代表此設備的設備文件,這是通過系統(tǒng)調(diào)用mknode()實現(xiàn)的。此外,更重要的是在設備驅(qū)動層要有這種設備的驅(qū)動程序。設備驅(qū)動概述要使一項設備可以被應用程序訪問,首先要在系統(tǒng)中建設備驅(qū)動概述設備文件:任何設備都被當作路徑/dev的設備文件處理,并通過這些設備文件提供訪問硬件的方法。每個設備文件除了設備名外,還有類型、主設備號、次設備號這三個屬性。設備文件是通過mknod系統(tǒng)調(diào)用創(chuàng)建的。其原型為:mknod(constchar*filename,intmode,dev_tdev)mknod/dev/led0c2530設備驅(qū)動概述設備文件:設備驅(qū)動概述主設備號和次設備號:主設備號標識設備對應的驅(qū)動程序。一般“一個主設備號對應一個驅(qū)動程序”次設備號用于確定設備文件所指的設備??赏ㄟ^ls–l“設備文件名”命令查看設備的主次設備號,以及設備的類型。設備驅(qū)動概述主設備號和次設備號:設備驅(qū)動概述主設備號和次設備號的內(nèi)部表達:Dev_t類型用于保存設備號,稱為設備編號。/linux/types.h文件中定義。目前設備編號dev_t是一個32位的整數(shù),其中12位表示主設備號,20位表示次設備號。通過設備編號獲取主次設備號:MAJOR(dev_tdev);MINOR(dev_tdev);通過主次設備號合成設備編號:MKDEV(intmajor,intminor);Dev_t格式以后可能會發(fā)生變化,但只要使用這些宏,就可保證設備驅(qū)動程序的正確性。設備驅(qū)動概述主設備號和次設備號的內(nèi)部表達:一些重要的數(shù)據(jù)結(jié)構大部分驅(qū)動程序涉及三個重要的內(nèi)核數(shù)據(jù)結(jié)構:文件操作file_operations結(jié)構體文件對象file結(jié)構體索引節(jié)點inode結(jié)構體一些重要的數(shù)據(jù)結(jié)構大部分驅(qū)動程序涉及三個重要的內(nèi)核數(shù)據(jù)結(jié)構:一些重要的數(shù)據(jù)結(jié)構文件操作結(jié)構體file_operations結(jié)構體file_operations在頭文件linux/fs.h中定義,用來存儲驅(qū)動內(nèi)核模塊提供的對設備進行各種操作的函數(shù)的指針。結(jié)構體的每個域都對應著驅(qū)動模塊用來處理某個被請求的事務的函數(shù)的地址。structfile_operations{ structmodule*owner; loff_t(*llseek)(structfile*,loff_t,int); ssize_t(*read)(structfile*,char__user*,size_t,loff_t*); ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*);
。。。
}
一些重要的數(shù)據(jù)結(jié)構文件操作結(jié)構體file_operation一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員Structmodule*owner,指向擁有該結(jié)構體的模塊的指針。方法llseek用來修改文件的當前讀寫位置,把新位置作為返回值返回。方法read用來從設備中讀取數(shù)據(jù)。非負返回值表示成功讀取的直接數(shù)。方法write向設備發(fā)送數(shù)據(jù)。方法ioctl提供一種執(zhí)行設備特定命令的方法。一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員驅(qū)動內(nèi)核模塊是不需要實現(xiàn)每個函數(shù)的。相對應的file_operations的項就為NULL。Gcc的語法擴展,使得可以定義該結(jié)構體:
structfile_operationsfops={ read:device_read, write:device_write, open:device_open, release:device_release};這種語法清晰,沒有顯示聲明的結(jié)構體成員都被gcc初始化為NULL。一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員標準C的標記化結(jié)構體的初始化方法:
structfile_operationsfops={ .read=device_read, .write=device_write, .open=device_open, .release=device_release };
推薦使用該方法,提高移植性,方法允許對結(jié)構體成員進行重新排列。沒有顯示聲明的結(jié)構體成員同樣都被gcc初始化為NULL。指向結(jié)構體file_operations的指針通常命名為fops。一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員一些重要的數(shù)據(jù)結(jié)構文件對象file結(jié)構體 文件對象file代表著一個打開的文件。進程通過文件描述符fd與已打開文件的file結(jié)構相聯(lián)系。進程通過它對文件的線性邏輯空間進行操作。例如:file->f_op->read();Structfile在<linux/fs.h>中定義。指向結(jié)構體structfile的指針通常命名為filp,或者file。建議使用文件指針filp。一些重要的數(shù)據(jù)結(jié)構文件對象file結(jié)構體 一些重要的數(shù)據(jù)結(jié)構文件對象file結(jié)構體的成員Structfile_operations*f_op;
與文件相關的操作結(jié)構體指針。與文件相關的操作是在打開文件的時候確定下來的,也就是確定該指針的值。可在需要的時候,改變指針所指向的文件操作結(jié)構體。用C語言實現(xiàn)面向?qū)ο缶幊痰姆椒ㄖ剌d。其他成員可先忽略,后面具體實例分析。因為設備驅(qū)動模塊并不自己直接填充結(jié)構體file,只是使用file中的數(shù)據(jù)。一些重要的數(shù)據(jù)結(jié)構文件對象file結(jié)構體的成員一些重要的數(shù)據(jù)結(jié)構索引節(jié)點inode結(jié)構文件打開,在內(nèi)存建立副本后,由唯一的索引節(jié)點inode描述。與file結(jié)構不同。file結(jié)構是進程使用的結(jié)構,進程每打開一個文件,就建立一個file結(jié)構。不同的進程打開同一個文件,建立不同的file結(jié)構。Inode結(jié)構是內(nèi)核使用的結(jié)構,文件在內(nèi)存建立副本,就建立一個inode結(jié)構來描述。一個文件在內(nèi)存里面只有一個inode結(jié)構對應。一些重要的數(shù)據(jù)結(jié)構索引節(jié)點inode結(jié)構一些重要的數(shù)據(jù)結(jié)構索引節(jié)點inode結(jié)構Inode結(jié)構包含大量描述文件信息的成員變量。但是對于描述設備文件的inode,跟設備驅(qū)動有關的成員只有兩個。Dev_ti_rdev;包含真正的設備編號。Structcdev*i_cdev;指向cdev結(jié)構體的指針。cdev是表示字符設備的內(nèi)核數(shù)據(jù)結(jié)構。從inode中獲得主設備號和次設備號的宏:Unsignedintiminor(structinode*inode);Unsignedintimajor(structinode*inode);一些重要的數(shù)據(jù)結(jié)構索引節(jié)點inode結(jié)構驅(qū)動程序中的內(nèi)存分配在Linux內(nèi)核模式下,不能使用用戶態(tài)的malloc()和free()函數(shù)申請和釋放內(nèi)存。內(nèi)核編程最常用的內(nèi)存申請和釋放函數(shù)為kmalloc()和kfree(),其原型為:include/linux/kernel.hvoid*kmalloc(unsignedintlen,intpriority);voidkfree(void*__ptr);priority參數(shù):通常設置為GFP_KERNEL,可能會引起睡眠.如果在中斷服務程序里申請內(nèi)存則要用GFP_ATOMIC參數(shù),在中斷中是不允許睡眠的。驅(qū)動程序中的內(nèi)存分配在Linux內(nèi)核模式下,不能使用用戶態(tài)的初始化和卸載函數(shù)驅(qū)動程序是內(nèi)核的一部分,因此我們需要給其添加模塊初始化函數(shù),該函數(shù)用來完成對所控設備的初始化工作,并調(diào)用register_chrdev()函數(shù)注冊字符設備.intregister_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops);major是給定的主設備號。為0代表什么?name是驅(qū)動的名字(將出現(xiàn)在/proc/devices),fops是設備驅(qū)動的file_operations結(jié)構。register_chrdev將給設備分配0-255的次設備號,并且為每一個建立一個缺省的cdev結(jié)構。與模塊初始化函數(shù)對應的就是模塊卸載函數(shù),需要調(diào)用register_chrdev()的"反函數(shù)"初始化和卸載函數(shù)驅(qū)動程序是內(nèi)核的一部分,因此我們需要給其添加設備操作函數(shù)集的定義file_operations結(jié)構體,驅(qū)動程序只是利用其中的一部分。對于字符設備來說,要提供的主要入口有:open()、release()、read()、write()、ioctl()等。設備操作函數(shù)集的定義file_operations結(jié)構體,驅(qū)設備操作函數(shù)集的定義open()函數(shù)對設備特殊文件進行open()系統(tǒng)調(diào)用時,將調(diào)用驅(qū)動程序的open()函數(shù):int(*open)(structinode*,structfile*);參數(shù)inode為設備特殊文件的inode(索引結(jié)點)結(jié)構的指針,參數(shù)file是指向這一設備的文件結(jié)構的指針。open()的主要任務是確定硬件處在就緒狀態(tài)、驗證次設備號的合法性(次設備號可以用MINOR(inode->i-rdev)取得)、控制使用設備的進程數(shù)、根據(jù)執(zhí)行情況返回狀態(tài)碼(0表示成功,負數(shù)表示存在錯誤)等;設備操作函數(shù)集的定義open()函數(shù)設備操作函數(shù)集的定義release()函數(shù)當最后一個打開設備的用戶進程執(zhí)行close()系統(tǒng)調(diào)用時,內(nèi)核將調(diào)用驅(qū)動程序的release()函數(shù):void(*release)(structinode*,structfile*);release函數(shù)的主要任務是清理未結(jié)束的輸入/輸出操作、釋放資源、用戶自定義排他標志的復位等.設備操作函數(shù)集的定義release()函數(shù)設備操作函數(shù)集的定義read()函數(shù)Read的任務,就是從設備拷貝數(shù)據(jù)到用戶空間。當對設備特殊文件進行read()系統(tǒng)調(diào)用時,將調(diào)用驅(qū)動程序read()函數(shù):
ssize_tread(structfile*filp,char__user*buff, size_tcount,loff_t*offp);filp是文件對象指針,count
是請求的傳輸數(shù)據(jù)大小.buff
參數(shù)對write來說是指向持有被寫入數(shù)據(jù)的緩存,對read則是放入新數(shù)據(jù)的空緩存.offp
是指向一個“l(fā)ongoffsettype”的指針,它指出用戶正在存取的文件位置.返回值是“signedsizetype”類型;設備操作函數(shù)集的定義read()函數(shù)設備操作函數(shù)集的定義write()函數(shù)Write的任務,則從用戶空間拷貝數(shù)據(jù)到設備。當設備特殊文件進行write()系統(tǒng)調(diào)用時,將調(diào)用驅(qū)動程序的write()函數(shù):
ssize_twrite(structfile*filp,constchar__user *buff,size_tcount,loff_t*offp);filp是文件對象指針,count
是請求的傳輸數(shù)據(jù)大小.buff
參數(shù)對write來說是指向持有被寫入數(shù)據(jù)的緩存,對read則是放入新數(shù)據(jù)的空緩存.offp
是指向一個“l(fā)ongoffsettype”的指針,它指出用戶正在存取的文件位置.返回值是“signedsizetype”類型;設備操作函數(shù)集的定義write()函數(shù)設備操作函數(shù)集的定義read和write方法的buff參數(shù)是用戶空間指針,不能被內(nèi)核代碼直接解引用。__user字符串只是形式上的說明,表明是用戶空間地址。驅(qū)動必須能夠存取用戶空間緩存以完成它的工作。內(nèi)核如何解決這個問題?為安全起見,內(nèi)核提供專用的函數(shù)來完成對用戶空間的存取。這些專用函數(shù)在<asm/uaccess.h>中聲明。
unsignedlongcopy_to_user(void__user*to,constvoid*from,unsignedlongcount); unsignedlongcopy_from_user(void*to,constvoid__user*from,unsignedlongcount);大多數(shù)讀寫函數(shù)都會調(diào)用這兩個函數(shù),用于跟應用程序空間交流信息。設備操作函數(shù)集的定義read和write方法的bufRead和Write方法典型的Read函數(shù)對參數(shù)的使用。Read和Write方法典型的Read函數(shù)對參數(shù)的使用。S3C2410的I/O介紹S3C2410有117個復用功能輸入輸出端口引腳,這些引腳是:PortA(GPA):32個輸入/輸出端口PortB(GPB):11個輸入/輸出端口PortC(GPC):16個輸入/輸出端口PortD(GPD):16個輸入/輸出端口PortE(GPE):16個輸入/輸出端口PortF(GPF):8個輸入/輸出端口PortG(GPG):16個輸入/輸出端口PortH(GPH):11個輸入/輸出端口S3C2410的I/O介紹S3C2410有117個復S3C2410的I/O介紹端口控制說明端口配置寄存器(GPACON――GPHCON) 大部分的引腳是復用的,所以必須對于每個引腳要求定義一個功能,端口配置寄存器定義了每個引腳的功能。端口數(shù)據(jù)寄存器(GPADAT――GPHDAT) 如果端口配置成輸出端口,數(shù)據(jù)能夠被寫到端口數(shù)據(jù)寄存器的對應位,然后通過管腳輸出。如果端口配置成輸入端口,能從端口數(shù)據(jù)寄存器對應的位中讀出管腳上的電平端口上拉寄存器(GPBUP――GPHUP) 端口上拉寄存器控制著每個端口組的上拉寄存器的使能或禁止,當對應位為0,這個引腳的上拉寄存器是允許的,當為1時,上拉寄存器是禁止的。S3C2410的I/O介紹端口控制說明MIZI提供的S3C2410.H使用一個32位的數(shù)來表示端口的使用情況。模式|上拉|端口|端口引腳MODE|PULLUP|PORT|OFS不需要自己手動組合,通過宏定義以及SHIFT和MASK組合。見程序MIZI提供的S3C2410.H使用一個32位的數(shù)來表示端口MIZI提供的S3C2410.H端口的表示#definePORTA_OFS 0#definePORTB_OFS 1#definePORTC_OFS 2#definePORTD_OFS 3#definePORTE_OFS 4#definePORTF_OFS 5#definePORTG_OFS 6#definePORTH_OFS 7MIZI提供的S3C2410.H端口的表示MIZI提供的S3C2410.H端口引腳的表示#defineGPIO_A0 MAKE_GPIO_NUM(PORTA_OFS,0)#defineGPIO_A1 MAKE_GPIO_NUM(PORTA_OFS,1)#defineGPIO_A2 MAKE_GPIO_NUM(PORTA_OFS,2)#defineGPIO_A3 MAKE_GPIO_NUM(PORTA_OFS,3)。。。#defineMAKE_GPIO_NUM(p,o) ((p<<GPIO_PORT_SHIFTT)|(o<<GPIO_OFS_SHIFT))MIZI提供的S3C2410.H端口引腳的表示MIZI提供的S3C2410.Hset_gpio_ctrl(x)
功能:配置端口引腳的功能,設置IO口控制寄存器和上拉寄存器用法:set_gpio_ctrl(模式|上拉?|IO腳)模式|是否上拉|IO腳,在S3C2410.h中都有其定義好的名字。
set_gpio_ctrl(GPIO_E11|GPIO_PULLUP_DIS|GPIO_MODE_OUT);MIZI提供的S3C2410.Hset_gpio_ctrl(MIZI提供的S3C2410.Hwrite_gpio_bit(x,v)功能:把端口對應的端口數(shù)據(jù)寄存器x位設置為vwrite_gpio_bit(GPIO_E11,0);read_gpio_bit(x)
功能:把端口數(shù)據(jù)寄存器x位的狀態(tài)讀入,函數(shù)返回值既是其狀態(tài)read_gpio_bit(GPIO_G11);MIZI提供的S3C2410.Hwrite_gpio_bitMIZI提供的S3C2410.Hwrite_gpio_reg(x,v)功能:把端口數(shù)據(jù)寄存器x設置為vread_gpio_reg(x)
功能:讀取端口數(shù)據(jù)寄存器x,函數(shù)返回值既是其數(shù)據(jù)MIZI提供的S3C2410.Hwrite_gpio_reg按驅(qū)動的框架寫好驅(qū)動,實現(xiàn)初始化、卸載函數(shù),以及file_opertation操作集。對于led使用的gpio函數(shù),內(nèi)核沒有輸出作為公開符號,所以需要手動修改內(nèi)核代碼,代碼放在arch/arm/march-s3c2410/gpio.c,輸出符號:EXPORT_SYMBOL(s3c2410_gpio_setpin);EXPORT_SYMBOL(s3c2410_gpio_cfgpin);EXPORT_SYMBOL(s3c2410_gpio_pullup);編寫驅(qū)動模塊的Makefile。交叉編譯驅(qū)動模塊NFS加載驅(qū)動模塊,進行測試。按驅(qū)動的框架寫好驅(qū)動,實現(xiàn)初始化、卸載函數(shù),以及file_o嵌入式鍵盤驅(qū)動廣州嵌入式軟件公共技術支持中心梁老師2007年7月嵌入式鍵盤驅(qū)動廣州嵌入式軟件公共技術支持中心注冊中斷服務例程
中斷線是一個寶貴且常常有限的資源,特別當它們只有15個時。內(nèi)核維護一個中斷線的注冊表。要使用中斷線,就要進行中斷線的申請,也就是IRQ(InterruptReQuirement),因此我們也常把申請一條中斷線稱為申請一個IRQ或者是申請一個中斷號。IRQ線是從0開始順序編號的;第一條IRQ線通常表示成IRQ0。IRQn的缺省向量是n+32。注冊中斷服務例程中斷線是一個寶貴且常常有限的資源,特別當注冊中斷服務例程
并不是每個設備都可以向中斷線上發(fā)中斷信號的,只有對某一條確定的中斷線擁有了控制權,才可以向這條中斷線上發(fā)送信號。計算機的外部設備越來越多,所以15條中斷線已經(jīng)不夠用了,中斷線是非常寶貴的資源。只有當設備需要中斷的時候才申請占用一個IRQ,或者是在申請IRQ時采用共享中斷的方式,這樣可以讓更多的設備使用中斷。注冊中斷服務例程并不是每個設備都可以向中斷線上發(fā)中斷信號的注冊中斷服務例程
在<linux/interrupt.h>實現(xiàn)中斷注冊接口: intrequest_irq(unsignedintirq, irqreturn_t(*handler)(int,void*,structpt_regs*), unsignedlongflags, constchar*dev_name, void*dev_id ); voidfree_irq(unsignedintirq,void*dev_id);request_irq的返回值是0指示申請成功,為負值時表示錯誤碼。函數(shù)返回-EBUSY表示已經(jīng)有另一個驅(qū)動占用了所要申請的中斷線。注冊中斷服務例程在<linux/interrupt.h>注冊中斷服務例程
request_irq的參數(shù)說明:unsignedintirq,要申請的中斷號。對某些設備,如傳統(tǒng)PC設備上的系統(tǒng)時鐘或鍵盤,這個值通常是預先確定的。而對于大多數(shù)其它設備來說,這個值要么可以通過探測獲取,要么可以動態(tài)確定。irqreturn_t(*handler)(int,void*,structpt_regs*),要安裝的中斷處理函數(shù)指針。后面介紹。注冊中斷服務例程request_irq的參數(shù)說明:注冊中斷服務例程
request_irq的參數(shù)說明:unsignedlongflags,
與中斷管理相關的位掩碼選項。constchar*dev_name,
用在/proc/interrupts中顯示中斷的擁有者。void*dev_id
這個指針用于共享的中斷線。做為驅(qū)動程序的私有數(shù)據(jù)區(qū)(可用來識別那個設備產(chǎn)生的中斷)。不使用共享中斷線方式時,可設置為NULL。注冊中斷服務例程request_irq的參數(shù)說明:注冊中斷服務例程
flags參數(shù)的詳細說明:Flags的每個位有不同含義SA_INTERRUPT
當該位被設置時,表示這是一個“快速”中斷。快速中斷處理例程運行時,屏蔽中斷。SA_SHIRQ
這個位表示中斷可以在設備間共享。注冊中斷服務例程flags參數(shù)的詳細說明:proc文件系統(tǒng)中的中斷信息/proc/interrupts反映系統(tǒng)的中斷信息第一列是IRQ號給出每個中斷線發(fā)生中斷的次數(shù)。給出處理中斷的可編程中斷控制器。給出在該中斷號上注冊中斷處理例程的設備名稱。proc文件系統(tǒng)中的中斷信息/proc/interrupt實現(xiàn)中斷處理例程首先中斷處理例程也是普通的C程序。特別之處:在中斷時間內(nèi)運行,不能向用戶空間發(fā)送或者接收數(shù)據(jù)。不能做任何導致休眠的操作。不能調(diào)用schedule函數(shù)。無論快速還是慢速中斷處理例程,都應該設計成執(zhí)行時間盡可能短。實現(xiàn)中斷處理例程首先中斷處理例程也是普通的C程序。實現(xiàn)中斷處理例程中斷處理函數(shù)的參數(shù)和返回值irqreturn_t(*handler)(int,void*,structpt_regs*)irqreturn_tshort_interrupt(intirq,void*dev_id,structpt_regs*regs)Irq中斷號Dev_id驅(qū)動程序可用的數(shù)據(jù)區(qū),通常可傳遞指向描述設備的數(shù)據(jù)結(jié)構指針。structpt_regs*regs,保存了處理器進入中斷代碼之前的cpu寄存器的值。一般驅(qū)動可不要。實現(xiàn)中斷處理例程中斷處理函數(shù)的參數(shù)和返回值矩陣式鍵盤原理矩陣式鍵盤一般適用于按鍵數(shù)量較多的場合,它由行線和列線組成,按鍵位于行、列的交叉點上。如圖所示,一個4×4的行、列結(jié)構可以構成一個有16個按鍵的鍵盤。矩陣式鍵盤原理矩陣式鍵盤一般適用于按鍵數(shù)量較多的場合,它由行矩陣式鍵盤原理按鍵設置在行、列交叉點上,行、列分別連接到按鍵開關的兩端。行線通過上拉電阻接到十5V上。平時無按鍵動作時,行線處于高電平狀態(tài);而當有健按下時,行線電平狀態(tài)將由通過此按鍵的列線電平?jīng)Q定:列線電平如果為低,行線電平為低;列線電平如果為高,則行線電平亦為高。這一點是識別矩陣式鍵盤是否被按下的關鍵所在。矩陣式鍵盤原理按鍵設置在行、列交叉點上,行、列分別連接到按鍵矩陣式鍵盤原理矩陣鍵盤按鍵的識別方法分兩步進行:①識別鍵盤哪一行的鍵被按下。讓所有列線均為低電平,檢查各行線電平是否為低。如果有行線為低,則說明該行有鍵被按下,否則說明無鍵被按下。②如果某行有鍵被按下,識別鍵盤哪一列的鍵被按下(亦稱之為掃描法)。逐列置低電平,并置其余各列為高電平.檢查各行線電平的變化。如果行電平變?yōu)榈碗娖?,則可確定此行此列交叉點處按鍵被按下。矩陣式鍵盤原理矩陣鍵盤按鍵的識別方法分兩步進行:鍵盤的硬件實現(xiàn)鍵盤的硬件實現(xiàn)鍵盤的硬件實現(xiàn)4X4矩陣鍵盤四個輸入引腳:
EINT0-----(GPF0)----INPUT EINT2-----(GPF2)----INPUT EINT11-----(GPG3)----INPUT EINT19-----(GPG11)----INPUT四個輸出引腳:
KEYSCAN0---(GPE11)----OUTPUT KEYSCAN1---(GPG6)----OUTPUT KEYSCAN2---(GPE13)----OUTPUT KEYSCAN3---(GPG2)----OUTPUT鍵盤的硬件實現(xiàn)4X4矩陣鍵盤鍵盤的驅(qū)動實現(xiàn)引入結(jié)構體key_info對按鍵進行描述staticstructkey_info{ intirq_no;//外部中斷號
unsignedintgpio_port;//輸入端口,EINT unsignedintgpio_port_kscan;//輸出端口,OUTPUT intkey_no;//按鍵序號,或者名字}key_info_tab[16]={ ……}鍵盤的驅(qū)動實現(xiàn)引入結(jié)構體key_info對按鍵進行描述鍵盤初始化程序staticint__initmatrix4_buttons_init(void){ 注冊字符設備register_chrdev(……); 初始化按鍵對應的輸出端口buttons_io_port_init(); 采用中斷機制,注冊中斷號request_irqs();}鍵盤初始化程序staticint__initmatri鍵盤初始化程序/*初始化kscan口為輸出0*/staticvoidbuttons_io_port_init(void){ inti; for(i=0;i<sizeofkscan/sizeofkscan[1];i++){
set_gpio_ctrl(kscan[i]|GPIO_PULLUP_DIS|GPIO_MODE_OUT); write_gpio_bit(kscan[i],0); }}鍵盤初始化程序/*初始化kscan口為輸出0*/請求注冊中斷staticintrequest_irqs(void){ for(i=0;i<使用中斷個數(shù);i++){
設置與外部中斷號相對應的GPIO端口以及模式 請求中斷號,并注冊中斷響應函數(shù)。
}}請求注冊中斷staticintrequest_irqs(鍵盤驅(qū)動的卸載函數(shù)staticvoid__exitmatrix4_buttons_exit(void){ 釋放中斷free_irqs(…); 注銷字符設備unregister_chrdev(…);}鍵盤驅(qū)動的卸載函數(shù)staticvoid__exitma按鍵中斷處理buttons_irqstaticvoidbuttons_irq(intirq,void*dev_id,structpt_regs*reg){ 設置GPIO為輸入狀態(tài) 鍵盤掃描 喚醒按鍵等待隊列的進程 重新設置GPIO為輸出 重新設置中斷}按鍵中斷處理buttons_irqstaticvoidLinux設備驅(qū)動廣州嵌入式軟件公共技術支持中心梁老師2007年07月Linux設備驅(qū)動廣州嵌入式軟件公共技術支持中心設備驅(qū)動概述操作系統(tǒng)是通過各種驅(qū)動程序來駕馭硬件設備,它為用戶屏蔽了各種各樣的設備,硬件設備的抽象。設備驅(qū)動程序:處理和管理硬件控制器的軟件。設備驅(qū)動程序是操作系統(tǒng)內(nèi)核和機器硬件之間的接口。設備驅(qū)動概述操作系統(tǒng)是通過各種驅(qū)動程序來駕馭硬件設備,它為用設備驅(qū)動概述設備由兩部分組成,一個是被稱為控制器的電器部分,另一個是機械部分。一組寄存器組被賦予到各個控制器。I/O端口包含4組寄存器,即狀態(tài)寄存器,控制寄存器,數(shù)據(jù)輸入寄存器,數(shù)據(jù)輸出寄存器。狀態(tài)寄存器擁有可以被CPU讀取的(狀態(tài))位,用來指示當前命令是否執(zhí)行完畢,或者字節(jié)是否可以被讀出或?qū)懭?,以及任何錯誤提示??刂萍拇嫫鲃t用于啟動一條命令(指令)或者改變設備的(工作)模式。數(shù)據(jù)輸入寄存器用于獲取輸入的數(shù)據(jù)。數(shù)據(jù)輸出寄存器則向CPU發(fā)送結(jié)果。處理器和設備之間的基本界面是控制和狀態(tài)寄存器。設備驅(qū)動概述設備由兩部分組成,一個是被稱為控制器的電器部分,設備驅(qū)動概述寄存器擁有在I/O空間明確定義的地址范圍。通常這些地址在啟動時被分配。如果設備是靜態(tài)加載的,各個設備的地址范圍可能被預分配。這意味內(nèi)核包含了已存在設備的驅(qū)動程序。通過運行“cat/proc/ioports”命令檢查其所使用的地址范圍。第一列輸出顯示了端口的范圍而第二列則是擁用這些端口的設備。
設備驅(qū)動概述寄存器擁有在I/O空間明確定義的地址范圍。設備驅(qū)動概述設備驅(qū)動的概念是非常抽象的并且處于一臺計算上所運行軟件的最低層。由于直接到設備的硬件特性的限制。每個設備驅(qū)動都只管理一種單一類型的設備。如果一個應用程序向設備提出(操作)要求。內(nèi)核會聯(lián)系到對應的設備驅(qū)動,設備驅(qū)動接著向特定的設備發(fā)出命令。設備驅(qū)動是一個函數(shù)集合:包含了許多調(diào)用入口,類似于open,close,read,write,ioctl,llseek等。
設備驅(qū)動概述設備驅(qū)動的概念是非常抽象的并且處于一臺計算上所運設備驅(qū)動概述Linux操作系統(tǒng)把設備納入文件系統(tǒng)的范疇來管理。文件操作是對設備操作的組織和抽象。設備操作則是對文件操作的最終實現(xiàn)。每個設備都對應一個文件名,在內(nèi)核中也就對應一個索引節(jié)點。
對文件操作的系統(tǒng)調(diào)用大都適用于設備文件。
從應用程序的角度看,設備文件邏輯上的空間是一個線性空間(起始地址為0,每讀取一個字節(jié)加1)。從這個邏輯空間到具體設備物理空間(如磁盤的磁道、扇區(qū))的映射則是由內(nèi)核提供,并被劃分為文件操作和設備驅(qū)動兩個層次。設備驅(qū)動概述Linux操作系統(tǒng)把設備納入文件系統(tǒng)的范疇來管理設備驅(qū)動概述Linux將設備分成兩大類。一類像鍵盤那樣以字符(字節(jié))為單位,逐個字符進行輸入/輸出的設備,稱為字符設備。一類是像磁盤那樣以塊或扇區(qū)為單位,成塊進行輸入/輸出的設備,稱為塊設備。文件系統(tǒng)通常都建立在塊設備上。設備驅(qū)動概述Linux將設備分成兩大類。設備驅(qū)動概述文件操作和設備驅(qū)動是對一個具體的設備操作的不同層次。從這種觀點出發(fā),從概念上可以把一個系統(tǒng)劃分為應用、文件系統(tǒng)和設備驅(qū)動三個層次。設備驅(qū)動概述文件操作和設備驅(qū)動是對一個具體的設備操作的不同層設備驅(qū)動概述設備驅(qū)動概述設備驅(qū)動概述要使一項設備可以被應用程序訪問,首先要在系統(tǒng)中建立一個代表此設備的設備文件,這是通過系統(tǒng)調(diào)用mknode()實現(xiàn)的。此外,更重要的是在設備驅(qū)動層要有這種設備的驅(qū)動程序。設備驅(qū)動概述要使一項設備可以被應用程序訪問,首先要在系統(tǒng)中建設備驅(qū)動概述設備文件:任何設備都被當作路徑/dev的設備文件處理,并通過這些設備文件提供訪問硬件的方法。每個設備文件除了設備名外,還有類型、主設備號、次設備號這三個屬性。設備文件是通過mknod系統(tǒng)調(diào)用創(chuàng)建的。其原型為:mknod(constchar*filename,intmode,dev_tdev)mknod/dev/led0c2530設備驅(qū)動概述設備文件:設備驅(qū)動概述主設備號和次設備號:主設備號標識設備對應的驅(qū)動程序。一般“一個主設備號對應一個驅(qū)動程序”次設備號用于確定設備文件所指的設備。可通過ls–l“設備文件名”命令查看設備的主次設備號,以及設備的類型。設備驅(qū)動概述主設備號和次設備號:設備驅(qū)動概述主設備號和次設備號的內(nèi)部表達:Dev_t類型用于保存設備號,稱為設備編號。/linux/types.h文件中定義。目前設備編號dev_t是一個32位的整數(shù),其中12位表示主設備號,20位表示次設備號。通過設備編號獲取主次設備號:MAJOR(dev_tdev);MINOR(dev_tdev);通過主次設備號合成設備編號:MKDEV(intmajor,intminor);Dev_t格式以后可能會發(fā)生變化,但只要使用這些宏,就可保證設備驅(qū)動程序的正確性。設備驅(qū)動概述主設備號和次設備號的內(nèi)部表達:一些重要的數(shù)據(jù)結(jié)構大部分驅(qū)動程序涉及三個重要的內(nèi)核數(shù)據(jù)結(jié)構:文件操作file_operations結(jié)構體文件對象file結(jié)構體索引節(jié)點inode結(jié)構體一些重要的數(shù)據(jù)結(jié)構大部分驅(qū)動程序涉及三個重要的內(nèi)核數(shù)據(jù)結(jié)構:一些重要的數(shù)據(jù)結(jié)構文件操作結(jié)構體file_operations結(jié)構體file_operations在頭文件linux/fs.h中定義,用來存儲驅(qū)動內(nèi)核模塊提供的對設備進行各種操作的函數(shù)的指針。結(jié)構體的每個域都對應著驅(qū)動模塊用來處理某個被請求的事務的函數(shù)的地址。structfile_operations{ structmodule*owner; loff_t(*llseek)(structfile*,loff_t,int); ssize_t(*read)(structfile*,char__user*,size_t,loff_t*); ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*);
。。。
}
一些重要的數(shù)據(jù)結(jié)構文件操作結(jié)構體file_operation一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員Structmodule*owner,指向擁有該結(jié)構體的模塊的指針。方法llseek用來修改文件的當前讀寫位置,把新位置作為返回值返回。方法read用來從設備中讀取數(shù)據(jù)。非負返回值表示成功讀取的直接數(shù)。方法write向設備發(fā)送數(shù)據(jù)。方法ioctl提供一種執(zhí)行設備特定命令的方法。一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員驅(qū)動內(nèi)核模塊是不需要實現(xiàn)每個函數(shù)的。相對應的file_operations的項就為NULL。Gcc的語法擴展,使得可以定義該結(jié)構體:
structfile_operationsfops={ read:device_read, write:device_write, open:device_open, release:device_release};這種語法清晰,沒有顯示聲明的結(jié)構體成員都被gcc初始化為NULL。一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員標準C的標記化結(jié)構體的初始化方法:
structfile_operationsfops={ .read=device_read, .write=device_write, .open=device_open, .release=device_release };
推薦使用該方法,提高移植性,方法允許對結(jié)構體成員進行重新排列。沒有顯示聲明的結(jié)構體成員同樣都被gcc初始化為NULL。指向結(jié)構體file_operations的指針通常命名為fops。一些重要的數(shù)據(jù)結(jié)構file_operations重要的成員一些重要的數(shù)據(jù)結(jié)構文件對象file結(jié)構體 文件對象file代表著一個打開的文件。進程通過文件描述符fd與已打開文件的file結(jié)構相聯(lián)系。進程通過它對文件的線性邏輯空間進行操作。例如:file->f_op->read();Structfile在<linux/fs.h>中定義。指向結(jié)構體structfile的指針通常命名為filp,或者file。建議使用文件指針filp。一些重要的數(shù)據(jù)結(jié)構文件對象file結(jié)構體 一些重要的數(shù)據(jù)結(jié)構文件對象file結(jié)構體的成員Structfile_operations*f_op;
與文件相關的操作結(jié)構體指針。與文件相關的操作是在打開文件的時候確定下來的,也就是確定該指針的值??稍谛枰臅r候,改變指針所指向的文件操作結(jié)構體。用C語言實現(xiàn)面向?qū)ο缶幊痰姆椒ㄖ剌d。其他成員可先忽略,后面具體實例分析。因為設備驅(qū)動模塊并不自己直接填充結(jié)構體file,只是使用file中的數(shù)據(jù)。一些重要的數(shù)據(jù)結(jié)構文件對象file結(jié)構體的成員一些重要的數(shù)據(jù)結(jié)構索引節(jié)點inode結(jié)構文件打開,在內(nèi)存建立副本后,由唯一的索引節(jié)點inode描述。與file結(jié)構不同。file結(jié)構是進程使用的結(jié)構,進程每打開一個文件,就建立一個file結(jié)構。不同的進程打開同一個文件,建立不同的file結(jié)構。Inode結(jié)構是內(nèi)核使用的結(jié)構,文件在內(nèi)存建立副本,就建立一個inode結(jié)構來描述。一個文件在內(nèi)存里面只有一個inode結(jié)構對應。一些重要的數(shù)據(jù)結(jié)構索引節(jié)點inode結(jié)構一些重要的數(shù)據(jù)結(jié)構索引節(jié)點inode結(jié)構Inode結(jié)構包含大量描述文件信息的成員變量。但是對于描述設備文件的inode,跟設備驅(qū)動有關的成員只有兩個。Dev_ti_rdev;包含真正的設備編號。Structcdev*i_cdev;指向cdev結(jié)構體的指針。cdev是表示字符設備的內(nèi)核數(shù)據(jù)結(jié)構。從inode中獲得主設備號和次設備號的宏:Unsignedintiminor(structinode*inode);Unsignedintimajor(structinode*inode);一些重要的數(shù)據(jù)結(jié)構索引節(jié)點inode結(jié)構驅(qū)動程序中的內(nèi)存分配在Linux內(nèi)核模式下,不能使用用戶態(tài)的malloc()和free()函數(shù)申請和釋放內(nèi)存。內(nèi)核編程最常用的內(nèi)存申請和釋放函數(shù)為kmalloc()和kfree(),其原型為:include/linux/kernel.hvoid*kmalloc(unsignedintlen,intpriority);voidkfree(void*__ptr);priority參數(shù):通常設置為GFP_KERNEL,可能會引起睡眠.如果在中斷服務程序里申請內(nèi)存則要用GFP_ATOMIC參數(shù),在中斷中是不允許睡眠的。驅(qū)動程序中的內(nèi)存分配在Linux內(nèi)核模式下,不能使用用戶態(tài)的初始化和卸載函數(shù)驅(qū)動程序是內(nèi)核的一部分,因此我們需要給其添加模塊初始化函數(shù),該函數(shù)用來完成對所控設備的初始化工作,并調(diào)用register_chrdev()函數(shù)注冊字符設備.intregister_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops);major是給定的主設備號。為0代表什么?name是驅(qū)動的名字(將出現(xiàn)在/proc/devices),fops是設備驅(qū)動的file_operations結(jié)構。register_chrdev將給設備分配0-255的次設備號,并且為每一個建立一個缺省的cdev結(jié)構。與模塊初始化函數(shù)對應的就是模塊卸載函數(shù),需要調(diào)用register_chrdev()的"反函數(shù)"初始化和卸載函數(shù)驅(qū)動程序是內(nèi)核的一部分,因此我們需要給其添加設備操作函數(shù)集的定義file_operations結(jié)構體,驅(qū)動程序只是利用其中的一部分。對于字符設備來說,要提供的主要入口有:open()、release()、read()、write()、ioctl()等。設備操作函數(shù)集的定義file_operations結(jié)構體,驅(qū)設備操作函數(shù)集的定義open()函數(shù)對設備特殊文件進行open()系統(tǒng)調(diào)用時,將調(diào)用驅(qū)動程序的open()函數(shù):int(*open)(structinode*,structfile*);參數(shù)inode為設備特殊文件的inode(索引結(jié)點)結(jié)構的指針,參數(shù)file是指向這一設備的文件結(jié)構的指針。open()的主要任務是確定硬件處在就緒狀態(tài)、驗證次設備號的合法性(次設備號可以用MINOR(inode->i-rdev)取得)、控制使用設備的進程數(shù)、根據(jù)執(zhí)行情況返回狀態(tài)碼(0表示成功,負數(shù)表示存在錯誤)等;設備操作函數(shù)集的定義open()函數(shù)設備操作函數(shù)集的定義release()函數(shù)當最后一個打開設備的用戶進程執(zhí)行close()系統(tǒng)調(diào)用時,內(nèi)核將調(diào)用驅(qū)動程序的release()函數(shù):void(*release)(structinode*,structfile*);release函數(shù)的主要任務是清理未結(jié)束的輸入/輸出操作、釋放資源、用戶自定義排他標志的復位等.設備操作函數(shù)集的定義release()函數(shù)設備操作函數(shù)集的定義read()函數(shù)Read的任務,就是從設備拷貝數(shù)據(jù)到用戶空間。當對設備特殊文件進行read()系統(tǒng)調(diào)用時,將調(diào)用驅(qū)動程序read()函數(shù):
ssize_tread(structfile*filp,char__user*buff, size_tcount,loff_t*offp);filp是文件對象指針,count
是請求的傳輸數(shù)據(jù)大小.buff
參數(shù)對write來說是指向持有被寫入數(shù)據(jù)的緩存,對read則是放入新數(shù)據(jù)的空緩存.offp
是指向一個“l(fā)ongoffsettype”的指針,它指出用戶正在存取的文件位置.返回值是“signedsizetype”類型;設備操作函數(shù)集的定義read()函數(shù)設備操作函數(shù)集的定義write()函數(shù)Write的任務,則從用戶空間拷貝數(shù)據(jù)到設備。當設備特殊文件進行write()系統(tǒng)調(diào)用時,將調(diào)用驅(qū)動程序的write()函數(shù):
ssize_twrite(structfile*filp,constchar__user *buff,size_tcount,loff_t*offp);filp是文件對象指針,count
是請求的傳輸數(shù)據(jù)大小.buff
參數(shù)對write來說是指向持有被寫入數(shù)據(jù)的緩存,對read則是放入新數(shù)據(jù)的空緩存.offp
是指向一個“l(fā)ongoffsettype”的指針,它指出用戶正在存取的文件位置.返回值是“signedsizetype”類型;設備操作函數(shù)集的定義write()函數(shù)設備操作函數(shù)集的定義read和write方法的buff參數(shù)是用戶空間指針,不能被內(nèi)核代碼直接解引用。__user字符串只是形式上的說明,表明是用戶空間地址。驅(qū)動必須能夠存取用戶空間緩存以完成它的工作。內(nèi)核如何解決這個問題?為安全起見,內(nèi)核提供專用的函數(shù)來完成對用戶空間的存取。這些專用函數(shù)在<asm/uaccess.h>中聲明。
unsignedlongcopy_to_user(void__user*to,constvoid*from,unsignedlongcount); unsignedlongcopy_from_user(void*to,constvoid__user*from,unsignedlongcount);大多數(shù)讀寫函數(shù)都會調(diào)用這兩個函數(shù),用于跟應用程序空間交流信息。設備操作函數(shù)集的定義read和write方法的bufRead和Write方法典型的Read函數(shù)對參數(shù)的使用。Read和Write方法典型的Read函數(shù)對參數(shù)的使用。S3C2410的I/O介紹S3C2410有117個復用功能輸入輸出端口引腳,這些引腳是:PortA(GPA):32個輸入/輸出端口PortB(GPB):11個輸入/輸出端口PortC(GPC):16個輸入/輸出端口PortD(GPD):16個輸入/輸出端口PortE(GPE):16個輸入/輸出端口PortF(GPF):8個輸入/輸出端口PortG(GPG):16個輸入/輸出端口PortH(GPH):11個輸入/輸出端口S3C2410的I/O介紹S3C2410有117個復S3C2410的I/O介紹端口控制說明端口配置寄存器(GPACON――GPHCON) 大部分的引腳是復用的,所以必須對于每個引腳要求定義一個功能,端口配置寄存器定義了每個引腳的功能。端口數(shù)據(jù)寄存器(GPADAT――GPHDAT) 如果端口配置成輸出端口,數(shù)據(jù)能夠被寫到端口數(shù)據(jù)寄存器的對應位,然后通過管腳輸出。如果端口配置成輸入端口,能從端口數(shù)據(jù)寄存器對應的位中讀出管腳上的電平端口上拉寄存器(GPBUP――GPHUP) 端口上拉寄存器控制著每個端口組的上拉寄存器的使能或禁止,當對應位為0,這個引腳的上拉寄存器是允許的,當為1時,上拉寄存器是禁止的。S3C2410的I/O介紹端口控制說明MIZI提供的S3C2410.H使用一個32位的數(shù)來表示端口的使用情況。模式|上拉|端口|端口引腳MODE|PULLUP|PORT|OFS不需要自己手動組合,通過宏定義以及SHIFT和MASK組合。見程序MIZI提供的S3C2410.H使用一個32位的數(shù)來表示端口MIZI提供的S3C2410.H端口的表示#definePORTA_OFS 0#definePORTB_OFS 1#definePORTC_OFS 2#definePORTD_OFS 3#definePORTE_OFS 4#definePORTF_OFS 5#definePORTG_OFS 6#definePORTH_OFS 7MIZI提供的S3C2410.H端口的表示MIZI提供的S3C2410.H端口引腳的表示#defineGPIO_A0 MAKE_GPIO_NUM(PORTA_OFS,0)#defineGPIO_A1 MAKE_GPIO_NUM(PORTA_OFS,1)#defineGPIO_A2 MAKE_GPIO_NUM(PORTA_OFS,2)#defineGPIO_A3 MAKE_GPIO_NUM(PORTA_OFS,3)。。。#defineMAKE_GPIO_NUM(p,o) ((p<<GPIO_PORT_SHIFTT)|(o<<GPIO_OFS_SHIFT))MIZI提供的S3C2410.H端口引腳的表示MIZI提供的S3C2410.Hset_gpio_ctrl(x)
功能:配置端口引腳的功能,設置IO口控制寄存器和上拉寄存器用法:set_gpio_ctrl(模式|上拉?|IO腳)模式|是否上拉|IO腳,在S3C2410.h中都有其定義好的名字。
set_gpio_ctrl(GPIO_E11|GPIO_PULLUP_DIS|GPIO_MODE_OUT);MIZI提供的S3C2410.Hset_gpio_ctrl(MIZI提供的S3C2410.Hwrite_gpio_bit(x,v)功能:把端口對應的端口數(shù)據(jù)寄存器x位設置為vwrite_gpio_bit(GPIO_E11,0);read_gpio_bit(x)
功能:把端口數(shù)據(jù)寄存器x位的狀態(tài)讀入,函數(shù)返回值既是其狀態(tài)read_gpio_bit(GPIO_G11);MIZI提供的S3C2410.Hwrite_gpio_bitMIZI提供的S3C2410.Hwrite_gpio_reg(x,v)功能:把端口數(shù)據(jù)寄存器x設置為vread_gpio_reg(x)
功能:讀取端口數(shù)據(jù)寄存器x,函數(shù)返回值既是其數(shù)據(jù)MIZI提供的S3C2410.Hwrite_gpio_reg按驅(qū)動的框架寫好驅(qū)動,實現(xiàn)初始化、卸載函數(shù),以及file_opertation操作集。對于led使用的gpio函數(shù),內(nèi)核沒有輸出作為公開符號,所以需要手動修改內(nèi)核代碼,代碼放在arch/arm/march-s3c2410/gpio.c,輸出符號:EXPORT_SYMBOL(s3c2410_gpio_setpin);EXPORT_SYMBOL(s3c2410_gpio_cfgpin);EXPORT_SYMBOL(s3c2410_gpio_pullup);編寫驅(qū)動模塊的Makefile。交叉編譯驅(qū)動模塊NFS加載驅(qū)動模塊,進行測試。按驅(qū)動的框架寫好驅(qū)動,實現(xiàn)初始化、卸載函數(shù),以及file_o嵌入式鍵盤驅(qū)動廣州嵌入式軟件公共技術支持中心梁老師2007年7月嵌入式鍵盤驅(qū)動廣州嵌入式軟件公共技術支持中心注冊中斷服務例程
中斷線是一個寶貴且常常有限的資源,特別當它們只有15個時。內(nèi)核維護一個中斷線的注冊表。要使用中斷線,就要進行中斷線的申請,也就是IRQ(InterruptReQuirement),因此我們也常把申請一條中斷線稱為申請一個IRQ或者是申請一個中斷號。IRQ線是從0開始順序編號的;第一條IRQ線通常表示成IRQ0。IRQn的缺省向量是n+32。注冊中斷服務例程中斷線是一個寶貴且常常有限的資源,特別當注冊中斷服務例程
并不是每個設備都可以向中斷線上發(fā)中斷信號的,只有對某一條確定的中斷線擁有了控制權,才可以向這條中斷線上發(fā)送信號。計算機的外部設備越來越多,所以15條中斷線已經(jīng)不夠用了,中斷線是非常寶貴的資源。只有當設備需要中斷的時候才申請占用一個IRQ,或者是在申請IRQ時采用共享中斷的方式,這樣可以讓更多的設備使用中斷。注冊中斷服務例程并不是每個設備都可以向中斷線上發(fā)中斷信號的注冊中斷服務例程
在<linux/interrupt.h>實現(xiàn)中斷注冊接口: intrequest_irq(unsignedintirq, irqreturn_t(*handler)(int,void*,structpt_regs*), unsignedlongflags, constchar*dev_name, void*dev_id ); voidfree_irq(unsignedintirq,void*dev_id);request_irq的返回值是0指示申請成功,為負值時表示錯誤碼。函數(shù)返回-EBUSY表示已經(jīng)有另一個驅(qū)動占用了所要申請的中斷線。注冊中斷服務例程在<linux/interrupt.h>注冊中斷服務例程
request_irq的參數(shù)說明:unsignedintirq,要申請的中斷號。對某些設備,如傳統(tǒng)PC設備上的系統(tǒng)時鐘或鍵盤,這個值通常是預先確定的。而對于大多數(shù)其它設備來說,這個值要么可以通過探測獲取,要么可以動態(tài)確定。irqreturn_t(*handler)(int,void*,structpt_regs*),要安裝的中斷處理函數(shù)指針。后面介紹。注冊中斷服務例程request_irq的參數(shù)說明:注冊中斷服務例程
request_irq的參數(shù)說明:unsignedlongflags,
與中斷管理相關的位掩碼選項。constchar*dev_name,
用在/proc/interrupts中顯示中斷的擁有者。void*dev_id
這個指針用于共享的中斷線。做為驅(qū)動程序的私有數(shù)據(jù)區(qū)(可用來識別那個設備產(chǎn)生的中斷)。不使用共享中斷線方式時,可設置為NULL。注冊中斷服務例程request_irq的參數(shù)說明:注冊中斷服務例程
flags參數(shù)的詳細說明:Flags的每個位有不同含義SA_INTERRUPT
當該位被設置時,表示這是一個“快速”中斷??焖僦袛嗵幚砝踢\行時,屏蔽中斷。SA_SHIRQ
這個位表示中斷可以在設備間共享。注冊中斷服務例程flags參數(shù)的詳細說明:proc文件系統(tǒng)中的中斷信息/proc/interrupts反映系統(tǒng)的中斷信息第一列是IRQ號給出每個中斷線發(fā)生中斷的
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 衢州市文化課堂管理辦法
- 衡東縣基礎教育管理辦法
- 裕安區(qū)臨時用地管理辦法
- 西安市門頭管理暫行辦法
- 解放軍機槍庫存管理辦法
- 證監(jiān)局違規(guī)處罰管理辦法
- 負責人年薪管理暫行辦法
- 賬戶適當性管理暫行辦法
- 貴州省私車公用管理辦法
- 資產(chǎn)購置與驗收管理辦法
- 初中數(shù)學浙教版九年級上冊第4章 相似三角形4.3 相似三角形 全國公開課一等獎
- 主令電器(課用)課件
- DLT 5066-2010 水電站水力機械輔助設備系統(tǒng)設計技術規(guī)定
- 湘少版英語六年級下冊全冊教案
- 測繪生產(chǎn)困難類別細則及工日定額
- 貨架的技術說明(一)
- 湖南省長郡中學“澄池”杯數(shù)學競賽初賽試題(掃描版含答案)
- 消防系統(tǒng)施工總進度計劃
- 2022年廣東省中山市紀念中學三鑫雙語學校小升初數(shù)學試卷
- 2020年全國統(tǒng)一高考語文試卷(新高考ⅱ)(含解析版)
- JJG30-2012通用卡尺檢定規(guī)程
評論
0/150
提交評論