Linux驱动混杂设备模型详解与程序实例

2019-07-12 14:32发布

一,混杂设备的定义   在Linux中,存在这么一类字符设备,他们拥有相同的主设备号为10,但次设备号不同,这类设备就称为混杂设备(miscdevice).所有的混杂设备形成一个链表,对设备访问时内核根据次设备号查找到相应的混杂设备。
  混杂设备定义头文件 二,描述混杂设备的结构体   在这个结构体中我们只关心以下几个变量的初始化。 struct miscdevice { int minor; //次设备号 const char *name; //设备名 const struct file_operations *fops; //文件操作 struct list_head list; struct device *parent; struct device *this_device; const char *nodename; mode_t mode; };三,混杂设备的注册与注销   注册:int misc_register(struct miscdevice *misc)   释放:int misc_deregister(struct miscdevice *misc)
四,驱动调用的实质
  通过 设备文件找到与之对应设备号的设备,再通过设备初始化时绑定的操作函数对硬件进行控制的。 五,实例分析   下面这个例子是运行在tiny6410上的按键驱动程序。 //混杂设备驱动模型 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEVICE_NAME "keys" //定义设备名称 #define MISC_DYNAMIC_MINOR 200 //主设备号 #define GPNCON 0x7F008830 //中断函数 static irqreturn_t buttons_interrupt(int irq, void *dev_id) { //1检测设备中是否发生了中断 //2清楚中断产生的标准 //3相应的硬件操作——————在这里就是打印出那个按键被按下 printk(KERN_EMERG "key dowm "); //打印 return 0; } //初始化函数 static int s3c64xx_buttons_open(struct inode *inode, struct file *file) { //一般选择open()函数中完成按键的初始化 //但在这里单独定义一个函数进行初始化 return 0; } //按键初始化函数 static int int_key() { //初始化按键对应的GPIO引脚为中断功能 //K1 对应着 GPN0 对应的中断时EINT0 unsigned int *gpio_config; unsigned short data; gpio_config=ioremap(GPNCON,4); //物理地址转换为虚拟地址 data=readw(gpio_config); //readw()读取寄存器原来的值 data &= ~0b11; data |= 0b10; //把GPN0设置为10 writew(data,gpio_config); //将data数值写入寄存器 printk(KERN_EMERG "function init "); return 0; } //操作函数集 static struct file_operations dev_fops = { .owner = THIS_MODULE, .open = s3c64xx_buttons_open, }; static struct miscdevice misc = { //在Linux中使用struct miscdevice这个结构来描述混杂设备 .minor = MISC_DYNAMIC_MINOR, //次设备号 .name = DEVICE_NAME, //设备名,使用宏定义来定义设备名 .fops = &dev_fops, //file_operation操作函数集 }; static int __init dev_init() //注册混杂设备 { int ret; ret = misc_register(&misc); request_irq(IRQ_EINT(0),buttons_interrupt,IRQF_TRIGGER_FALLING,"key",0); //注册中断函数 //注册中断函数有五个参数,中断号(与硬件相关),中断处理函数,与中断有关的各种选项 int_key(); //初始化按键函数 //设备名,共享中断时使用 //设置为下降沿触发中断 IRQF_TRIGGER_FALLING printk (DEVICE_NAME" initialized "); return ret; } static void __exit dev_exit() //注销混杂设备 { misc_deregister(&misc); } module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); //表明遵循GPL协议 MODULE_AUTHOR("FriendlyARM Inc.");