Linux中断
Linux中断处理过程
1.使能中断,初始化相应的寄存器
2.注册中断服务函数,也就是向irqTable数组的指定标号处写入中断服务函数
3.中断发生以后进入IRQ中断服务函数,IRQ的中断服务函数在irqTable里面查找具体的中断处理函数,找到以后执行相应的中断处理函数
Linux中断处理API函数
request_irq(注册中断处理程序)
request_irq函数用于申请中断,但是可能会导致睡眠,因此不能在中断上下文或者其他禁止睡眠的代码段中使用request_irq函数。request_irq函数会使能中断,所以不需要我们手动去使能中断。
函数原型:
int request_irq(unsigned int irq,
irq_handler_t handler,
unsigned long flags,
const char *name,
void *dev);
参数说明:
irq:要申请中断的中断号
handler:中断处理函数,当中断发生以后就会执行此中断处理函数
flags:中断标志,可以在include/linux/interrupt.h里面查看所有的中断标志
name:中断名字,设置以后可以在/proc/interrupts文件中可以看到对应的中断名字
dev:如果flags设置为IRQF_SHARED的话,dev用来区分不同的中断,一般情况下将dev设置为设备结构体,dev会传递给中断处理函数irq_handler_t的第二个参数
第二个参数handler是一个指针,指向处理这个中断的实际中断处理程序。只要操作系统一接收到中断,该函数就被调用
typedef irqreturn_t (*irq_handler_t)(int,void *); // handler函数的原型,接受两个参数,返回值为irqreturn_t
常用中断标志:
标志 | 描述 |
---|---|
IRQF_SHARED | 多个设备共享一个中断线,共享的所有中断都必须指定此标志。如果使用共享中断的话,request_irq函数的dev参数就是唯一区分他们的标志。 |
IRQF_ONESHOT | 单次中断,中断执行一次就结束 |
IRQF_TRIGGER_NONE | 无触发 |
IRQF_TRIGGER_RASING | 上升沿触发 |
IRQF_TRIGGER_FALLING | 下降沿触发 |
IRQF_TRIGGER_HIGH | 高电平触发 |
IRQF_TRIGGER_LOW | 低电平触发 |
代码实例:
// irq:请求的中断线
// my_interrupt:中断处理程序
// IRQF_SHARED:中断线可以共享
// my_device:中断名字
// my_dev:传递my_dev变量给dev形参。如果请求失败将直接返回
if(request_irq(irqn,my_interrupt,IRQF_SHARED,"my_device",my_dev))
{
return -EIO;
}
free_irq(释放中断)
释放相应的中断,注释掉相应的中断处理程序,并释放中断线。如果中断不是共享的,那么free_irq会删除中断处理函数并且禁止中断.
函数原型:
void free_irq(unsigned int irq,void *dev);
参数说明:
irq:要释放的中断。
dev:如果flags设置为IRQF_SHARED的话,dev用来区分不同的中断。共享中断只有在释放最后中断处理函数的时候才会被禁止掉
中断处理函数
使用request_irq函数申请中断的时候需要设置中断处理函数
函数原型:
irqreturn (*irq_handler_t)(int , void *);
参数说明:
第一参数:中断处理函数相对应的中断号
第二参数:指向void的指针,也就是一个通用指针,需要与request_irq函数的dev参数保持一致,用于区分共享中断的不同设备
返回值:
enum irqreturn
{
IRQ_NONE = (0 << 0),
IRQ_HANDLED = (1 << 0),
IRQ_WAKE_THREAD = (1 << 1),
};
中断使能与禁止函数
常用中断使用和禁止函数
void enable_irq(unsigned int irq);
void disable_irq(unsigned int irq);
enable_irq和disable_irq用于使能和禁止指定的中断,irq就是要禁止的中断号。disable_irq函数要等到当前正在执行的中断处理函数执行完才返回,因此需要保证不会产生新的中断,并且确保所有已经开始执行的中断处理程序已经全部退出。在这种情况下,可以使用另外一个中断禁止函数:
void disable_irq_nosync(unsigned int irq);
disable_irq_nosync函数调用以后立即返回,不会等待当前中断处理程序执行完毕。上面三个函数都是使能或者禁止某一个中断,如果需要关闭全局中断需要使用一下函数:
local_irq_enbale(); // 使能当前处理器中断系统
local_irq_disbale(); // 禁止当前处理器中断系统
local_irq_save(flags); // 用于禁止中断,并且将中断状态保存到flags中
local_irq_restore(flags); // 用于恢复中断,将中断恢复到flags状态。
标签:函数,中断,irq,dev,简述,Linux,IRQF,处理函数
From: https://www.cnblogs.com/Wangzx000/p/17209226.html