led设备驱动(s3c_led.c)
s3c_led.c分析:http://blog.csdn.net/hurry_liu/article/details/8770206 1,注冊設(shè)備號
int register_chrdev_region(dev_t from, unsigned count, const char *name)
動態(tài)分配設(shè)備號
int?alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name) // 無法再安裝驅(qū)動前創(chuàng)建設(shè)備文件,因為安裝前沒有分配設(shè)備號;安裝驅(qū)動后,從/proc/devices中查詢設(shè)備號 釋放設(shè)備號 void unregister_chrdev_region(dev_t from, unsigned count) 2,重要的結(jié)構(gòu)體 <1>struct file? ??? ?<linux/fs.h> //系統(tǒng)中每個打開的文件在內(nèi)核空間都有一個關(guān)聯(lián)的struct file。打開文件時創(chuàng)建,關(guān)閉時創(chuàng)建 重要成員: loff_t f_pos //文件讀寫位置
struct file_operations *f_op void *private_data; <2>struct file_operations?? ? ? ? ? ?<linux/fs.h>
//操作函數(shù)指針的集合,每個指針表示用戶空間能對設(shè)備文件進行的操作(其中的各函數(shù)是最主要的工作)
重要成員: int (*open)(struct inode *, struct file *) ?//初始化設(shè)備和標(biāo)明次設(shè)備號 void (*release)(struct inode *,struct file *) //關(guān)閉設(shè)備 ssize_t (*read)(sruct file *flip, char __user?*buff, size_t count, loff_t *offp)? //從設(shè)備中讀取數(shù)據(jù)到用戶空間,offp文件當(dāng)前的訪問位置? //buff指向數(shù)據(jù)緩存,?是指向用戶空間,不能被內(nèi)核代碼直接引用 count傳輸?shù)臄?shù)據(jù)量 ?(這兩個參數(shù)由用戶空間提供) ssize_t (*write)(sruct file *, const?char __user *buff, size_t, loff_t *) ?//將數(shù)據(jù)傳遞給驅(qū)動程序 int (*ioctl)(struct inode *, srtuct file *, unsigned int, unsigned long) ? ?//控制設(shè)備 off_t (*llseek)(struct file *, loff_t, int) <3>struct inode結(jié)構(gòu) ??
//記錄文件的物理上的信息,一個文件只有一個inode結(jié)構(gòu)
重要成員: dev_t ?i_rdev; ? ?//設(shè)備號(對于表示設(shè)備文件的inode) struct ?*cdev *i_cdev; ? ?//當(dāng)inode指向字符設(shè)備文件時
可以從inode中獲取主次設(shè)備號
MAJOR(dev_t dev)
MINOR(dev_t dev)
MKDEV(int major,int minor) ? //通過主次設(shè)備號來生成dev_t
?
<4>struct cdev結(jié)構(gòu) ? ? ? ? ? ? ? ? <linux/cdev.h> //內(nèi)核使用cdev結(jié)構(gòu)體描述字符設(shè)備 重要成員:
struct module *owner; ? ?//所屬模塊
const struct file_operations *ops; ?
dev_t dev;??????????//設(shè)備號
?
3,一些函數(shù)
<1>用來對cdev結(jié)構(gòu)操作的函數(shù):
void cdev_init(struct cdev *, const struct file_operations *);
//初始化,建立cdev和file_operation?之間的連接
struct cdev *cdev_alloc(void); //動態(tài)申請一個cdev內(nèi)存
void cdev_put(struct cdev *p); //釋放
int cdev_add(struct cdev *, dev_t, unsigned); //注冊設(shè)備,通常發(fā)生在驅(qū)動模塊的加載函數(shù)中
void cdev_del(struct cdev *);//注銷設(shè)備,通常發(fā)生在驅(qū)動模塊的卸載函數(shù)中
?
<2>內(nèi)核提供專門的函數(shù)用于訪問用戶空間的指針
int copy_from_user(void *to, const void __user *from,int n) ? write() int copt_to_user(void __user *to, const void *from, int n) ? ?read() <3>宏定義request_mem_region和ioremap ? ??include/linux/ioport.h request_mem_region(S3C_GPB_BASE, S3C_GPB_LEN,DEV_NAME)) /* 申請內(nèi)存。注意:這里的內(nèi)存是FL2440中實際的物理內(nèi)存,他對應(yīng)了與LED的相關(guān)的寄存器 占用起始物理地址S3C_GPB_BASE之后的連續(xù)S3C_GPB_LEN字節(jié)大小空間 該函數(shù)并沒有做實際性的映射工作,只是告訴內(nèi)核要使用一塊內(nèi)存地址,聲明占有,也方便內(nèi)核管理這些資源。*/ fl2440_gpb_membase=ioremap(S3C_GPB_BASE, S3C_GPB_LEN) ? ? ?ioremap()在mm/ioremap.c中定義,返回void型指針 //主要是檢查傳入地址的合法性,建立頁表(包括訪問權(quán)限),完成物理地址到虛擬地址的轉(zhuǎn)換。 release_mem_region(S3C_GPB_BASE, S3C_GPB_LEN) void iounmap(fl2440_gpb_membase); //一些宏定義 __raw_writel((val),(reg)+s3c_gpb_membase) __raw_readll((reg)+s3c_gpb_membase) ? //讀操作和寫操作寄存器 4,led字符設(shè)備 //字符設(shè)備用struct cdev來描述;struct cdev *led_cdev;
加載模塊int __init s3c_led_init(): <1>硬件初始化:s3c_hw_init(): 申請內(nèi)存request_mem_region()-->?建立物理內(nèi)存到虛擬內(nèi)存的映射ioremap()-->初始化硬件設(shè)備 <2>申請設(shè)備號: <3>為cdev分配內(nèi)存(定義為指針式需要) led_cdev = cdev_alloc(); //可以將cdev結(jié)構(gòu)嵌入到自己的設(shè)備特定結(jié)構(gòu)中 <4>初始化cdev ? led_cdev->owner = THIS_MODULE; cdev_init(led_cdev, &led_fops); ? ?//將led_cdev和file_operations掛鉤 <5>,添加cdev ? ? result = cdev_add(led_dev, devno, dev_count);? //將設(shè)備號和設(shè)備掛鉤 ? devno是設(shè)備號 //在驅(qū)動程序準(zhǔn)備好處理設(shè)備上的操作時,調(diào)用該函數(shù) <6>出錯處理[函數(shù)] 卸載模塊s3c_led_exit(): <1>調(diào)用s3c_hw_term() ?: 關(guān)閉led-->釋放內(nèi)存release_mem_region()-->解除映射關(guān)系iounmap() <2>注銷設(shè)備:cdev_del() <3>釋放設(shè)備號:unregister_chrdev_region() 設(shè)備操作的實現(xiàn) 定義struct file_operations led_fops = { .owner = THIS_MODULE; .open = led_open; .release = led_release; .unlocked_ioctl = led_ioctl;
}; 三,arm開發(fā)板上 tftp -gr s3c_hello.ko 192.168.1.3 insmod,rmmod ? ? ?//加載和卸載模塊命令(root權(quán)限) lsmod ? ? //列舉內(nèi)核模塊及引用計數(shù) ?cat /proc/modules insmod s3c_led.ko cat /proc/drivers cd dev/? mknod -m666 c led0 ?252 0 mknod -m666 c led1 ?252 1 mknod -m666 c led2 ?252 2 mknod -m666 c led3 ?252 3 ./test_led /dev/led0 1 ? ? //點亮第一個燈
轉(zhuǎn)載于:https://www.cnblogs.com/zhoutian220/p/3965100.html
總結(jié)
以上是生活随笔為你收集整理的led设备驱动(s3c_led.c)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Java基础]接口基础
- 下一篇: 腾讯游戏《妖精的尾巴 力量觉醒》宣布将于