这段时间学习好累,没有及时更新。总结了几篇,没有及时发表。
实现中断需要两步:1.向内核注册中断 2.实现中断处理函数
使用前当然先要注册,下面就是注册函数的原型。注意红色字体的几个参数,下面将这几个参数什么作用。
中断注册函数:
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
{
return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}
返回0表示成功。错误返回错误码。最常见的错误是-EBUSY,表示当前申请的中断线已经被占用。
unsigned int irq:中断号
irq_handler_t handler:中断处理函数,这个函数中不能阻塞,不能睡眠,尽可能少的执行操作。耗时操作交给中断下文去做。Linux 内核有2 个不同的机制可用来实现底半部处理: tasklet (首选机制),它非常快,但是所有的 tasklet 代码必须是原子的;工作队列, 它可能有更高的延时,但允许睡眠(这是下文执行,并不在前面所说的不允许睡眠的范围)。另外中断函数可以有多个,用几个要注册几次中断。
enum irqreturn {
IRQ_NONE = (0 << 0), //不是本设备中断
IRQ_HANDLED = (1 << 0), //本设备中断
IRQ_WAKE_THREAD = (1 << 1), //处理程序请求线程唤醒
};
unsigned long flags:中断处理属性
IRQF_DISABLED :独占类型中断
IRQF_SHARED :共享类型中断
IRQF_SAMPLE_RANDOM 这个设备产生的中断对内核熵池(先不用管)有贡献
const char *name:设备名
注册后会出现/proc/irq/irq号/ name 文件夹出现
void *dev:共享中断时使用
用于共享中断信号线的指针。它是唯一的标识,在中断线空闲时可以使用它,驱动程序也可以用它来指向自己的私有数据区(来标识哪个设备产生中断)。若中断没有被共享,dev_id 可以设置为 NULL,但推荐用它指向设备的数据结构。
void free_irq(unsigned int irq,void *dev_id)
从内核注销一个中断服务函数
voiddisable_irq(unsigned int irq)
关闭指定的中断,并等待中断服务函数运行结束后才会返回,在中断函数外调用,不能再中断服务程序中调用。
void enable_irq(unsignedint irq)
使能指定中断
写了这么久博客了也没有人给我留言,提问。好伤心。。。