版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、- 簡介Linux 下的 MISC 簡單字符設(shè)備驅(qū)動雖然使用簡單,但卻不靈活。只能建立主設(shè)備號為 10 的設(shè)備文件。 字符設(shè)備比較容易理解, 同時也能夠滿足大多數(shù)簡 單的硬件設(shè)備 , 字符設(shè)備通過文件系 統(tǒng)中的名字來讀取。這些名字就是文件系統(tǒng)中的特 殊文件或者稱為設(shè)備文件、 文件系統(tǒng)的簡單結(jié)點, 一般位于 /dev/ 目錄下 使用 ls 進(jìn)行查 看會顯示以 C 開頭證明這是字符設(shè)備文件crw-w 1 root tty 4, 0 4 月 14 11:05 tty0 。第一個數(shù)字是主設(shè)備 號,第二個數(shù)字是次設(shè)備號。- 分配和釋放設(shè)備編號1) 在 建 立 字 符 設(shè) 備 驅(qū) 動 時 首 先 要 獲
2、取 設(shè) 備 號 , 為 此 目 的 的 必 要 的 函 數(shù) 是 register_chrdev_region, 在 linux/fs.h 中 聲 明 : int register_chrdev_region(dev_t first, unsigned int count, char *name);first 是你想 要分配的起始設(shè)備編號, first 的次編號通 常是 0,count 是你請求的連續(xù)設(shè)備編號的 總數(shù)。 count 如果太大會溢出到下一個主設(shè)備號中。 name 是設(shè)備的名字,他會出 現(xiàn)在 /proc/devices 和 sysfs 中。操作成功返回 0,如果失敗會返回一個負(fù)的錯誤
3、碼。2) 如果明確知道設(shè)備號可用那么上一個方法可行,否則我們可以使用內(nèi)核動態(tài)分配的設(shè) 備號 int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,unsigned int count, char *name);dev 是個只輸出的參數(shù), firstminor 請求的第一個要用的次 編號, count和name的作用如上1)對于新驅(qū)動,最好的方法是進(jìn)行動態(tài)分配3) 釋放設(shè)備號, void unregister_chrdev_region(dev_t first unsigned int count);- 文件操作 file_ope
4、rations 結(jié)構(gòu)體, 內(nèi)部連接了多個設(shè)備具體操作函數(shù)。 該變量內(nèi)部 的函數(shù)指針指向驅(qū)動程序中的具體操作,沒有對應(yīng)動作的指針設(shè)置為NULL。1) fops的第一個成員是 struct module *owner 通常都是設(shè)置成 THIS_MODULElinux/module.h 中定義的宏。用來在他的操作還在被使用時阻止模塊被卸載。2) loff_t (*llseek) (struct file *, loff_t, int);該方法用以改變文件中的當(dāng)前讀 /寫位置該函數(shù)用返回新位置。3) ssize_t (*read) (struct file *, char _user *, size_
5、t, loff_t *);以從設(shè)備文件中讀取數(shù)據(jù),讀取成功返回讀取的字節(jié)數(shù)。4) ssize_t (*write) (struct file *, const char _user *,size_t , loff_t *); 該函數(shù)用以向設(shè)備寫入數(shù)據(jù),如果成功返回寫入的字節(jié)數(shù)。5) int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);ioctl 系統(tǒng)調(diào)用提供發(fā)出設(shè)備特定命令的方法。6) int (*open) (struct inode *, struct file *);設(shè)備文件進(jìn)行的第一個操作,
6、打開設(shè)備文件。7) int (*release) (struct inode * , struct file *); 釋放文件結(jié)構(gòu)函數(shù)指針。 一般初始化該結(jié)構(gòu)體如下:struct file_operations fops = .owner = THIS_MODULE, .llseek= xxx_llseek, .read = xxx_read, .writexxx_write,.ioctl = xxx_ioctl, .open = xxx_open, .release = xxx_release ;PS:以上的文件操作函數(shù)指針并不是全部,只是介紹了幾個常用的操作。- 文件結(jié)構(gòu)struct fi
7、le 定義在 linux/fs.h 中,是設(shè)備驅(qū)動中第二個最重要的數(shù)據(jù)結(jié)構(gòu), 此處的 file 和用戶空間程序中的 FILE 指針沒有關(guān)系。前者位于內(nèi)核空間,后者位于用戶控件。 文件結(jié)構(gòu)代表一個打開的文件。 (他不特定給設(shè)備驅(qū)動 ; 系統(tǒng)中每個打開的文件 有一個關(guān)聯(lián)的 struct file 在內(nèi)核空間 )。它由內(nèi)核在 open 時創(chuàng)建,并可以傳遞給文件 件操作函數(shù),文件關(guān)閉之后,內(nèi)核釋放數(shù)據(jù)結(jié)構(gòu)。1)mode_t f_mode 。確定文件讀寫模式2)loff_t f_ops 。當(dāng)前讀寫位置3)unsigned int f_flags。文件標(biāo)志, O_RDONL、Y O_NONBLOC,K4)
8、 struct file_operations *f_op 。關(guān)聯(lián)文件相關(guān)操作5) void *private_data。 open系統(tǒng)調(diào)用設(shè)置該指針NULL指向分配的數(shù)據(jù)。6) struct dentry *f_dentry。關(guān)聯(lián)到文件的目錄入口 dentry 結(jié)構(gòu)。-inode 結(jié)構(gòu)inode 結(jié)構(gòu)由內(nèi)核在內(nèi)部用來表示文件。它和代表打開文件描述符的文件結(jié)構(gòu)是不同的。 inode 結(jié)構(gòu)包含大量關(guān)于文件的信息。作為通用規(guī)則,這個結(jié)構(gòu)只有兩個成 員對驅(qū)動代碼有作用。dev_t i_rdev 。對于代表設(shè)備文件的節(jié)點,這個成員包含實際的設(shè)備編號。struct cdev *i_cdev 。內(nèi)核內(nèi)部結(jié)
9、構(gòu),代表字符設(shè)備。- 字符設(shè)備注冊在內(nèi)核調(diào)用你的設(shè)備操作前,你編寫分配并注冊一個或幾個struct cdev.struct cdev *my_cdev = cdev_alloc(); my_cdev-;ops = &my_fops;或者定義成 static 均可。對定義的 cdev 變量進(jìn)行初始化,可以使用專門的函數(shù),或者使用如上的方法。cdev_init( my_cdev, &my_fops); 其實上邊的兩行代碼就是做了這個函數(shù)的工作。最后告訴內(nèi)核該 cdev。cdev_add(struct cdev *dev, dev_t num, unsigned in
10、t count);/* 上述總結(jié),到此關(guān)于設(shè)備文件相關(guān)的結(jié)構(gòu)數(shù)據(jù)以及如何注冊銷毀等操作相關(guān)的 函數(shù)基本上都已經(jīng)介紹完畢。主要的還是要設(shè)計具體操作的函數(shù)來實現(xiàn)具體的 邏輯操作 */以下代碼整理、摘錄自 An droid深度探索HAL與驅(qū)動開發(fā)-李寧LED驅(qū)動篇#include#include#include#include#include#include#include#deifne DEVICE_NAME s3c6410_leds#define DEVICE_COUNT 1#define S3C6410_LEDS_MAJOR 0#define S3C6410_LEDS_MINOR 234#de
11、fine PARAM_SIZE 3static int major = S3C6410_LEDS_MAJOR;static int minor = S3C6410_LEDS_MINOR;static dev_t dev_number;static int leds_state = 1;static char *params = string1,string2,string3;static iint param_size = PARAM_SIZE;static struct class *leds_class = NULL;static int s3c6410_leds_ioctl (struc
12、t file *file, unsigned int cmd, unsigned long arg)switch (cmd)unsigned tmp;case 0:case 1:if (arg ; 4)return -EINVAL;tmp = ioread32 (S3C64XX_GPMDAT);if (cmd = 1)tmp &= (1 << arg);elsetmp |= (1 << arg);iowrite32 (tmp, S3C64XX_GPMDAT);return 0;default : return -EINVA
13、L;static ssize_t s3c6410_leds_write (struct file *file, const char _user *buf, size_t count, loff_t *ppos)unsigned tmp = count;unsigned long i = 0;memset(mem, 0, 4);if (count ; 4)tmp = 4;if (copy_from_user (mem, buf, tmp) )return -EFAULT;elsefor( i=0; i<4; i+)tmp = ioread32(S3C64XX_GPMDAT);if
14、 (memi = '1')tmp &= (1 << i);elsetmp |= (1 << i);iowrite32(tmp, S3C64XX_GPMDAT);return count;static struct file_operations dev_fops =.write.owner = THIS_MODULE, .unlocked_ioctl = s3c6410_leds_ioctl, s3c6410_leds_write;static struct cdev leds_cdev;static in
15、t leds_create_device(void)int ret = 0;int err = 0;cdev_init (&leds_cdev, &dev_fops);leds_cdev.owner = THIS_MODULE;if (major ; 0)dev_number = MKDEV(major,minor);err = register_chrdev_region(dev_number, DEVICE_COUNT, DEVICE_NAME);if (err < 0)printk(KERN_WANRING register_chrdev_r
16、egion errorn);return errelseerr = alloc_chrdev_region(&leds_cdev.dev, 10, DEVICE_COUNT, DEVICE_NAME); if(err < 0)printk (KERN_WARNING alloc_chrdev_region errorn);return err;major = MAJOR(leds_cdev.dev);major = MINOR(leds_cdev.dev);dev_number = leds_cdev.dev;ret = cdev_add(&led
17、s_cdev,dev_number, DEVICE_COUNT);leds_class = class_create (THIS_MODULE, DEVICE_NAME); device_create (leds_class, NULL, dev_number, NULL, DEVICE_NAME); return ret;static void leds_init_gpm(int leds_default)int tmp = 0;tmp = ioread32(S3C64XX_GPMCON);tmp &= (0xffff);tmp |= 0x1111;iowrite32(tmp
18、,S3C64XX_GPMCON);tmp = ioread32(S3C64XX_GPMPUD);tmp &= (0XFF);tmp |= 0xaa;iowrite32(tmp,S3C64XX_GPMPUD);tmp = ioread32(S3C64XX_GPMDAT);tmp &= (0xf);tmp |= leds_default;iowrite32(tmp, S3C64XX_GPMDAT);static leds_init( void)int ret;ret = leds_create_device();leds_init_gpm (leds_state);printk(DEVICE_NAMEtinitializedn);return ret;static void leds_destroy_device(void)device_destroy(leds_class, dev_number);if(leds_class)class_destroy(leds_class);unregister_chrdev_region(dev
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 貴州大學(xué)《機(jī)械制圖(二)》2023-2024學(xué)年第一學(xué)期期末試卷
- 貴陽學(xué)院《自動控制原理C》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025黑龍江省安全員-B證考試題庫附答案
- 2025年上海建筑安全員考試題庫附答案
- 硅湖職業(yè)技術(shù)學(xué)院《廣播電視深度報道實務(wù)》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025湖南建筑安全員B證考試題庫附答案
- 2025重慶市建筑安全員-B證(項目經(jīng)理)考試題庫
- 廣州幼兒師范高等專科學(xué)?!督ㄖ?、結(jié)構(gòu)識圖》2023-2024學(xué)年第一學(xué)期期末試卷
- 廣州新華學(xué)院《數(shù)字化模具設(shè)計》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025重慶市安全員考試題庫
- 非急救轉(zhuǎn)運(yùn)管理制度
- 第18課《天下第一樓(節(jié)選)》 統(tǒng)編版語文九年級下冊
- 活動策劃部培訓(xùn)課件
- 江蘇省鹽城市2022-2023學(xué)年八年級上學(xué)期期末歷史試題
- 稻草購銷合同模板
- 執(zhí)法中隊競聘演講稿
- 國有企業(yè)員工守則
- CSR社會責(zé)任管理手冊模板
- 毛澤東軍事思想概述(新)
- 錨桿框格梁施工技術(shù)交底
- 商戶清場協(xié)議書
評論
0/150
提交評論