现在的位置: 首页 > 综合 > 正文

驱动程序学习(六)中断处理

2013年09月22日 ⁄ 综合 ⁄ 共 1734字 ⁄ 字号 评论关闭

中断的概念我想大家都很清楚,在我们学习单片机的时候接触很多,所以这里就不再赘述了。

在linux设备驱动程序中,中断处理相关的首先是申请与释放IRQ的API是:

request_irq()和free_irq()

request_irq()的原型是

int request_irq(unsigened int irq,void (*handler)(int irq,void *dev_id , struct pt_regs *regs , unsigned long irqflags, count char * devname , void * dev_id))

irq:是要申请的硬件中断号,

handler:是向系统登记的中断处理函数,是一个回调函数,中断发生使,系统调用这个函数

dev_id 参数将被传递

irqflags :是中断处理的属性,若设置SA_INTERRUPT标明中断处理程序是快速处理程序。

快速处理程序被调用时屏蔽所有中断,慢处理程序不屏蔽。

若设置SA_SHIRQ 则多个设备共享中断,dev_id在中断共享时会用到,一般设置为该设备的device结构本身或者NULL

free_irq()的原型是

      void free_irq( unsigend itn irq , void  * dev_id )

另外非常重要的是:

linux中断分为两个半部。

上半部分的功能是“登记中断”,当一个中断发生时,它进行相应的硬件读写后,把中断例程的下半部分挂到该设备的下半部分执行队列中去。

下半部分的作用 几乎做了中断处理程序的所有的事情,而且可以被新的中断打断。而上半部分是不可中断的。

这样在我们响应中断时需要非常快速,而在处理时则不必太紧急,而可以处理响应新产生的中断。

linux实现下半部的机制主要是tasklet和工作队列

tasklet 基于 Linux softirq

通过定义tasklet及其处理函数并将二者关联:

void my_tasklet_func(unsigned long);//定义一个处理函数

 

DECLARE_TASKLET(my_tasklet  , my_tasklet_func ,data)//定义一个tasklet结构my_tasklet 与my_tasklet_func(data)相关联。

接着我们来运行一个实例

在我们上篇博客中的驱动程序文件中添加如下代码:

http://blog.csdn.net/zhaole20094463/article/details/7907007

void test_tasklet_action(unsigned long t);

DECLARE_TASKLET(test_tasklet, test_tasklet_action ,0);

void test_tasklet_action(unsigned long t)
{
printk(KERN_EMERG"tasklet is executing\n");
}

修改该文件write函数

static ssize_t chardev_write(struct file *filp,const char *buf,size_t len,loff_t *off)
{
if(down_interruptible(&sem))
{
return -ERESTARTSYS;
}
if(copy_from_user(&chardev_var,buf,sizeof(int)))
{
up(&sem);
return -EFAULT;
}
tasklet_schedule(&test_tasklet);//在此处产生中断。

up(&sem);
flag = 1;

wake_up_interruptible(&outq);
return sizeof(int);
}

该模块完成的功能就是在该设备被写入一个字符后即可出发中断,中断打印出我们中断服务子函数中的语句。

编译完成后加载模块,创建设备节点,使用

http://blog.csdn.net/zhaole20094463/article/details/7907007该博客中的写测试程序即可

在我们输入一个字符后产生中断,

打印   tasklet is executing

备注:如果没有打印信息的话多试几次,我的就是由于系统的原因,第一次存储在了缓冲区里,再测试一次的时候打印信息就正常了。

抱歉!评论已关闭.