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.");
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮