版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度養(yǎng)殖場(chǎng)廢棄物資源化利用技術(shù)承包合同范本4篇
- 2022版義務(wù)教育階段英語(yǔ)課程標(biāo)準(zhǔn)模擬測(cè)試卷
- 2025年度整棟醫(yī)療設(shè)施出租經(jīng)營(yíng)合同4篇
- 2025年度存量房交易資金監(jiān)管服務(wù)合同范本2篇
- 2024智能健康監(jiān)測(cè)設(shè)備研發(fā)與生產(chǎn)合同
- 2025別墅庭院園藝景觀植物租賃與養(yǎng)護(hù)合同3篇
- 2025年度新能源汽車動(dòng)力電池回收利用技術(shù)合作合同范本3篇
- 2024美容院?jiǎn)T工勞動(dòng)合同及保密協(xié)議
- 2025年度醫(yī)院兒科病房改造與承包運(yùn)營(yíng)協(xié)議4篇
- 2025年度床上用品行業(yè)環(huán)保公益活動(dòng)合作合同3篇
- 納米復(fù)合材料增強(qiáng)金屬基材
- 拆除豬場(chǎng)補(bǔ)償協(xié)議書模板
- 水利水電工程施工安全管理導(dǎo)則
- 5歲幼兒數(shù)學(xué)練習(xí)題
- 2024年高中生物新教材同步選擇性必修第三冊(cè)學(xué)習(xí)筆記第3章 本章知識(shí)網(wǎng)絡(luò)
- 2024年全國(guó)體育單招英語(yǔ)考卷和答案
- 食品安全管理制度可打印【7】
- 藥物流行病學(xué)教學(xué)大綱
- 健康管理師二級(jí)理論考核試題及答案
- 手術(shù)室常見消毒滅菌方法
- 2024年九年級(jí)語(yǔ)文中考名著閱讀《儒林外史》考前練附答案
評(píng)論
0/150
提交評(píng)論