Kernel之共享中断

背景

最近有个测试用例的需求,是关于中断管理的。
在现有的硬件基础上,实现以下功能:

  • 缺省情况下提供默认的中断处理程序
  • 能使能和屏蔽某一特定中断

后面用共享中断实现了这个测试用例

共享中断

有时候多个设备可能共享一根硬件中断线,在现实应用场景中广泛存在,特别像PCI控制器,GPIO等,所以内核提供了这种中断共享的机制。

下面是中断共享的使用及注意点:

  1. 共享中断的多个设备在申请中断时,都应加上 IRQF_SHARED 标志,而且一个设备以IRQF_SHARED申请某中断成功的前提是该中断未被申请,或该中断虽然被申请了,但是之前申请该中断的所有设备也都以IRQF_SHARED标志申请该中断。
  2. 尽管内核模块可访问的全局地址都可以作为request_irq(…,void*dev_id)的最后一个参数dev_id,但是设备结构体指针显然是可传入的最佳参数。
  3. 在中断到来时,会遍历执行共享此中断的所有中断处理程序,直到某一个函数返回IRQ_HANDLED。在中断处理程序顶半部中,应根据硬件寄存器中的信息比照传入的dev_id参数迅速地判断是否为本设备的中断,若不是,应迅速返回IRQ_NONE,如下图所示。

共享中断伪代码实现:

/* 中断处理函数 */
static irqreturn_t irq_test_handler(int irq, void *data)
{
	printk("This is a test to verify the interrupt!\n");

	/* 
		这里可以加入判断是否为本设备中断, 不是本设备中断,立即返回 IRQ_NONE ;
		可以通过申请中断时传入的最后一个参数,来获取需要判断的依据,即这里的data,一般为设备的数据结构体
	*/

	return IRQ_HANDLED;
}

/* 在驱动的probe函数或是init函数中申请中断 */
static int irq_test_probe(struct platform_device *pdev)
{
	...
	/* 
		见下面备注
	*/
	ret = request_threaded_irq(i_data->test_irq_num, NULL, irq_test_handler,
				IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED,
				"elan_ts"/*pdev->name*/, i_data);
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to request irq_test_device IRQ\n");
		goto out2;
	}
	...
}

/* 在驱动的remove函数或是exit函数中释放中断 */
static int irq_test_remove(struct platform_device *pdev)  
{  
	... 
	
	if(data->test_irq_num > 0)
		/* 注意这里最后一个参数要和申请时的最后一个参数对应 */
		free_irq(data->test_irq_num, (void *)data);   

	...
}

备注:

  • 要共享中断,在每个申请中断的时候,最重要的就是标志flag里的IRQF_SHARED标志位都要设置,触发类型标志位要匹配,还有这里的”elan_ts”要和共享中断的设备名一致,不然会报 mismatch 错误
  • 这里我们共享的是elan触摸屏的中断,所以和elan驱动中申请中断时的设备名一致; 同时,elan驱动中申请中断时也需要加上 IRQF_SHARED 标志
  • 有些中断是不能共享的,比如NMIs不可屏蔽中断等

内核里的原始说明:

/*      
	* Can't share interrupts unless both agree to and are         
	* the same type (level, edge, polarity). So both flag         
	* fields must have IRQF_SHARED set and the bits which         
	* set the trigger type must match. Also all must         
	* agree on ONESHOT.         
	* Interrupt lines used for NMIs cannot be shared.         
*/

具体的可以参见内核里面的代码

参考

https://blog.csdn.net/yueni_zhao/article/details/127546784