码迷,mamicode.com
首页 > 其他好文 > 详细

内核中断及按键驱动程序

时间:2015-02-05 13:25:18      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:

寒假Linux学习笔记

2015年1月25日 晚 20:00

一、内核中断处理

进程上下文:应用程序主动调用内核驱动的程序的跳转

中断上下文:中断由硬件产生的,与应用程序无关

?

?

1、注册中断

Int request_irq(unsigned int irq, ????????????//中断号

void (*handler)(int ,void *, struct pt_regs*),????//中断处理函数

unsigned long flags,????????????//与中断处理管理相关的各种选项

const char * devname,????????//设备名

void * dev_id????????????????//共享中断时使用的id号,唯一

);

Flags参数:

????IRQF_DISABLED(SA_INTERRUPT);????//若设置此位,则是一个快速中断,即中断为原子操作,不会被打断;未设置该位,则是一个慢速中断

????IRQF_SHARED(SA_SHIRQ);????????//中断可以在设备间共享,申请共享中断必须设置此位为IRQF_SHARED

?

注意:共享中断 不能使用 disable_irq(unsigned int irq),因为一旦使用该函数,则共享该中断线的全部都不能用

?

2、中断处理函数流程

Void short_sh_interrupt(int irq, void *dev_id, struct pt_regs *regs)

{

????/*判断是否是本设备的中断,因为共享中断中使用的是同一个中断处理函数,此时内核就无法判断是哪一个设备发生的中断,可能产生误调用*/

????Value = inb(short_base);

If(!value & 0x80) return;

?

/*清除中断标志位(若设备支持自动清除,则不需要此位)*/

Outb(value & 0x7f, short_base);

?

/* 中断处理函数,数据处理 */

……

/* 唤醒等待的进程 */

Wake_up_interrruptible(&short_quue);

}

?

中断处理程序:(运行环境为中断上下文)

????1.不能向用户空间发送或接受数据,因为进程变了,用户就变了,中断不对应任何进程

????2.不能使用可能引起阻塞的函数

????3.不能使用可能引起调度的函数,中断中无进程,无法调度

?

?

3、释放中断

Void free_irq(unsigned int irq,void * dev_id);

当被释放的是共享中断时,必须设定dev_id位,否则共享中断全线不能用

?

?

二、按键驱动处理程序分析

分析实现流程:

????????//混杂设备结构体,主设备为10,次设备号不同的一类设备

static struct miscdevice misc = {

????.minor = MISC_DYNAMIC_MINOR,????????//次设备号

????.name = DEVICE_NAME,????????//设备名

????.fops = &dev_fops????????????//字符设备的file_operation

};

1.初始化程序

Static int __init dev_init(void){

????Int ret;

????ret = misc_register(&misc);????????//注册混杂设备

????……

????return ret;

}

?

2.file_operations 按键实现的操作

static struct file_operations dev_fops = {

????.owner = buttons_open,????//打开操作

????.release = buttons_close,

????.poll = buttons_poll????????//select,多路监控

};

//open 函数实现

Static buttons_open(static inode *inode,struct(file *file)){

????????//为六个中断线分别注册驱动程序 总的大小/单个的大小=个数

????For(I = 0, i<sizeof(button_irqs)/sizeof(button_irqs[0]);i++){????

????????If(button_irqs[i].irq<0)????????

????????????Continue;

//制定中断处理程序, IRQ_TYPE_EDGE_BOTH:双边沿产生中断

????request_irq(button_irqs[i].irq,buttons_interrupt,IRQ_TYPE_EDGE_BOTH,button_irqs[i].name,(void *)&button_irqs[i]);

}

}

//poll 函数实现

static unsigned int buttons_poll(struct file *file,struct poll_table_struct *wait){

????poll_wait(file,&button_waitq,wait);????????//指明要使用的等待队列

????if(ev_press)????????????//全局静态变量,初始值未按下为0,为1时按键按下

????????mask |= POLLIN | POLLRDNORM; ????//按键可读不可写

????return mask;????????//返回掩码

}

//当按键按下,程序开始读,读函数实现

static unsigned int buttons_read(struct file * filp,char __user *buff,size_t count,loff_t *offp){

????if(!ev_press)????{????????//如果未按下

????????if(filp->f_flags & O_NONBLOCK)????//O_NONBLOCK:用户通过此指定不阻塞

????????????return –EAGAIN;

????????else

????????????wait_event_interruptible(button_wait,ev_press);//阻塞在等待队列

}

ev_press = 0; //此行语句之前,ev_press其实是1的,中断程序里设置为1

????????????????????//读取键值

err = copy_to_user(buff,(const void *)key_values,min(sizeof(key_values),count));

return err ? –EFAULT : min(sizeof(key_values),count);

}

?

3.中断处理程序

static irqreturn_t buttons_interrupt(int irq, void *dev_id){

????????//读取按键gpio的数据寄存器的值

????down = !gpio_getpin(button_irqs->pin);//按下是值为0,而程序中1表示按下

????????//key_values初始全是为0的,按下时变为1,则不再运行,可防止抖动

if(down != (key_values[button_irqs->number] & 1)){????

????????key_values[button_irqs->number] = ‘0‘ + down;

????????ev_press = 1;????????//有键按下

????????wake_up_interruptible(&button_waitq);

}

return IRQ_RETVAL(IRQ_HANDLED);

}

?

?

内核中断及按键驱动程序

标签:

原文地址:http://www.cnblogs.com/lihaiyan/p/4274461.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!