linux雜項(xiàng)設(shè)備驅(qū)動(dòng)模型_第1頁(yè)
linux雜項(xiàng)設(shè)備驅(qū)動(dòng)模型_第2頁(yè)
linux雜項(xiàng)設(shè)備驅(qū)動(dòng)模型_第3頁(yè)
linux雜項(xiàng)設(shè)備驅(qū)動(dòng)模型_第4頁(yè)
linux雜項(xiàng)設(shè)備驅(qū)動(dòng)模型_第5頁(yè)
已閱讀5頁(yè),還剩3頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、Linux驅(qū)動(dòng)中把無(wú)法歸類的五花八門的設(shè)備定義為混雜設(shè)備(用miscdevice結(jié)構(gòu)體表述)。miscdevice共享一個(gè)主設(shè)備號(hào)MISC_MAJOR(即10),但次設(shè)備號(hào)不同。所有的miscdevice設(shè)備形成了一個(gè)鏈表,對(duì)設(shè)備訪問時(shí)內(nèi)核根據(jù)次設(shè)備號(hào)查找對(duì)應(yīng)的miscdevice設(shè)備,然后調(diào)用其file_operations結(jié)構(gòu)中注冊(cè)的文件操作接口進(jìn)行操作。在內(nèi)核中用structmiscdevice表示miscdevice設(shè)備,然后調(diào)用其file_operations結(jié)構(gòu)中注冊(cè)的文件操作接口進(jìn)行操作。miscdevice的API實(shí)現(xiàn)在drivers/char/misc.c中?;祀s項(xiàng)設(shè)備驅(qū)動(dòng)的

2、程序組織架構(gòu):新建一個(gè)first_led.c,先可能用到的頭文件都引用上吧!#include #include /驅(qū)動(dòng)模塊必需要加的個(gè)頭文件#include #include #include #include #include #include #include #include ./對(duì)應(yīng)著相應(yīng)機(jī)器平臺(tái)的頭文件#include #include #include /給自己設(shè)備驅(qū)動(dòng)定義一個(gè)名字#define DEVICE_NAME First_led名字有了,但樣子是怎樣的呢?現(xiàn)在就開始定義一個(gè)“樣子”!如果一個(gè)字符設(shè)備驅(qū)動(dòng)要驅(qū)動(dòng)多個(gè)設(shè)備,那么它就不應(yīng)該用misc設(shè)備來(lái)實(shí)現(xiàn)。通常情況下,一個(gè)字

3、符設(shè)備都不得不在初始化的過(guò)程中進(jìn)行下面的步驟:通過(guò)alloc_chrdev_region()分配主次設(shè)備號(hào)。使用cdev_init()和cdev_add()來(lái)以一個(gè)字符設(shè)備注冊(cè)自己。而一個(gè)misc驅(qū)動(dòng),則可以只用一個(gè)調(diào)用misc_register()來(lái)完成這所有的步驟。(所以miscdevice是一種特殊的chrdev字符設(shè)備驅(qū)動(dòng))所有的miscdevice設(shè)備形成一個(gè)鏈表,對(duì)設(shè)備訪問時(shí),內(nèi)核根據(jù)次設(shè)備號(hào)查找對(duì)應(yīng)的miscdevice設(shè)備,然后調(diào)用其file_operations中注冊(cè)的文件操作方法進(jìn)行操作。在Linux內(nèi)核中,使用structmiscdevice來(lái)表示miscdevice。這

4、個(gè)結(jié)構(gòu)體的定義為:structmiscdeviceintminor;constchar*name;conststructfile_operations*fops;structlist_headlist;structdevice*parent;structdevice*this_device;constchar*nodename;mode_tmode;minor是這個(gè)混雜設(shè)備的次設(shè)備號(hào),若由系統(tǒng)自動(dòng)配置,則可以設(shè)置為MISC_DYNANIC_MINOR,name是設(shè)備名為了容易理解,我們先打大概的“樣子”做好。只做minor、name、fops;定義一個(gè)myfirst_led_dev設(shè)備:sta

5、tic struct miscdevice myfirst_led_dev = .minor= MISC_DYNAMIC_MINOR,.name= DEVICE_NAME,.fops= &myfirst_led_dev_fops,;Minorname都已經(jīng)定義好了。那么接下來(lái)實(shí)現(xiàn)一下myfirst_led_dev_fops方法。內(nèi)核中關(guān)于file_operations的結(jié)構(gòu)體如下:structfile_operationsstructmodule*owner;loff_t(*llseek)(structfile*,loff_t,int);ssize_t(*read)(structfile*,c

6、har_user*,size_t,loff_t*);ssize_t(*write)(structfile*,constchar_user*,size_t,loff_t*);ssize_t(*aio_read)(structkiocb*,conststructiovec*,unsignedlong,loff_t);ssize_t(*aio_write)(structkiocb*,conststructiovec*,unsignedlong,loff_t);int(*readdir)(structfile*,void*,filldir_t);unsignedint(*poll)(structfil

7、e*,structpoll_table_struct*);long(*unlocked_ioctl)(structfile*,unsignedint,unsignedlong);long(*compat_ioctl)(structfile*,unsignedint,unsignedlong);int(*mmap)(structfile*,structvm_area_struct*);int(*open)(structinode*,structfile*);int(*flush)(structfile*,fl_owner_tid);int(*release)(structinode*,struc

8、tfile*);int(*fsync)(structfile*,intdatasync);int(*aio_fsync)(structkiocb*,intdatasync);int(*fasync)(int,structfile*,int);int(*lock)(structfile*,int,structfile_lock*);ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);unsignedlong(*get_unmapped_area)(structfile*,unsignedlong,unsignedl

9、ong,unsignedlong,unsignedlong);int(*check_flags)(int);int(*flock)(structfile*,int,structfile_lock*);ssize_t(*splice_write)(structpipe_inode_info*,structfile*,loff_t*,size_t,unsignedint);ssize_t(*splice_read)(structfile*,loff_t*,structpipe_inode_info*,size_t,unsignedint);int(*setlease)(structfile*,lo

10、ng,structfile_lock*);long(*fallocate)(structfile*file,intmode,loff_toffset,loff_tlen);對(duì)于LED的操作,只需要簡(jiǎn)單實(shí)現(xiàn)io操作就可以了,所以只實(shí)現(xiàn)long(*unlocked_ioctl)(structfile*,unsignedint,unsignedlong);(該函數(shù)是在linux2.6.5以后才出現(xiàn)在設(shè)備的操作方法中的。)函數(shù)參數(shù)為文件節(jié)點(diǎn)、命令、參數(shù)static struct file_operations myfirst_led_dev_fops = .owner= THIS_MODULE,.un

11、locked_ioctl= myfirst_led_ioctl,;到了這里,就考慮一下LED的物理層面是怎樣的實(shí)現(xiàn)了,通過(guò)開發(fā)板的引腳我們可以知道,四個(gè)LED是分別接到了GPJ2的03號(hào)管腳上。因此,我們定義一個(gè)數(shù)組來(lái)引用這幾個(gè)管腳(當(dāng)然不能像祼機(jī)那樣對(duì)IO的物理地址進(jìn)行操作了,是需要經(jīng)過(guò)內(nèi)核的內(nèi)存映射得來(lái)的IO內(nèi)存操作!而內(nèi)核把ARM的IO管腳地址按一個(gè)線性地址進(jìn)行了編排)static int led_gpios = S5PV210_GPJ2(0),S5PV210_GPJ2(1),S5PV210_GPJ2(2),S5PV210_GPJ2(3),;#define LED_NUMARRAY_SI

12、ZE(led_gpios)/判斷l(xiāng)ed_gpio有多少個(gè)S5PV210_GPJ2(*)的定義如下#defineS5PV210_GPJ2(_nr) (S5PV210_GPIO_J2_START+(_nr)enums5p_gpio_numberS5PV210_GPIO_A0_START =0,.S5PV210_GPIO_J2_START =S5PV210_GPIO_NEXT(S5PV210_GPIO_J1),. #defineS5PV210_GPIO_NEXT(_gpio)(_gpio#_START)+(_gpio#_NR)+CONFIG_S3C_GPIO_SPACE+1)給用戶空間的接口操作:s

13、tatic long myfirst_led_ioctl(struct file *filp, unsigned int cmd,unsigned long arg)switch(cmd) case 0:case 1:if (arg LED_NUM) return -EINVAL;/判讀用戶的參數(shù)是否有誤gpio_set_value(led_gpiosarg, !cmd);/用戶選定的LED并設(shè)置值/printk(DEVICE_NAME: %d %dn, arg, cmd);break;default:return -EINVAL;return 0;對(duì)于gpio_set_value(unsig

14、nedintgpio,intvalue),內(nèi)核有以下定義:staticinlinevoidgpio_set_value(unsignedintgpio,intvalue)_gpio_set_value(gpio,value);void_gpio_set_value(unsignedgpio,intvalue)structgpio_chip *chip;chip=gpio_to_chip(gpio);WARN_ON(chip-can_sleep);trace_gpio_value(gpio,0,value);chip-set(chip,gpio-chip-base,value);到了這里,對(duì)于用

15、戶空間來(lái)說(shuō),已經(jīng)有了完整的操作方法接口,但對(duì)于內(nèi)核模塊來(lái)說(shuō),還缺少驅(qū)動(dòng)模塊的進(jìn)入與退出。以下接著寫驅(qū)動(dòng)模塊的初始化(即進(jìn)入)和退出。staticint_initmyfirst_led_dev_init(void);staticvoid_exitmyfirst_led_dev_exit(void);函數(shù)如上。雙下劃線表示模塊在內(nèi)核啟動(dòng)和關(guān)閉時(shí)自動(dòng)運(yùn)行和退出對(duì)于驅(qū)動(dòng)模塊的初始化函數(shù),要寫些什么呢?我們這樣考慮:對(duì)于用戶空間接口來(lái)說(shuō),我們的實(shí)現(xiàn)函數(shù)只是給出了IO的值設(shè)置的,但是ARM的IO管腳使用還是需要配置方向、上拉下拉.才能正常使用的,并且所有的硬件資源,都是受內(nèi)核所支配的,驅(qū)動(dòng)程序必需向內(nèi)核申

16、請(qǐng)硬件資源才能對(duì)硬件進(jìn)行操作。另外還需要對(duì)設(shè)備進(jìn)行注冊(cè),內(nèi)核才知道你這個(gè)設(shè)備是什么東東,用到哪些東西。這些操作,我們安排在init里實(shí)現(xiàn)!static int _init myfirst_led_dev_init(void) int ret;int i;for (i = 0; i LED_NUM; i+) ret = gpio_request(led_gpiosi, LED);/申請(qǐng)IO引腳if (ret) printk(%s: request GPIO %d for LED failed, ret = %dn, DEVICE_NAME,led_gpiosi, ret);return ret;

17、s3c_gpio_cfgpin(led_gpiosi, S3C_GPIO_OUTPUT);gpio_set_value(led_gpiosi, 1);ret = misc_register(&myfirst_led_dev);printk(DEVICE_NAMEtinitializedn);return ret;pio_request(unsignedgpio,constchar*label)gpio則為你要申請(qǐng)的哪一個(gè)管腳,label為其名字。ints3c_gpio_cfgpin(unsignedintpin,unsignedintconfig);對(duì)芯片進(jìn)行判斷,并設(shè)置引腳的方向。ret=misc_register(&myfirst_led_dev);.該函數(shù)中、內(nèi)核會(huì)自動(dòng)為你的設(shè)備創(chuàng)建一個(gè)設(shè)備節(jié)點(diǎn)對(duì)設(shè)備進(jìn)行注冊(cè)到這里,設(shè)備的初始化與注冊(cè)已經(jīng)完成!當(dāng)用戶不再需要該驅(qū)動(dòng)資源時(shí),我們必需在驅(qū)動(dòng)模塊中,對(duì)占用內(nèi)核的資源進(jìn)行主動(dòng)的釋放!因此在驅(qū)動(dòng)模塊退出時(shí),完成這些工作!static void _exit myfirst_led_dev_exit(void) int i;for (i = 0; i LED_NUM; i+) gp

溫馨提示

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

評(píng)論

0/150

提交評(píng)論