中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
在 Linux 中,中断处理是操作系统与硬件设备之间通信的重要方式之一。Linux 内核中的中断处理程序负责响应硬件设备发出的中断信号,并执行相应的处理;
Linux 中断处理的一般流程:
硬件中断触发->中断控制器响应->中断处理程序调用->中断处理->中断处理程序完成
在驱动程序中实现中断:
1、获取中断号
2、请求中断
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char * name, void * dev);
参数1:中断号
参数2:中断处理函数
参数3:中断类型
参数4:中断处理函数的标识名称
参数5:设备指针
3、中断处理函数
函数指针定义
typedef irqreturn_t (*irq_handler_t)(int, void *);
3、释放中断请求
free_irq(unsigned int irq, void * dev_id);
举个例子:
#include <linux/init.h>
#include <linux/module.h>
#define GPIO_BUTTON_PIN 40
static unsigned int irq_num;
// 中断处理函数
static irqreturn_t key_irq_handler(int irq, void *dev_id)
{
int value = gpio_get_value(GPIO_BUTTON_PIN);
if (!value) {
printk("--------key press-------\n");
} else {
printk("--------key up----------\n")
}
return IRQ_HANDLED;
}
static int __init key_drv_init(void) {
int ret;
// 获取中断号
// 请求 GPIO 引脚
ret = gpio_request(GPIO_BUTTON_PIN, "key_gpio");
if (ret) {
printk(KERN_ERR "Failed to request GPIO pin\n");
return ret;
}
// 设置 GPIO 引脚方向为输入
ret = gpio_direction_input(GPIO_BUTTON_PIN);
if (ret) {
printk(KERN_ERR "Failed to set GPIO pin direction\n");
gpio_free(GPIO_BUTTON_PIN);
return ret;
}
// 将 GPIO 映射到 IRQ
irq_num = gpio_to_irq(GPIO_BUTTON_PIN);
if (irq_num < 0) {
printk(KERN_ERR "Failed to map GPIO to IRQ\n");
gpio_free(GPIO_BUTTON_PIN);
return irq_num;
}
// 请求中断
ret = request_irq(irq_num, key_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "key_irq", NULL);
if (ret) {
printk(KERN_ERR "Failed to register IRQ handler\n");
gpio_free(GPIO_BUTTON_PIN);
return ret;
}
return 0;
}
static void __exit key_drv_exit(void) {
free_irq(irq_num, NULL);
gpio_free(GPIO_BUTTON_PIN);
}
module_init(key_drv_init);
module_exit(key_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("dengcaixiang");
MODULE_DESCRIPTION("Simple key driver");
代码中实现了gpio按键中断,设备运行效果如下: