中断处理例程

irqreturn_t handler(int irq, void *dev)

中断处理例程和其他的c程序代码没有太大的区别,当然它必须准守之前提到的一些规范。

中断处理例程的功能就是将有关中断接收的信息反馈给设备,并根据正在服务的中断的不同含义对数据进行相应的读或写。这里可能会涉及到一步清除‘中断标志位’的操作,大多数硬件设备在它们的“interrupt-pending(中断挂起)”位被清除之前不会产生其他的中断。当然也有一些程序没有中断挂起位。

关于中断挂起位举个之前处理过的距离感应器的例子:

当中断发生后,驱动程序需要读取设备上的某个寄存器,以达到再次开启中断的目的。

  1. 有物体接近/离开了器件之后,中断被触发
  2. 运行中断处理例程
  3. 在中断处理例程中读取寄存器用以打开设备中断,等待下一次中断被触发

 

中断处理例程的两个参数,irq表示中断号,void *dev是request_irq函数中传入的参数,这里再复习在request_irq函数。

request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
	    const char *name, void *dev)

返回值irqreturn_t,一般来说,处理好中断返回一个IRQ_HANDLED就可以了,当然还有其他返回值,如下:

/**
 * enum irqreturn
 * @IRQ_NONE		interrupt was not from this device or was not handled
 * @IRQ_HANDLED		interrupt was handled by this device
 * @IRQ_WAKE_THREAD	handler requests to wake the handler thread
 */
enum irqreturn {
	IRQ_NONE		= (0 << 0),
	IRQ_HANDLED		= (1 << 0),
	IRQ_WAKE_THREAD		= (1 << 1),
};

中断处理例程的一个主要问题是怎么在处理例程内完成耗时的任务。响应一次设备中断需要完成一定数量的工作,但是中断处理例程需要尽快结束而不能使中断阻塞的时间过长,这两个需求(工作和速度)彼此冲突,不可协调。

Linux通过将中断处理例程分成两部分来解决这个问题。也就是我们常说的顶半部和底半部,被称为“顶半部”的部分,是实际响应中断的例程,也就是用request_irq注册的中断例程;而“底半部”是一个被顶半部调度,并在稍后更安全的时间内执行的例程。顶半部和底半部处理例程之间最大的不同,就是当底半部处理例程执行时,所有的中断都是打开的——这就是所谓的在更安全的时间内运行。经典的情况是,顶半部保存设备的数据到一个设备特定的缓冲区并调度它的底半部,然后退出。这种方式允许在底半部工作期间,顶半部还可以继续为新的中断服务。

之前提到工作队列几时处理底半部的一种机制。除此之外还有softirq和tasklet。

你可能感兴趣的:(驱动)