mini6410是我LED驱动程序

来源:互联网 发布:淘宝精仿浪琴手表 编辑:程序博客网 时间:2024/06/07 20:13

首先 是一些 写驱动需要包含的头文件

<pre name="code" class="cpp">#include<linux/init.h>     //module_init exit#include<linux/module.h>   //MODULE_LISENCE AUTHOR#include<linux/fs.h>       //file_operations#include<linux/mm.h>#include<linux/slab.h>#include<linux/errno.h>#include<linux/ioctl.h>     //ioctl#include<linux/cdev.h>#include<asm/io.h>#include<mach/map.h>#include<mach/regs-clock.h>#include<mach/regs-gpio.h>#include<mach/gpio-bank-k.h>




a、用字符设备写LED的驱动

struct cdev { struct kobject kobj; /* 内嵌的 kobject 对象 */ struct module *owner; /*所属模块*/ struct file_operations *ops; /*文件操作结构体*/ struct list_head list; dev_t dev; /*设备号*/ unsigned int count; };

步骤:
0、定义cdev结构体

定义cdev 时,可以静态定义或者动态分配

动态分配用 cdev_alloc()

struct cdev *cdev_alloc(void)


1、分配设备号

设备号可以动态分配,也可以静态指定

当静态分配时,使用函数 register_chrdev_region

int register_chrdev_region(dev_t from, unsigned count, const char *name) ;

当动态分配时,使用函数 alloc_chrdev_region

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,  const char *name) ;


2、cdev_init

void cdev_init(struct cdev *, struct file_operations *);
cdev_init 用于连接cdev和fops的关系

fops 结构体中包含操作设备的 open write read ioctl release 等函数

3、cdev_add

int cdev_add(struct cdev *, dev_t, unsigned);

cdev_add用于关联cdev和dev_no


4、收尾工作

动态分配cdev的注销 

void cdev_del(struct cdev *);

动态分配设备号的注销

void unregister_chrdev_region(dev_t from, unsigned count) ;


模块卸载函数中对cdev的卸载

void cdev_del(struct cdev *);

相反地,在调用 cdev_del()函数从系统注销字符设备之后,unregister_chrdev_region()应该被调用以释放原先申请的设备号,这个函数的原型为:

void unregister_chrdev_region(dev_t from, unsigned count) ;



b、用miscdevice驱动写LED程序
miscdevice 本质上还是字符型设备,只是在其上增加了一层封装而已

<pre name="code" class="cpp">struct miscdevice {  int minor; const char *name; const struct file_operations *fops; struct list_head list; struct device *parent; struct device *this_device; };


1、定义miscdevice结构体
 struct miscdevice { int minor; const char *name; const struct file_operations *fops; struct list_head list; struct device *parent; struct device *this_device; };


2、用misc_register()注册
int misc_register(struct miscdevice * misc);


3、用misc_deregister()注销
int misc_deregister(struct miscdevice *misc);


用到的函数原型

<span style="font-size:18px;">对主次设备号的操作函数</span>
MAJOR(dev_t dev)MINOR(dev_t dev)MKDEV(int major, int minor)


file_operations 结构

struct file_operations { struct module *owner; /* 拥有该结构的模块的指针,一般为 THIS_MODULES */ loff_t( *llseek)(struct file *, loff_t, int); /* 用来修改文件当前的读写位置 */ ssize_t( *read)(struct file *, char _ _user *, size_t, loff_t*); /* 从设备中同步读取数据 */ ssize_t( *write)(struct file *, const char _ _user *, size_t, loff_t*); /* 向设备发送数据*/ ssize_t( *aio_read)(struct kiocb *, char _ _user *, size_t, loff_t); /* 初始化一个异步的读取操作*/ ssize_t( *aio_write)(struct kiocb *, const char _ _user *, size_t, loff_t); /* 初始化一个异步的写入操作*/ int( *readdir)(struct file *, void *, filldir_t); /* 仅用于读取目录,对于设备文件,该字段为 NULL */ unsigned int( *poll)(struct file *, struct poll_table_struct*); /* 轮询函数,判断目前是否可以进行非阻塞的读取或写入*/ int( *ioctl)(struct inode *, struct file *, unsigned int, unsigned long); /* 执行设备 I/O 控制命令*/ long( *unlocked_ioctl)(struct file *, unsigned int, unsigned long); /* 不使用 BLK 的文件系统,将使用此种函数指针代替 ioctl */ long( *compat_ioctl)(struct file *, unsigned int, unsigned long); /* 在 64 位系统上, 32 位的 ioctl 调用,将使用此函数指针代替*/ int( *mmap)(struct file *, struct vm_area_struct*); /* 用于请求将设备内存映射到进程地址空间*/ int( *open)(struct inode *, struct file*); /* 打开 */ int( *flush)(struct file*); int( *release)(struct inode *, struct file*); /* 关闭*/ int ( *fsync) (struct file *, struct dentry *, int datasync); /* 刷新待处理的数据*/ int( *aio_fsync)(struct kiocb *, int datasync); /* 异步 fsync */ int( *fasync)(int, struct file *, int); /* 通知设备 FASYNC 标志发生变化*/ int( *lock)(struct file *, int, struct file_lock*); ssize_t( *sendpage)(struct file *, struct page *, int, size_t, loff_t *, int); /* 通常为 NULL */ unsigned long( *get_unmapped_area)(struct file *,unsigned long, unsigned long, unsigned long, unsigned long); /* 在当前进程地址空间找到一个未映射的内存段 */ int( *check_flags)(int); /* 允许模块检查传递给 fcntl(F_SETEL...) 调用 的标志 */ int( *dir_notify)(struct file *filp, unsigned long arg); /* 对文件系统有效,驱动程序不必实现*/ int( *flock)(struct file *, int, struct file_lock*); ssize_t ( *splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); /* 由 VFS 调用,将管道数据粘接到文件 */ ssize_t ( *splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); /* 由 VFS 调用,将文件数据粘接到管道 */ int ( *setlease)(struct file *, long, struct file_lock **); };











0 0