《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记
文章目录
- 中断线程化简介
- 中断线程化 API
- 中断线程化实验
中断线程化简介
中断线程化也是中断下文的一种方式,与工作队列和软中断不同的是,中断线程只用于这个中断,当发生中断的时候,会唤醒这个内核线程,然后由这个内核线程来执行中断下半部分的函数。
——原文
中断线程化 API
request_threaded_irq() 用来申请中断和中断线程,它和之前提到的 request_irq() 函数非常类似,仅仅多了一个 thread_fn 参数。
#include <linux/interrupt.h>
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn, unsigned long flags,const char *name,
void *dev);
函数功能:向内核注册一个中断服务函数(当 irq 对应的中断发生时,会执行 handler 指向的中断服务函数)。
中断服务函数原型为:typedef irqreturn_t (*irq_handler_t)(int, void *)
函数参数
- irq 中断号(在内核中是唯一的)
- handler 中断服务函数指针
- thread_fn 中断线程函数(为 NULL 表示不使用中断线程)
- flags 中断标志,具体内容由中断源决定,如果中断源为外部中断,则存在上升沿和下降沿两种标志
- name 中断名(会在 /proc/interrupts 下体现)
- dev 中断服务函数的参数
返回值
返回 0 表示申请成功,失败返回负值。
中断线程化实验
实验代码
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/delay.h>
int irq;
//中断下文(中断线程函数)
irqreturn_t thread_func(int irq, void *args)
{
msleep(1000);
printk("This is inttrupt thread func.\n");
return IRQ_RETVAL(IRQ_HANDLED);
}
//中断服务函数
irqreturn_t my_interrupt(int irq, void *args)
{
printk("my interrupt handler.\n");
return IRQ_WAKE_THREAD; // 唤醒中断线程函数
//return IRQ_RETVAL(IRQ_WAKE_THREAD); // 错误
}
static int interrupt_irq_init(void)
{
int ret = 0;
// 获取中断号
irq = gpio_to_irq(101);
printk("irq is %d\n", irq);
// 申请中断(线程)
ret = request_threaded_irq(irq, my_interrupt, thread_func, IRQF_TRIGGER_RISING, "inttrupt_test", NULL);
if(ret < 0)
{
printk("request irq error.\n");
return 0;
}
return 0;
}
static void interrupt_irq_exit(void)
{
printk("interrupt irq exit.\n");
// 注销中断
free_irq(irq, NULL);
}
module_init(interrupt_irq_init);
module_exit(interrupt_irq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xiaohui");
实验结果
和之前的软中断实验类似,在中断上文执行完成后,继续执行中断下文(中断线程函数)。