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

一,混杂设备的定义

  在Linux中,存在这么一类字符设备,他们拥有相同的主设备号为10,但次设备号不同,这类设备就称为混杂设备(miscdevice).所有的混杂设备形成一个链表,对设备访问时内核根据次设备号查找到相应的混杂设备。

  混杂设备定义头文件<linux/miscdevice.h>中

二,描述混杂设备的结构体

  在这个结构体中我们只关心以下几个变量的初始化。

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 <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>

#include <mach/map.h>
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>

#include <plat/gpio-cfg.h>
#include <mach/gpio-bank-n.h>
#include <mach/gpio-bank-l.h>


#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\n");  //打印
    
    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\n");
	
	
    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"\tinitialized\n");    

    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.");

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值