嵌入式第10章字符設(shè)備和驅(qū)動程序設(shè)計(jì)-陳文智._第1頁
嵌入式第10章字符設(shè)備和驅(qū)動程序設(shè)計(jì)-陳文智._第2頁
嵌入式第10章字符設(shè)備和驅(qū)動程序設(shè)計(jì)-陳文智._第3頁
嵌入式第10章字符設(shè)備和驅(qū)動程序設(shè)計(jì)-陳文智._第4頁
嵌入式第10章字符設(shè)備和驅(qū)動程序設(shè)計(jì)-陳文智._第5頁
已閱讀5頁,還剩35頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、1、字符設(shè)備驅(qū)動框架2、字符設(shè)備驅(qū)動開發(fā)3、GPIO驅(qū)動概述4、串行總線概述5、I2C總線驅(qū)動開發(fā)1、字符字符設(shè)備驅(qū)動設(shè)備驅(qū)動框架框架 Linux的一個重要特點(diǎn)就是將所有的設(shè)備都當(dāng)作文件來處理,其中就包括設(shè)備文件,它們可以使用和操作文件相同的、標(biāo)準(zhǔn)的系統(tǒng)調(diào)用接口來完成打開、關(guān)閉、讀寫和I/O控制操作,而驅(qū)動程序的主要任務(wù)也就是要實(shí)現(xiàn)這些系統(tǒng)調(diào)用函數(shù)。設(shè)備驅(qū)動程序?yàn)閼?yīng)用程序屏蔽了硬件的細(xì)節(jié)。字符設(shè)備驅(qū)動程序是嵌入式Linux最基本、也是最常用的驅(qū)動程序。它的功能非常強(qiáng)大,幾乎可以描述不涉及掛載文件系統(tǒng)的所有硬件設(shè)備。字符設(shè)備驅(qū)動程序的實(shí)現(xiàn)方式分為兩種:一種是直接編譯進(jìn)內(nèi)核,另一種是以模塊方式加載

2、,然后在需要使用驅(qū)動時加載。2、字符設(shè)備驅(qū)動開發(fā)對字符設(shè)備的訪問是通過文件系統(tǒng)內(nèi)的設(shè)備文件進(jìn)行的,或者稱為設(shè)備節(jié)點(diǎn)。它們通常位于/dev目錄。表示字符設(shè)備的設(shè)備文件可以通過“l(fā)s -l”命令輸出的第一列中的“c”來識別,而塊設(shè)備則用“b”標(biāo)識。主設(shè)備號用來標(biāo)識該設(shè)備的種類,也標(biāo)識了該設(shè)備所使用的驅(qū)動程序;次設(shè)備號由內(nèi)核使用,標(biāo)識使用同一設(shè)備驅(qū)動程序的不同硬件設(shè)備。設(shè)備設(shè)備號號在Linux內(nèi)核中,使用dev_t類型來表示設(shè)備號,這個類型在頭文件中定義。typedef _u32 _kernel_dev_t;typedef _kernel_dev_tdev_t;dev_t是一個32位的無符號數(shù),其高

3、12位用來表示主設(shè)備號,低20位用來表示次設(shè)備號。在2.6內(nèi)核中,可以容納大量的設(shè)備,而不像先前的內(nèi)核版本最多只能使用255個主設(shè)備號和255個次設(shè)備號。內(nèi)核主要提供了三個操作dev_t類型的函數(shù),它們分別是: MAJOR(dev)、MINOR(dev)和MKDEV(ma, mi)。 其中MAJOR(dev)用于獲取主設(shè)備號。 MINOR(dev)則用于獲取次設(shè)備號。 MKDEV(ma, mi) 根據(jù)主設(shè)備號ma和次設(shè)備號mi構(gòu)造dev_t設(shè)備號。在頭文件中給出了這些宏的定義#define MINORBITS20#define MINORMASK(1U MINORBITS)#define MI

4、NOR(dev)(unsigned int) (dev) & MINORMASK)#define MKDEV(ma,mi) (ma) MINORBITS) | (mi)注冊和注銷設(shè)備號在建立一個字符設(shè)備之前,驅(qū)動程序首先要做的一件事是向內(nèi)核請求分配一個或多個設(shè)備號。內(nèi)核專門提供了字符設(shè)備號管理的函數(shù)接口:int register_chrdev_region(dev_t first, unsigned int count, const char *name);int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned

5、 int count, const char *name);void unregister_chrdev_region(dev_t first, unsigned int count);register_chrdev_region函數(shù)和alloc_chrdev_region函數(shù)用于分配設(shè)備號,它們的區(qū)別是后者是以動態(tài)的方式分配的。unregister_chrdev_region函數(shù)則用于釋放設(shè)備號。關(guān)鍵關(guān)鍵數(shù)據(jù)結(jié)構(gòu)數(shù)據(jù)結(jié)構(gòu)多數(shù)情況下,基本的驅(qū)動程序操作都會涉及到內(nèi)核提供的三個關(guān)鍵數(shù)據(jù)結(jié)構(gòu),分別是file_operations、file和inode,它們都在頭文件中定義。 struct file

6、_operations struct file struct inodefile_operationsfile_operations結(jié)構(gòu)體描述了一個文件操作所需要的所有函數(shù)。這組函數(shù)是以函數(shù)指針的形式給出的,它們是字符設(shè)備驅(qū)動程序設(shè)計(jì)的主要內(nèi)容。每個打開的文件,在內(nèi)核里都用file結(jié)構(gòu)體表示,這個結(jié)構(gòu)體中有一個成員為f_op,它是指向一個file_operations結(jié)構(gòu)體的指針。通過這種形式將一個文件同它自身的操作函數(shù)關(guān)聯(lián)起來,這些函數(shù)實(shí)際上是系統(tǒng)調(diào)用的底層實(shí)現(xiàn)。在用戶空間的應(yīng)用程序調(diào)用內(nèi)核提供的open、close、read、write等系統(tǒng)調(diào)用時,實(shí)際上最終會調(diào)用這些函數(shù)。file_op

7、erations編寫驅(qū)動程序的主要工作就是實(shí)現(xiàn)這些函數(shù)中的一部分,具體實(shí)現(xiàn)哪些函數(shù)因?qū)嶋H需要而定。對于一個字符設(shè)備來說,一般只要實(shí)現(xiàn)open、release、read、write、mmap、ioctl這幾個函數(shù)。隨著內(nèi)核版本的不斷改進(jìn),file_operations結(jié)構(gòu)體的規(guī)模也越來越大,它的定義如下所示:struct file_operations /指向擁有該結(jié)構(gòu)的模塊的指針,一般初始化為THIS_MODULE struct module *owner; /用來改變文件中的當(dāng)前讀/寫位置 loff_t (*llseek) (struct file *, loff_t, int); /用來從

8、設(shè)備中讀取數(shù)據(jù) ssize_t (*read) (struct file *, char _user *, size_t, loff_t *); /用來向設(shè)備寫入數(shù)據(jù) ssize_t (*write) (struct file *, const char _user *, size_t, loff_t *); /初始化一個異步讀取操作 ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); /初始化一個異步寫入操作 ssize_t (*aio_write) (struct kiocb

9、*, const struct iovec *, unsigned long, loff_t); /用來讀取目錄,對于設(shè)備文件,該成員應(yīng)當(dāng)為NULL int (*readdir) (struct file *, void *, filldir_t); /輪詢函數(shù),查詢對一個或多個文件描述符的讀或?qū)懯欠駮枞?unsigned int (*poll) (struct file *, struct poll_table_struct *); /用來執(zhí)行設(shè)備I/O操作命令 int (*ioctl) (struct inode *, struct file *, unsigned int, unsig

10、ned long); /不使用BKL文件系統(tǒng),將使用此函數(shù)代替ioctl long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); /在64位系統(tǒng)上,使用32位的ioctl調(diào)用將使用此函數(shù)代替long (*compat_ioctl) (struct file *, unsigned int, unsigned long);/用來將設(shè)備內(nèi)存映射到進(jìn)程的地址空間int (*mmap) (struct file *, struct vm_area_struct *);/用來打開設(shè)備int (*open) (struct

11、inode *, struct file *);/執(zhí)行并等待設(shè)備的任何未完成的操作int (*flush) (struct file *, fl_owner_t id);/用來關(guān)閉設(shè)備int (*release) (struct inode *, struct file *);/用來刷新待處理的數(shù)據(jù)int (*fsync) (struct file *, struct dentry *, int datasync);/fsync的異步版本int (*aio_fsync) (struct kiocb *, int datasync);/通知設(shè)備FASYNC標(biāo)志的改變int (*fasync) (

12、int, struct file *, int);/用來實(shí)現(xiàn)文件加鎖,通常設(shè)備文件不需要實(shí)現(xiàn)此函數(shù)int (*lock) (struct file *, int, struct file_lock *);file_operations主要的函數(shù) llseek()函數(shù)用于改變文件中的讀寫位置,并將新位置返回。 open()函數(shù)負(fù)責(zé)打開設(shè)備和初始化I/O。 release()函數(shù)負(fù)責(zé)釋放設(shè)備占用的內(nèi)存并關(guān)閉設(shè)備。 read()函數(shù)用來從設(shè)備中讀取數(shù)據(jù)。 write()函數(shù)用來向設(shè)備上寫入數(shù)據(jù)。 ioctl()函數(shù)實(shí)現(xiàn)對設(shè)備的控制。 mmap()函數(shù)將設(shè)備內(nèi)存映射到進(jìn)程的地址空間。若 aio_rea

13、d()和aio_write()函數(shù)分別實(shí)現(xiàn)對設(shè)備進(jìn)程異步的讀寫操作。fileLinux中的所有設(shè)備都是文件,在內(nèi)核中使用file結(jié)構(gòu)體來表示一個打開的文件。file結(jié)構(gòu)體中的重要成員 fmode_t f_mode loff_t f_pos unsigned int f_flags const struct file_operations *f_op void *private_datainodeinode結(jié)構(gòu)體是一個內(nèi)核文件系統(tǒng)索引節(jié)點(diǎn)對象,它包含了內(nèi)核在操作文件或目錄時所需要的全部信息。在內(nèi)核中inode結(jié)構(gòu)體用來表示文件,它與表示打開文件的file結(jié)構(gòu)體的區(qū)別是,同個文件可能會有多個打開文

14、件,因此一個inode結(jié)構(gòu)體可能會對應(yīng)著多個file結(jié)構(gòu)體。inode對于字符設(shè)備驅(qū)動來說,需要關(guān)心的是如何從inode結(jié)構(gòu)體中獲取設(shè)備號。與此相關(guān)的兩個成員分別是: dev_t i_rdev 對于設(shè)備文件而言,此成員包含實(shí)際的設(shè)備號。 struct cdev *i_cdev 字符設(shè)備在內(nèi)核中是用cdev結(jié)構(gòu)來表示的。此成員是指向cdev結(jié)構(gòu)的指針。inode內(nèi)核開發(fā)者提供了兩個函數(shù)來從inode對象中獲取設(shè)備號,它們的定義如下:static inline unsigned iminor(const struct inode *inode) return MINOR(inode-i_rdev)

15、;static inline unsigned imajor(const struct inode *inode) return MAJOR(inode-i_rdev); 字符字符設(shè)備注冊和注銷設(shè)備注冊和注銷字符設(shè)備初始化 void cdev_init(struct cdev *, const struct file_operations *);字符設(shè)備注冊 struct cdev *cdev_alloc(void);字符設(shè)備添加 void cdev_add(struct cdev *, dev_t, unsigned);字符設(shè)備刪除 void cdev_del(struct cdev *);

16、方法一:struct cdev *my_cdev = cdev_alloc();my_cdev-owner = THIS_MODULE;my_cdev-ops = &fops;方法二:struct cdev my_cdev;cdev_init(&my_cdev, &fops);my_cdev.owner = THIS_MODULE;3、GPIO概述概述GPIO接口利用工業(yè)標(biāo)準(zhǔn)I22C、SMBus或SPI接口簡化了I/O接口的擴(kuò)展。當(dāng)微控制器或芯片組沒有足夠的I/O端口,或當(dāng)系統(tǒng)需要使用遠(yuǎn)程串行通信或控制時,GPIO接口能夠提供額外的控制和監(jiān)視功能。GPIO接口一般至少會有兩個寄存器,即控制寄存

17、器和數(shù)據(jù)寄存器。數(shù)據(jù)寄存器的各位都直接引到芯片外部,而針對該寄存器的每一位的功能,則可以通過控制寄存器中相應(yīng)的位來設(shè)置。GPIO接口的優(yōu)點(diǎn)是低功耗、小封裝、低成本、較好的靈活性。14、串行串行總線概述總線概述目前流行的通信一般采用串行或并行模式,而串行模式應(yīng)用更廣泛。目前,大多數(shù)微控制器都提供SPI 和I2C接口,用于發(fā)送、接收數(shù)據(jù)。微處理器通過幾條總線控制周邊的設(shè)備。串行相比于并行的主要優(yōu)點(diǎn)是要求的線數(shù)較少,通常只需要使用2條、3條或4條數(shù)據(jù)/時鐘總線連續(xù)傳輸數(shù)據(jù)。SPI總線總線同步外設(shè)接口(Serial Peripheral Interface,SPI)是由摩托羅拉公司推出的一種高速的、全

18、雙工、同步的串行總線。它主要應(yīng)用在EEPROM、Flash、實(shí)時時鐘、AD轉(zhuǎn)換器以及數(shù)字信號處理器和數(shù)字信號解碼器之間。SPI 的工作模式有兩種:主模式和從模式,無論那種模式,都支持3Mbit/s的速率,并且還具有傳輸完成標(biāo)志和寫沖突保護(hù)標(biāo)志。I2C總線總線部集成電路(Internal Integrated Circuit),通常也被稱為I22C或者IIC,這種總線主要用于連接微控制器和外圍設(shè)備。它是由Philips公司開發(fā)的二線式串行總線標(biāo)準(zhǔn),最初被應(yīng)用于音頻和視頻領(lǐng)域的設(shè)備開發(fā),現(xiàn)今已在各種電子設(shè)備中得到了廣泛的使用。I2C總線最主要的特點(diǎn)是它的簡單性和高效性。SMBus總線總線系統(tǒng)管理總

19、線(System Management Bus,SMBus)最初由Intel提出,應(yīng)用于移動PC和桌面PC系統(tǒng)中的低速通訊。SMBus總線同I2C總線一樣也是一種二線式串行總線,它使用一條數(shù)據(jù)線和一條時鐘線進(jìn)行通信。雖然SMBus的數(shù)據(jù)傳輸率較慢,只有大約100kbit/s,卻以其結(jié)構(gòu)簡單、造價低的特點(diǎn),受到業(yè)界的普遍歡迎。5、I2C總線驅(qū)動總線驅(qū)動開發(fā)開發(fā)I2C驅(qū)動架構(gòu)驅(qū)動架構(gòu) Linux下的I2C驅(qū)動架構(gòu)有相當(dāng)?shù)膹?fù)雜度,主要由I2C核心、I2C總線驅(qū)動以及I2C設(shè)備驅(qū)動三個部分組成。I2C核心 主要提供了以下幾個功能:I2C總線驅(qū)動和設(shè)備驅(qū)動的注冊及注銷函數(shù),I2C algorithm的上

20、層代碼實(shí)現(xiàn),探測設(shè)備、檢測設(shè)備地址的上層代碼實(shí)現(xiàn)。I2C總線驅(qū)動 I2C總線驅(qū)動是對I2C硬件架構(gòu)中適配器的具體實(shí)現(xiàn)。 I2C總線驅(qū)動負(fù)責(zé)實(shí)現(xiàn)I2C適配器數(shù)據(jù)結(jié)構(gòu)(i2c_adapter)、I2C適配器的algorithm數(shù)據(jù)結(jié)構(gòu)(i2c_algorithm)以及控制適配器產(chǎn)生通信信號的函數(shù)。I2C設(shè)備驅(qū)動 I2C設(shè)備驅(qū)動是對I2C硬件架構(gòu)中設(shè)備的具體實(shí)現(xiàn)。 I2C設(shè)備驅(qū)動負(fù)責(zé)實(shí)現(xiàn)i2c_driver和i2c_client兩個數(shù)據(jù)結(jié)構(gòu)。關(guān)鍵數(shù)據(jù)結(jié)構(gòu)關(guān)鍵數(shù)據(jù)結(jié)構(gòu)i2c_adapter是對硬件上的適配器的抽象,相當(dāng)于整個I2C驅(qū)動的控制器,它的作用是產(chǎn)生總線時序,例如開始位、停止位、讀寫周期等,用

21、以讀寫I2C從設(shè)備。I2c_adapter結(jié)構(gòu)體定義如下:struct i2c_adapter struct module *owner; /*所屬模塊*/unsigned int id;unsigned int class; /*用來允許探測的類*/const struct i2c_algorithm *algo; /*I22C algorithm結(jié)構(gòu)體指針*/void *algo_data; /*algorithm所需數(shù)據(jù)*/ /*client注冊和注銷時調(diào)用*/int (*client_register)(struct i2c_client *) _deprecated;int (*cl

22、ient_unregister)(struct i2c_client *) _deprecated;int timeout;/*超時限制*/int retries; /*重試次數(shù)*/struct device dev;/*適配器設(shè)備*/int nr;struct list_head clients;/* client鏈表頭*/char name48; /*適配器名稱*/struct completion dev_released;i2c_alogorithm是提供控制適配器產(chǎn)生總線時序的函數(shù)。i2c_algorithm結(jié)構(gòu)體定義如下:struct i2c_algorithm /I22C傳輸函數(shù)

23、指針 int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); /SMBus傳輸函數(shù)指針 int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data); /確定適配器所支持的功能 u32 (*functionality) (struct i2c_adapter *);與適配器對

24、應(yīng)的是從設(shè)備,表示它的數(shù)據(jù)結(jié)構(gòu)為i2c_client。每個I2C設(shè)備都需要一個i2c_client來描述。該結(jié)構(gòu)體的定義如下:struct i2c_client unsigned short flags; /*標(biāo)志*/ unsigned short addr; /*芯片地址,注意:7位地址存儲在低7位*/ char nameI2C_NAME_SIZE; /*設(shè)備名字*/ struct i2c_adapter *adapter; /*依附的i2c_adapter指針*/ struct i2c_driver *driver; /*依附的i2c_driver指針*/ struct device de

25、v; /*設(shè)備結(jié)構(gòu)體*/ int irq; struct list_head list; /*鏈表頭*/ struct list_head detected; struct completion released; /*用于同步*/;i2c_driver并不是任何真實(shí)物理設(shè)備的對應(yīng),它只是一套驅(qū)動函數(shù)。在I2C驅(qū)動架構(gòu)中的設(shè)備驅(qū)動部分,i2c_driver是輔助類型的數(shù)據(jù)結(jié)構(gòu)。它的定義如下所示:struct i2c_driver int id; /*唯一的驅(qū)動id*/ unsigned int class; /*適配器添加函數(shù)(舊式)*/ int (*attach_adapter)(struc

26、t i2c_adapter *); /*適配器刪除函數(shù)(舊式)*/ int (*detach_adapter)(struct i2c_adapter *); /*設(shè)備刪除函數(shù)(舊式)*/ int (*detach_client)(struct i2c_client *) _deprecated; /*設(shè)備添加函數(shù)(新式)*/ int (*probe)(struct i2c_client *, const struct i2c_device_id *); /*設(shè)備刪除函數(shù)(新式)*/ int (*remove)(struct i2c_client *); void (*shutdown)(str

27、uct i2c_client *); /*設(shè)備關(guān)閉函數(shù)*/ /*設(shè)備掛起函數(shù)*/ int (*suspend)(struct i2c_client *, pm_message_t mesg); int (*resume)(struct i2c_client *); /*設(shè)備恢復(fù)函數(shù)*/ int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); /*類似ioctl*/ struct device_driver driver; /*設(shè)備驅(qū)動結(jié)構(gòu)體*/ /*此驅(qū)動支持的I22C設(shè)備列表*/ const struct

28、 i2c_device_id *id_table; /*檢測函數(shù)*/ int (*detect)(struct i2c_client *, int kind, struct i2c_board_info *); const struct i2c_client_address_data *address_data; struct list_head clients; /*鏈表頭*/;I2C核心核心I2C Core用于維護(hù)Linux的I2C核心部分,它主要提供了一套接口函數(shù),允許一個I2C adapter、I2C driver和I2C client在初始化時在I2C Core中進(jìn)行注冊,以及在退出

29、時進(jìn)行注銷。這些接口函數(shù)都是與具體硬件平臺無關(guān)的函數(shù),它們在drivers/i2c-core.c文件中定義,在linux/ic.h文件中聲明。i2c_adapter的注冊和注銷 int i2c_add_adapter(struct i2c_adapter *adapter); int i2c_del_adapter(struct i2c_adapter *adapter)i2c_driver的注冊和注銷 int i2c_register_driver(struct module *owner, struct i2c_driver *driver); void i2c_del_driver(str

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論