九鼎创展论坛中文版English
登录 | 立即注册 设为首页收藏本站 切换到宽版
查看: 4172|回复: 0
打印 上一主题 下一主题

Linux的中断编程

[复制链接]
跳转到指定楼层
楼主
发表于 2012-7-19 11:55:57 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
Linux提供了很多API函数用于中断编程,同时提供了几种底半部机制用于中断函数的实现。正确的使用它们,有利于优化需要实现的中断机制。
.1        申请IRQ
static inline int __must_check
request_irq(unsigned int irq, irq_handler_thandler, unsigned long flags,const char *name, void *dev)
{
         returnrequest_threaded_irq(irq, handler, NULL, flags, name, dev);
}
irq为要申请的硬件中断号,handle为向系统登记的中断处理函数,中断发生时系统将调用它。flags为中断处理的属性。
request_irq()返回0表示申请成功,返回-INVAL表示中断号无效或处理函数指针为NULL,返回-EBUSY表示中断已经被占用且不能共享。
.2        释放IRQ
void free_irq(unsigned int irq, void *dev_id)
{
         kfree(__free_irq(irq,dev_id));
}
它与request_irq()函数对应,用于释放IRQ中断。
.3        使能和屏蔽中断
void disable_irq(unsigned int irq)
{
         structirq_desc *desc = irq_to_desc(irq);
         if(!desc)
                   return;
         disable_irq_nosync(irq);
         if(desc->action)
                   synchronize_irq(irq);
}
disable_irq函数用于屏蔽IRQ中断;
void enable_irq(unsigned int irq)
{
         structirq_desc *desc = irq_to_desc(irq);
         unsignedlong flags;
         if(!desc)
                   return;
         spin_lock_irqsave(&desc->lock,flags);
         __enable_irq(desc,irq, false);
         spin_unlock_irqrestore(&desc->lock,flags);
}
enable_irq函数用于使能IRQ中断,可以看到函数中加入了自旋锁。
#define local_irq_enable() \
         do {trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
#define local_irq_disable() \
         do {raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
#define local_irq_save(flags)                             \
         do {                                                 \
                   typecheck(unsignedlong, flags);     \
                   raw_local_irq_save(flags);              \
                   trace_hardirqs_off();                       \
         }while (0)
#define local_irq_restore(flags)                         \
         do {                                                 \
                   typecheck(unsignedlong, flags);     \
                   if(raw_irqs_disabled_flags(flags)) {       \
                            raw_local_irq_restore(flags); \
                            trace_hardirqs_off();              \
                   }else {                                   \
                            trace_hardirqs_on();               \
                            raw_local_irq_restore(flags); \
                   }                                             \
         }while (0)
local_irq_enable和local_irq_restore函数用于恢复中断,local_irq_disable和local_irq_save用于屏蔽所有中断。local_irq_save将目前的中断状态保留在flags中,而local_irq_disable直接禁止中断。这里的local表明作用范围在本CPU内。
.4        底半部机制
   Linux实现底半部中断的机制主要有tasklet,工作队列和软中断。通常我们使用前两种。
.4.1    tasklet
定义tasklet及其处理函数,并将两者关联:
void my_tasklet_func(unsigned long);
DECLARE_TASKLET(my_tasklet,my_tasklet_func,data);
DECLARE_TASKLET定义名称为my_tasklet的tasklet并将其与my_tasklet_func函数绑定,传入这个函数的参数为data。在需要调度tasklet的时候引用tasklet_schedule函数就能使系统在适当时候运行:
tasklet_schedule(&my_tasklet);
.4.2    工作队列
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳市九鼎创展科技官方论坛 ( 粤ICP备11028681号-2  

GMT+8, 2024-11-23 11:01 , Processed in 0.018528 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表