




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、第7章 嵌入式Linux設備驅動程序開發 第第7 7章章 嵌入式嵌入式LinuxLinux設備驅動程序開發設備驅動程序開發 7.1 嵌入式嵌入式Linux的設備管理的設備管理7.2 設備驅動模塊化編程設備驅動模塊化編程7.3 GPIO字符設備驅動程序設計字符設備驅動程序設計7.4 A/D轉換器驅動程序設計轉換器驅動程序設計7.5 IC卡驅動程序設計卡驅動程序設計7.6 內核驅動程序設計內核驅動程序設計觸摸屏驅動程序觸摸屏驅動程序第7章 嵌入式Linux設備驅動程序開發 第第7章章 嵌入式嵌入式Linux設備驅動程序開發設備驅動程序開發 7.1 嵌入式嵌入式Linux的設備管理的設備管理設備驅動
2、程序實際是處理和操作硬件控制器的軟件,從本質上設備驅動程序實際是處理和操作硬件控制器的軟件,從本質上講,是內核中具有最高特權級的、駐留內存的、可共享的底層講,是內核中具有最高特權級的、駐留內存的、可共享的底層硬件處理例程。完成以下功能:硬件處理例程。完成以下功能: 對設備初始化和釋放;對設備初始化和釋放; 對設備進行管理,包括實時參數設置,以及提供對設備的操對設備進行管理,包括實時參數設置,以及提供對設備的操作接口;作接口; 讀取應用程序傳送給設備文件的數據或者回送應用程序請求讀取應用程序傳送給設備文件的數據或者回送應用程序請求的數據;的數據; 檢測和處理設備出現的錯誤。檢測和處理設備出現的錯
3、誤。第7章 嵌入式Linux設備驅動程序開發 整個設備管理子系統的結構如圖整個設備管理子系統的結構如圖7.1 所示。所示。 圖圖7.1設備管理系統結構設備管理系統結構 第7章 嵌入式Linux設備驅動程序開發 7.1.1 設備驅動和文件系統的關系設備驅動和文件系統的關系 open 打開設備準備打開設備準備I/O操作。操作。 其調用格式為其調用格式為: :int open(char *filename, int access); 第7章 嵌入式Linux設備驅動程序開發 close close() close close()函數的作用是關閉由函數的作用是關閉由open()open()函數打開的函
4、數打開的文件文件, , 其調用格式為其調用格式為: :int close(int handle);int close(int handle);該函數關閉文件描述字該函數關閉文件描述字handle handle 相連的文件。相連的文件。 read 從設備上讀數據。對于有緩沖區的從設備上讀數據。對于有緩沖區的I/O 操作,一般操作,一般是從緩沖區里讀數據。是從緩沖區里讀數據。 write write 往設備上寫數據,對于有緩沖區的往設備上寫數據,對于有緩沖區的I/O I/O 操作,一操作,一般是把數據寫入緩沖區里。般是把數據寫入緩沖區里。write()write()函數的調用格式為:函數的調用格式
5、為:int write(int handle, void int write(int handle, void * *buf, int count);buf, int count);write()write()函數把函數把count count 個字節從個字節從buf buf 指向的緩沖區寫入與指向的緩沖區寫入與handle handle 相連的文件中,返回值為實際寫入的字節數。相連的文件中,返回值為實際寫入的字節數。 第7章 嵌入式Linux設備驅動程序開發 ioctl ioctl主要用于對設備進行讀寫之外的其他控制。主要用于對設備進行讀寫之外的其他控制。用戶空間的用戶空間的ioctl io
6、ctl 函數的原型為:函數的原型為:int ioctl(inf fd,int cmd,)int ioctl(inf fd,int cmd,)其中的其中的代表可變數目的參數表,實際中是一個可選參數,一般定代表可變數目的參數表,實際中是一個可選參數,一般定義為義為: :int ioctl(inf fd,int cmd,char int ioctl(inf fd,int cmd,char * *argp)argp)驅動程序中定義的驅動程序中定義的ioctl ioctl 方法原型為:方法原型為:int (int (* *ioctl) (struct inode ioctl) (struct inode
7、 * *inode, struct file inode, struct file * *file,unsigned int cmd, unsigned long arg)file,unsigned int cmd, unsigned long arg)inode inode 和和filp filp 兩個指針對應應用程序傳遞的文件描述符兩個指針對應應用程序傳遞的文件描述符fdfd、cmd cmd 不會被修改地傳遞給驅動程序,可選的參數不會被修改地傳遞給驅動程序,可選的參數arg arg 則無論用戶應用程則無論用戶應用程序使用的是指針還是其他類型值,都以序使用的是指針還是其他類型值,都以unsi
8、gned long unsigned long 的形式傳遞的形式傳遞給驅動。給驅動。第7章 嵌入式Linux設備驅動程序開發 7.1.2 設備類型設備類型 Linux 中的設備可以分為三類:中的設備可以分為三類: 字符設備字符設備 塊設備塊設備 網絡設備網絡設備。 一個運行的一個運行的linux linux 系統,當前使用的設系統,當前使用的設備可以通過文件備可以通過文件/proc/devices/proc/devices 查看。查看。 第7章 嵌入式Linux設備驅動程序開發 7.1.3 設備號設備號 linux/uclinux linux/uclinux 內核還需要內核還需要 : :主設備
9、號主設備號標識設備對應的驅動程序。系統中不同標識設備對應的驅動程序。系統中不同的設備可以有相同的主設備號,主設備號相同的的設備可以有相同的主設備號,主設備號相同的設備使用相同的驅動程序。設備使用相同的驅動程序。 次設備號次設備號用來區分具體驅動程序的實例。一個主用來區分具體驅動程序的實例。一個主設備號可能有多個設備與之對應,這多個設備正設備號可能有多個設備與之對應,這多個設備正是在驅動程序內通過次設備號來進一步區分的。是在驅動程序內通過次設備號來進一步區分的。次設備號只能由設備驅動程序使用,內核的其他次設備號只能由設備驅動程序使用,內核的其他部分僅將它作為參數傳遞給驅動程序。部分僅將它作為參數
10、傳遞給驅動程序。第7章 嵌入式Linux設備驅動程序開發 字符型設備主設備號的添加和注銷字符型設備主設備號的添加和注銷 字符型設備主設備號的添加和注銷分別通過調用函數字符型設備主設備號的添加和注銷分別通過調用函數register_chrdev()register_chrdev()和和unregister_chrdev()unregister_chrdev()實現,這兩實現,這兩個函數原型在個函數原型在文件說明。文件說明。extern int register_chrdev(unsigned int major, extern int register_chrdev(unsigned int m
11、ajor, const char const char * *name, struct file_operations name, struct file_operations * *fops);fops);extern int unregister_chrdev(unsigned int major, extern int unregister_chrdev(unsigned int major, const char const char * *name);name);第7章 嵌入式Linux設備驅動程序開發 7.1.4 設備驅動中關鍵數據結構設備驅動中關鍵數據結構 在在linuxlinu
12、x系統中,設備驅動程序所提供系統中,設備驅動程序所提供的這組入口點由一個文件操作結構進行說的這組入口點由一個文件操作結構進行說明,分別是明,分別是: : file_operationsfile_operations數據結構數據結構 inodeinode數據結構數據結構 filefile數據結構數據結構, 它們定義于它們定義于Linux/fs.hLinux/fs.h文件中。文件中。 第7章 嵌入式Linux設備驅動程序開發 1. file_operations數據結構數據結構 struct file_operations struct file_operations struct module
13、struct module * *owner;owner;loff_t (loff_t (* *llseek) (struct file llseek) (struct file * *, loff_t, int);, loff_t, int);ssize_t (ssize_t (* *read) (struct file read) (struct file * *, char , char * *, size_t, loff_t , size_t, loff_t * *););ssize_t (ssize_t (* *write) (struct file write) (struct f
14、ile * *, const char , const char * *, size_t, loff_t , size_t, loff_t * *););int (int (* *readdir) (struct file readdir) (struct file * *, void , void * *, filldir_t);, filldir_t);unsigned int (unsigned int (* *poll) (struct file poll) (struct file * *, struct poll_table_struct , struct poll_table_s
15、truct * *););int (int (* *ioctl) (struct inode ioctl) (struct inode * *, struct file , struct file * *, unsigned int, unsigned , unsigned int, unsigned long);long);int (int (* *mmap) (struct file mmap) (struct file * *, struct vm_area_struct , struct vm_area_struct * *););int (int (* *open) (struct
16、inode open) (struct inode * *, struct file , struct file * *););int (int (* *flush) (struct file flush) (struct file * *););第7章 嵌入式Linux設備驅動程序開發 int (int (* *release) (struct inode release) (struct inode * *, struct file , struct file * *););int (int (* *fsync) (struct file fsync) (struct file * *,
17、struct dentry , struct dentry * *, int datasync);, int datasync);int (int (* *fasync) (int, struct file fasync) (int, struct file * *, int);, int);int (int (* *lock) (struct file lock) (struct file * *, int, struct file_lock , int, struct file_lock * *););ssize_t (ssize_t (* *readv) (struct file rea
18、dv) (struct file * *, const struct iovec , const struct iovec * *, unsigned long, , unsigned long, loff_t loff_t * *););ssize_t (ssize_t (* *writev) (struct file writev) (struct file * *, const struct iovec , const struct iovec * *, unsigned long, , unsigned long, loff_t loff_t * *););ssize_t (ssize
19、_t (* *sendpage) (struct file sendpage) (struct file * *, struct page , struct page * *, int, size_t, , int, size_t, loff_t loff_t * *, int);, int);unsigned long (unsigned long (* *get_unmapped_area)(struct file get_unmapped_area)(struct file * *,unsigned ,unsigned long,unsigned long,unsigned long,
20、unsigned long);long,unsigned long,unsigned long, unsigned long);第7章 嵌入式Linux設備驅動程序開發 在在file_operationsfile_operations數據結構中,指出了設備驅動程序所提供的入數據結構中,指出了設備驅動程序所提供的入口點位置,分別是:口點位置,分別是:owner module owner module 的擁有者。的擁有者。lseeklseek移動文件指針的位置,只能用于可以隨機存取的設備。移動文件指針的位置,只能用于可以隨機存取的設備。readread進行讀操作,進行讀操作,bufbuf為存放讀取
21、結果的緩沖區,為存放讀取結果的緩沖區,countcount為所要為所要讀取的數據長度。讀取的數據長度。writewrite進行寫操作,與進行寫操作,與readread類似。類似。readdirreaddir只用于文件系統,對設備無用。只用于文件系統,對設備無用。selectselect進行選擇操作。進行選擇操作。ioctlioctl進行讀、寫以外的其他操作。進行讀、寫以外的其他操作。第7章 嵌入式Linux設備驅動程序開發 mmapmmap用于把設備的內容映射到地址空間,一般只有塊設備驅用于把設備的內容映射到地址空間,一般只有塊設備驅動程序使用。動程序使用。openopen打開設備進行打開設備
22、進行I/OI/O操作。返回操作。返回0 0表示成功,返回負數表示表示成功,返回負數表示失敗。失敗。releaserelease關閉設備并釋放資源。即關閉設備并釋放資源。即close close 操作。操作。 flushflush清除內容,一般只用于網絡文件系統中。清除內容,一般只用于網絡文件系統中。fsyncfsync實現內存與設備的同步,如將內存數據寫入硬盤。實現內存與設備的同步,如將內存數據寫入硬盤。fasyncfasync實現內存與設備之間的異步通訊。實現內存與設備之間的異步通訊。locklock文件鎖定,用于文件共享時的互斥訪問。文件鎖定,用于文件共享時的互斥訪問。readvreadv
23、在進行讀操作前要驗證地址是否可讀。在進行讀操作前要驗證地址是否可讀。writevwritev在進行寫操作前要驗證地址是否可寫。在進行寫操作前要驗證地址是否可寫。第7章 嵌入式Linux設備驅動程序開發 2 2 inodeinode數據結構數據結構文件系統處理的文件所需要的信息在文件系統處理的文件所需要的信息在inodeinode(索引結點)數據結構中。(索引結點)數據結構中。InodeInode數數據結構提供了關于特殊設備文件據結構提供了關于特殊設備文件/dev/DriverName/dev/DriverName的信息,定義如下:的信息,定義如下: struct inodestruct ino
24、de稱做索引節點數據結構,稱做索引節點數據結構,inodeinode(索引結點)數據結構定義如下:(索引結點)數據結構定義如下:struct inode struct inode struct list_headstruct list_headi_hash; /i_hash; /指向哈希鏈表的指針指向哈希鏈表的指針struct list_headstruct list_headi_list; /i_list; /指向索引結點鏈表的指針指向索引結點鏈表的指針struct list_headstruct list_headi_dentry; /i_dentry; /指向目錄項鏈表的指針指向目錄項鏈
25、表的指針struct list_headstruct list_headi_dirty_buffers; /i_dirty_buffers; /指向指向“臟臟”緩沖區鏈表的指針緩沖區鏈表的指針struct list_headstruct list_headi_dirty_data_buffers; i_dirty_data_buffers; unsigned longunsigned longi_ino; /i_ino; /描述索引結點描述索引結點atomic_tatomic_ti_count; /i_count; /當前使用該結點的進程數當前使用該結點的進程數第7章 嵌入式Linux設備驅動
26、程序開發 kdev_tkdev_ti_dev; /i_dev; /設備類型設備類型umode_tumode_ti_mode; /i_mode; /文件類型文件類型nlink_tnlink_ti_nlink; /i_nlink; /與該結點建立鏈接的文件數與該結點建立鏈接的文件數uid_tuid_ti_uid; /i_uid; /文件擁有者的標識號文件擁有者的標識號gid_tgid_ti_gid; /i_gid; /文件擁有者的所在組的標識號文件擁有者的所在組的標識號kdev_tkdev_ti_rdev; /i_rdev; /實際設備標識號實際設備標識號loff_tloff_ti_size; /
27、i_size; /文件大小文件大小time_ttime_ti_atime; /i_atime; /文件最后訪問的時間文件最后訪問的時間time_ttime_ti_mtime; /i_mtime; /文件最后修改的時間文件最后修改的時間time_ttime_ti_ctime; /i_ctime; /結點最后修改的時間結點最后修改的時間unsigned intunsigned inti_blkbits; /i_blkbits; /位數位數unsigned longunsigned long i_blksize; /i_blksize; /塊大小塊大小unsigned longunsigned lo
28、ng i_blocks; /i_blocks; /文件所占用的塊數文件所占用的塊數unsigned longunsigned long i_version; /i_version; /版本號版本號struct semaphorestruct semaphorei_sem; /i_sem; /用于同步操作的信號量結構用于同步操作的信號量結構第7章 嵌入式Linux設備驅動程序開發 struct semaphorestruct semaphorei_zombie; /i_zombie; /索引結點的信號量索引結點的信號量struct inode_operationsstruct inode_ope
29、rations* *i_op; /i_op; /索引結點操作索引結點操作struct file_operationsstruct file_operations* *i_fop; /i_fop; /指向文件操作的指針指向文件操作的指針struct super_blockstruct super_block* *i_sb; /i_sb; /指向讀文件系統超級塊指針指向讀文件系統超級塊指針wait_queue_head_twait_queue_head_ti_wait;i_wait; /指向索引結點等待隊列的指針指向索引結點等待隊列的指針struct file_lockstruct file_lo
30、ck* *i_flock; /i_flock; /指向文件加鎖鏈表的指針指向文件加鎖鏈表的指針struct address_spacestruct address_space * *i_mapping; /i_mapping; /把所有可交換的頁面管理起來把所有可交換的頁面管理起來struct address_spacestruct address_space i_data; /i_data; /數據數據struct dquotstruct dquot* *i_dquotMAXQUOTAS; /i_dquotMAXQUOTAS; /索引結點的磁盤限額索引結點的磁盤限額struct list_h
31、eadstruct list_headi_devices; /i_devices; /設備文件形成的鏈表設備文件形成的鏈表struct pipe_inode_infostruct pipe_inode_info* *i_pipe; /i_pipe; /指向管道文件指向管道文件struct block_devicestruct block_device* *i_bdev; /i_bdev; /指向塊設備文件的指針指向塊設備文件的指針struct char_devicestruct char_device * *i_cdev; /i_cdev; /指向字符設備文件的指針指向字符設備文件的指針uns
32、igned longunsigned longi_dnotify_mask; i_dnotify_mask; 第7章 嵌入式Linux設備驅動程序開發 struct dnotify_structstruct dnotify_struct* *i_dnotify; i_dnotify; unsigned longunsigned longi_state; /i_state; /索引結點狀態標志索引結點狀態標志unsigned intunsigned inti_flags; /i_flags; /文件系統的安裝標志文件系統的安裝標志unsigned charunsigned chari_sock;
33、 /i_sock; /是否是套接字文件是否是套接字文件atomic_tatomic_ti_writecount; /i_writecount; /寫進程的引用計數寫進程的引用計數unsigned intunsigned inti_attr_flags; /i_attr_flags; /文件創建標志文件創建標志u32u32i_generation; /i_generation; /保留保留union union struct minix_inode_info struct minix_inode_infominix_i;minix_i; struct jffs2_inode_info struc
34、t jffs2_inode_infojffs2_i;jffs2_i; void void* *generic_ip;generic_ip; u; u; ; 第7章 嵌入式Linux設備驅動程序開發 3file數據結構數據結構 struct file struct file struct list_headstruct list_headf_list; /f_list; /打開的文件形成一個列表打開的文件形成一個列表 struct dentrystruct dentry* *f_dentry; /f_dentry; /指向相關目錄項的指針指向相關目錄項的指針struct vfsmount str
35、uct vfsmount * *f_vfsmnt; /f_vfsmnt; /執行執行VFSVFS掛載點的指針掛載點的指針struct file_operationsstruct file_operations* *f_op; /f_op; /執行文件操作的指針執行文件操作的指針atomic_tatomic_tf_count; /f_count; /使用該結構的進程數使用該結構的進程數unsigned int unsigned int f_flags;/f_flags;/文件打開的標志,如讀寫等文件打開的標志,如讀寫等mode_tmode_tf_mode; /f_mode; /文件打開的模式文件
36、打開的模式第7章 嵌入式Linux設備驅動程序開發 loff_tloff_tf_pos; /f_pos; /文件的當前位置文件的當前位置unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin; unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin; / /* *預讀標志、要預讀的最多頁面數、上次預讀后的文件指針、預預讀標志、要預讀的最多頁面數、上次預讀后的文件指針、預讀的字節數以及預讀的頁面數讀的字節數以及預讀的頁面數* */ /struct fown_structstru
37、ct fown_structf_owner; /f_owner; /文件的所有者文件的所有者unsigned intunsigned intf_uid, f_gid; /f_uid, f_gid; /用戶的用戶的UIDUID和和GIDGIDintint f_error; /f_error; /網絡寫操作錯誤碼網絡寫操作錯誤碼unsigned longunsigned longf_version; /f_version; /版本號版本號voidvoid * *private_data; /ttyprivate_data; /tty驅動程序使用驅動程序使用struct kiobufstruct k
38、iobuf* *f_iobuf;f_iobuf;longlong f_iobuf_lock; f_iobuf_lock;第7章 嵌入式Linux設備驅動程序開發 FileFile結構中與驅動相關的成員如下:結構中與驅動相關的成員如下:f_modef_mode標識文件的讀寫權限標識文件的讀寫權限f_posf_pos當前讀寫位置,類型為當前讀寫位置,類型為loff_t loff_t 是是64 64 位的數,只能讀不位的數,只能讀不能寫能寫; ;f_flagf_flag文件標志,主要用于進行阻塞文件標志,主要用于進行阻塞/ /非阻塞型操作時檢查非阻塞型操作時檢查f_opf_op文件操作的結構指針,內
39、核在文件操作的結構指針,內核在OPEN OPEN 時對此指針賦值。時對此指針賦值。private_data Openprivate_data Open系統調用在調用驅動程序的系統調用在調用驅動程序的open open 方法前,方法前,將此指針值將此指針值NULLNULL,驅動程序可以將這個字段用于任何目的,一般,驅動程序可以將這個字段用于任何目的,一般用它指向已經分配的數據,但在內核銷毀用它指向已經分配的數據,但在內核銷毀file file 結構前要在結構前要在release release 方法中釋放內存。方法中釋放內存。f_dentryf_dentry文件對應的目錄項結構,一般在驅動中用文
40、件對應的目錄項結構,一般在驅動中用filp-filp-f_dentry-d_inode f_dentry-d_inode 訪問索引節點時用到它。訪問索引節點時用到它。第7章 嵌入式Linux設備驅動程序開發 7.1.5 設備驅動開發中基本函數設備驅動開發中基本函數 1I/O口函數口函數 1)int check_region(unsigned int from, unsigned int extent); 2)void request_region(unsigned int from, unsigned int extent,const char *name);3 3)void release_
41、region(unsigned int from, unsigned int extent);void release_region(unsigned int from, unsigned int extent);在申請了在申請了I/OI/O端口之后,可以借助端口之后,可以借助asm/io.hasm/io.h中的如下幾個函數來訪問中的如下幾個函數來訪問I/OI/O端口:端口:inline unsigned int inb(unsigned short port); /inline unsigned int inb(unsigned short port); /讀取某個端口的值讀取某個端口的值i
42、nline unsigned int inb_p(unsigned short port);inline unsigned int inb_p(unsigned short port);inline void outb(char value, unsigned short port);/inline void outb(char value, unsigned short port);/向某個端口賦值向某個端口賦值inline void outb_p(char value, unsigned short port);inline void outb_p(char value, unsigned
43、 short port);其中其中inb_pinb_p和和outb_poutb_p插入了一定的延時以適應某些慢速的插入了一定的延時以適應某些慢速的I/OI/O端口。端口。 可以查詢可以查詢/proc/ioports文件獲得當前已經分配的文件獲得當前已經分配的I/O地址。地址。 第7章 嵌入式Linux設備驅動程序開發 2時鐘函數時鐘函數 與時鐘有關的系統調用有:與時鐘有關的系統調用有:#include #include #include #include struct timer_list struct timer_list struct timer_list struct timer_lis
44、t * *next;next;struct timer_list struct timer_list * *prev;prev;unsigned long expires;unsigned long expires;unsigned long data;unsigned long data;void (void (* *function)(unsigned long);function)(unsigned long);void add_timer(struct timer_list void add_timer(struct timer_list * * timer); timer);int
45、del_timer(struct timer_list int del_timer(struct timer_list * * timer); timer);inline void init_timer(struct timer_list inline void init_timer(struct timer_list * * timer); timer);第7章 嵌入式Linux設備驅動程序開發 3 3內存操作函數內存操作函數#include /linux/kernel.h#include /linux/kernel.h里聲明了里聲明了kmalloc()kmalloc()和和kfree()k
46、free(),用于在,用于在內核模式下申請和釋放內存。內核模式下申請和釋放內存。void void * * kmalloc(unsigned int len, int priority); kmalloc(unsigned int len, int priority);void kfree(void void kfree(void * * obj); obj);其中其中lenlen為申請的字節數,為申請的字節數,objobj為要釋放的內存指針。為要釋放的內存指針。prioritypriority為分為分配內存操作的優先級。配內存操作的優先級。與用戶模式下的與用戶模式下的malloc()mall
47、oc()不同,不同,kmalloc()kmalloc()申請空間有大小限制。申請空間有大小限制。長度是長度是2 2的整次方。可以申請的最大長度也有限制。另外的整次方。可以申請的最大長度也有限制。另外prioritypriority參數,通常使用時可以為參數,通常使用時可以為GFP_KERNELGFP_KERNEL,如果在中斷里調用,則用,如果在中斷里調用,則用GFP_ATOMICGFP_ATOMIC參數,因為使用參數,因為使用GFP_KERNELGFP_KERNEL則調用者可能進入則調用者可能進入sleepsleep狀狀態,在處理中斷時是不允許的。態,在處理中斷時是不允許的。kfree()kf
48、ree()釋放的內存必須是釋放的內存必須是kmalloc()kmalloc()申請的。如果知道內存的大小,也可以用申請的。如果知道內存的大小,也可以用kfree_s()kfree_s()釋放。釋放。第7章 嵌入式Linux設備驅動程序開發 4 4復制函數復制函數在用戶程序調用在用戶程序調用readread、writewrite時,因為進程的運行狀態由用戶態變為核心態,地時,因為進程的運行狀態由用戶態變為核心態,地址空間也變為核心地址空間。由于址空間也變為核心地址空間。由于readread、writewrite中參數中參數bufbuf是指向用戶程序的私有是指向用戶程序的私有地址空間的,所以不能直
49、接訪問,必須通過下面兩個系統函數來訪問用戶程序的地址空間的,所以不能直接訪問,必須通過下面兩個系統函數來訪問用戶程序的私有地址空間。私有地址空間。# include # include void memcpy_fromfs(void void memcpy_fromfs(void * * to,const void to,const void * * from,unsigned long n); from,unsigned long n);void memcpy_tofs(void void memcpy_tofs(void * * to,const void to,const void *
50、* from,unsigned long n); from,unsigned long n);memcpy_fromfsmemcpy_fromfs由用戶程序地址空間往核心地址空間復制,由用戶程序地址空間往核心地址空間復制,memcpy_tofsmemcpy_tofs則反之。則反之。參數參數toto為復制的目的指針,為復制的目的指針,fromfrom為源指針,為源指針,n n為要復制的字節數。為要復制的字節數。在設備驅動程序里,可以調用在設備驅動程序里,可以調用printkprintk來打印一些調試信息,來打印一些調試信息,printkprintk的用法與的用法與printfprintf類似。類
51、似。printkprintk打印的信息不僅出現在屏幕上,同時還記錄在文件打印的信息不僅出現在屏幕上,同時還記錄在文件syslogsyslog里。里。第7章 嵌入式Linux設備驅動程序開發 7.2 設備驅動模塊化編程設備驅動模塊化編程 7.2.1 設備驅動程序的開發流程設備驅動程序的開發流程 (1 1)硬件接口設計或使用嵌入式處理器的生產商提供參考接口電)硬件接口設計或使用嵌入式處理器的生產商提供參考接口電路。路。(2 2)定義設備號。)定義設備號。(3 3)實現初始化函數。在驅動程序中實現驅動的注冊和卸載。)實現初始化函數。在驅動程序中實現驅動的注冊和卸載。(4 4)設計所要實現的文件操作,
52、定義)設計所要實現的文件操作,定義file_operationsfile_operations結構。結構。(5 5)實現所需的文件操作調用,如)實現所需的文件操作調用,如readread、writewrite等。等。(6 6)實現中斷服務,并用)實現中斷服務,并用request_irqrequest_irq向內核注冊。向內核注冊。(7 7)編譯該驅動程序到內核中,或者用)編譯該驅動程序到內核中,或者用insmodinsmod命令加載模塊。命令加載模塊。(8)測試該設備,編寫應用程序,對驅動程序進行測試。)測試該設備,編寫應用程序,對驅動程序進行測試。 第7章 嵌入式Linux設備驅動程序開發
53、7.2.2 內核空間和用戶空間內核空間和用戶空間 系統態系統態: :在在Linux系統中,內核在最高級執行,也稱為系統中,內核在最高級執行,也稱為“系統態系統態”,在這一級任何操作都可以執行。,在這一級任何操作都可以執行。 用戶態:用戶態:而應用程序則用戶態執行在最低級,所謂的而應用程序則用戶態執行在最低級,所謂的“用戶態用戶態”,在這一級處理器禁止對硬件的直接訪問和對,在這一級處理器禁止對硬件的直接訪問和對內存的未授權訪問。內存的未授權訪問。 內核空間:內核空間:模塊運行的空間是在所謂的模塊運行的空間是在所謂的“內核空間內核空間”; 用戶空間:用戶空間:應用程序運行的空間是在應用程序運行的空
54、間是在“用戶空間用戶空間” ” 。 它們分別引用不同的內存映射,也就是程序代碼使用它們分別引用不同的內存映射,也就是程序代碼使用不同的不同的“地址空間地址空間”。第7章 嵌入式Linux設備驅動程序開發 7.2.3 7.2.3 設備注冊和初始化設備注冊和初始化 int register_chrdev(unsigned int major, const char *name, struct file_ operations *fops); 注冊成功,設備名就會出現在注冊成功,設備名就會出現在/proc/dvices文件中。文件中。LinuxLinux在在/dev/dev目錄中為每個設備建立一個文
55、件,用目錄中為每個設備建立一個文件,用ls lls l命令列出函數返回值,命令列出函數返回值,若小于若小于0 0,則表示注冊失敗;返回,則表示注冊失敗;返回0 0或者大于或者大于0 0的值表示注冊成功。的值表示注冊成功。 int unregister_chrdev(unsigned int major, const char int unregister_chrdev(unsigned int major, const char * *name);name); 此函數的參數為主設備號此函數的參數為主設備號majormajor和設備名和設備名namename。LinuxLinux內核把內核把na
56、mename和和majormajor在內核注冊的名稱對比,如果不相等,卸載失敗,并返回在內核注冊的名稱對比,如果不相等,卸載失敗,并返回EINVALEINVAL;如果;如果majormajor大于最大的設備號,也返回大于最大的設備號,也返回EINVALEINVAL。 第7章 嵌入式Linux設備驅動程序開發 設備驅動的初始化函數主要完成的功能是有以下設備驅動的初始化函數主要完成的功能是有以下5 5項:項:(1 1)對驅動程序管理的硬件進行必要的初始化。如:)對驅動程序管理的硬件進行必要的初始化。如:S3C2410XS3C2410X的的硬件寄存器設置。硬件寄存器設置。(2 2)初始化設備驅動相關
57、的參數。如:設備變量及設備相關的參)初始化設備驅動相關的參數。如:設備變量及設備相關的參數。數。(3 3)在內核注冊設備。調用)在內核注冊設備。調用register_chrdev()register_chrdev()函數來注冊設備。函數來注冊設備。(4 4)注冊中斷。如果設備需要)注冊中斷。如果設備需要IRQIRQ支持,則要使用支持,則要使用request_irq()request_irq()函數注冊中斷。函數注冊中斷。(5 5)其他初始化工作。主要包括給設備驅動程序申請包括內存、)其他初始化工作。主要包括給設備驅動程序申請包括內存、時鐘、時鐘、I/OI/O端口等在內的系統資源,這些資源也可以
58、在端口等在內的系統資源,這些資源也可以在openopen子程序子程序或者其他地方申請。這些資源不用時,應該釋放,以利于資源的共或者其他地方申請。這些資源不用時,應該釋放,以利于資源的共享。享。第7章 嵌入式Linux設備驅動程序開發 內核中驅動程序的初始化函數如下方式聲明:內核中驅動程序的初始化函數如下方式聲明:int _init chr_driver_init(void);int _init chr_driver_init(void);其中其中_init_init是必不可少的,在系統啟動時會由內核調用是必不可少的,在系統啟動時會由內核調用chr_driver_initchr_driver_i
59、nit,完成驅動程序的初始化。,完成驅動程序的初始化。以模塊的形式編寫驅動程序時,則要按照如下方式聲明:以模塊的形式編寫驅動程序時,則要按照如下方式聲明:int init_module(void)int init_module(void)當運行后面介紹的當運行后面介紹的insmodinsmod命令插入模塊時,會調用命令插入模塊時,會調用init_moduleinit_module函數完成初始化工作。函數完成初始化工作。 第7章 嵌入式Linux設備驅動程序開發 7.2.4 中斷管理中斷管理 設備驅動程序通過調用設備驅動程序通過調用request_irq函數來申請中斷,通過函數來申請中斷,通過f
60、ree_irq來釋放中斷。來釋放中斷。它們在它們在linux/sched.h中的定義如下:中的定義如下:int request_irq(unsigned int irq, void (*handler)(int irq,void dev_id,struct pt_regs *regs), unsigned long flags, const char *device, void *dev_id );void free_irq(unsigned int irq, void *dev_id);從從request_irq函數返回的值為函數返回的值為0時,表示申請成功;負值表示出現錯誤。時,表示申請成
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年度浙江省二級造價工程師之土建建設工程計量與計價實務考前沖刺試卷B卷含答案
- 內科帕金森病診療要點
- 闌尾炎并膿腫護理
- 治療腫瘤癥狀護理常規
- 怎樣做一個健康的人
- 地黃種植培訓課件
- ICU患者營養病例分享
- 冬季安全生產教育
- 上海醫藥線上面試題及答案
- 懸疑腦子測試題及答案
- T/CHES 43-2020水利水電工程白蟻實時自動化監測預警系統技術規范
- 稅務籌劃與稅務咨詢常年服務協議
- 學習給復旦大學建校120周年賀信心得體會
- 浙江省杭州市北斗聯盟2024-2025學年高一下學期4月期中聯考地理試卷(含答案)
- 核醫學講課比賽技巧與策略
- 2025年貴州六盤水市燃氣集團六盤水燃氣有限公司招聘筆試參考題庫含答案解析
- 妊娠期子宮蛻膜息肉診治中國專家共識(2024年版)解讀課件
- 幼兒園教育懲戒的邊界與藝術
- 交通安全與一氧化碳安全教育
- 2025年出版:全球市場工程機械多路換向閥總體規模、主要生產商、主要地區、產品和應用細分調研報告
- 電梯公告板制度
評論
0/150
提交評論