6. 中断的使用方法
在ARM64架构的Linux内核中,中断处理是操作系统响应硬件事件的关键机制。以下是中断处理的一般使用方法和步骤:
-
中断控制器初始化:
- 在系统启动时,需要初始化中断控制器(如GIC,Generic Interrupt Controller)。这通常在
arch/arm64/kernel/setup.c
文件中完成,通过调用gic_init()
来设置中断控制器。
- 在系统启动时,需要初始化中断控制器(如GIC,Generic Interrupt Controller)。这通常在
-
中断请求(IRQ)分配:
- 使用
request_irq()
函数来请求一个中断号(IRQ)。这个函数需要传递中断号、中断处理函数、中断类型(如共享或独占)和上下文数据等参数。
- 使用
-
中断处理函数:
- 编写一个中断处理函数,这个函数将在中断发生时被调用。中断处理函数通常需要遵循特定的原型,例如
irqreturn_t irq_handler(unsigned int irq, void *dev_id)
。
- 编写一个中断处理函数,这个函数将在中断发生时被调用。中断处理函数通常需要遵循特定的原型,例如
-
中断处理函数注册:
- 在请求中断时,将中断处理函数与中断号关联。
request_irq()
函数会返回一个错误码,如果成功,返回0。
- 在请求中断时,将中断处理函数与中断号关联。
-
中断处理函数的执行:
- 当硬件设备产生中断时,中断控制器会通知CPU,CPU会跳转到中断处理函数执行中断服务例程。
-
中断结束:
- 中断处理完成后,需要使用
irq_set_affinity()
设置中断的CPU亲和性,以便在多核系统中正确分配中断处理任务。
- 中断处理完成后,需要使用
-
释放中断:
- 当不再需要中断处理时,使用
free_irq()
函数释放之前请求的中断号。
- 当不再需要中断处理时,使用
-
中断处理的同步:
- 在中断处理函数中,可能需要同步操作,如禁用中断(使用
local_irq_disable()
)和启用中断(使用local_irq_enable()
)。
- 在中断处理函数中,可能需要同步操作,如禁用中断(使用
-
中断处理的优化:
- 为了提高中断处理效率,可能需要使用中断共享、快速中断处理(FIQ)等技术。
-
中断处理的调试:
- 使用
irq_affinity_hint()
和irq_affinity_hint_handler()
来设置中断的CPU亲和性提示,这有助于在多核系统中优化中断处理。
- 使用
6.1 gic中断使用
6.1.1 设备树的编写
interrupt-parent = <&gic>;
i2c4: i2c@ffa30000 {
compatible = "rockchip,rk3562-i2c", "rockchip,rk3399-i2c";
reg = <0x0 0xffa30000 0x0 0x1000>;
clocks = <&cru CLK_I2C4>, <&cru PCLK_I2C4>;
clock-names = "i2c", "pclk";
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
};
6.1.2 驱动编写
static int lpc32xx_ts_probe(struct platform_device *pdev)
{
...
irq = platform_get_irq(pdev, 0);
...
error = request_irq(tsc->irq, lpc32xx_ts_interrupt,
0, pdev->name, tsc);
...
}
6.2 gpio中断使用
6.2.1 设备树的编写
bq25700: bq25700@6b {
compatible = "ti,bq25703";
reg = <0x6b>;
interrupt-parent = <&gpio1>;
interrupts = <RK_PA1 IRQ_TYPE_LEVEL_LOW>;
};
6.2.2 驱动编写
static int i2c_gpio_fi_act_on_scl_irq(struct i2c_gpio_private_data *priv,
irqreturn_t handler(int, void*))
{
int ret, irq = gpiod_to_irq(priv->scl);
...
ret = request_irq(irq, handler, IRQF_TRIGGER_FALLING,
"i2c_gpio_fault_injector_scl_irq", priv);
...
}