Linux内核API irq_set_irq_type

irq_set_irq_type函数功能描述:此函数用于设置中断处理函数触发的类型,被操作的中断描述符保存在数组irq_desc中,对应的下标为参数irq的值,设置的中断触发类型为参数type所代表的类型。

irq_set_irq_type文件包含

#include<linux/irq.h>

irq_set_irq_type函数定义

在内核源码中的位置:linux-3.19.3/kernel/irq/chip.c

函数定义格式:

int irq_set_irq_type(unsigned int irq, unsigned int type)

irq_set_irq_type输入参数说明

  • 参数 unsigned int irq是对应的中断号,与数组irq_desc的下标相对应,数组的大小为16640。
  • 参数unsigned int type是系统定义的中断触发类型,定义见文件linux-3.19.3/include/linux/irq.h,可能的取值定义如下:
    • IRQ_TYPE_NONE 0x00000000系统默认的没有明确指明类型的触发模式
    • IRQ_TYPE_EDGE_RISING 0x00000001上升沿触发
    • IRQ_TYPE_EDGE_FALLING 0x00000002下降沿触发
    • IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)上升沿下降沿两种触发都行
    • IRQ_TYPE_LEVEL_HIGH 0x00000004高电平触发
    • IRQ_TYPE_LEVEL_LOW 0x00000008低电平触发
    • IRQ_TYPE_SENSE_MASK 0x0000000f以上任何一种条件
    • IRQ_TYPE_DEFAULT IRQ_TYPE_SENSE_MASK以上任何一种条件
    • IRQ_TYPE_PROBE 0x00000010在进程中查询

irq_set_irq_type返回参数说明

函数的返回结果是int型变量,返回0或者负数,如果返回结果是负数,说明设置中断触发类型失败;如果返回结果是0,有四种情况:

  • 设置中断触发类型成功;
  • 传入的中断触发类型参数是IRQ_TYPE_NONE,如果传入此参数,函数不会更改中断的触发类型;
  • 数组中与irq对应的元素的chip字段的值为NULL;
  • 数组中与irq对应的元素的chip字段的值不为NULL,但chip字段的set_type字段的值为NULL。

irq_set_irq_type实例解析

编写测试文件:irq_set_irq_type.c

头文件引用及全局变量定义:

#include <linux/interrupt.h>
#include<linux/irq.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int irq=10;  //定义中断号变量

中断处理函数及中断线程函数定义:

// 自定义中断处理函数
static irqreturn_t irq_handler(int irq, void *dev_id)
{
    printk("the irq is :%d\n", irq);   //显示中断号
    printk("in the interrupt handler function\n");
    return IRQ_WAKE_THREAD;            //触发中断线程处理函数执行
}

// 自定义中断线程处理函数
static irqreturn_t irq_thread_fn(int irq, void *dev_id)
{
    printk("the irq is :%d\n", irq);   //显示中断号
    printk("in the thread handler function\n");
    return IRQ_HANDLED;
}

模块加载函数定义:

static int __init irq_set_irq_type_init(void)
{
    int result=-1, result1=-1;
    int irqtype=1;
    printk("into irq_set_irq_type_init\n");

    /*申请中断*/
    result=request_threaded_irq(irq, irq_handler, irq_thread_fn, IRQF_DISABLED, "A_NEW_DEVICE", NULL);
    result1=irq_set_irq_type(irq, irqtype); //调用irq_set_irq_type( )函数设置中断类型

    /*显示函数调用结果*/
    printk("the request_threaded_irq result is: %d\n", result);
    printk("the irq_set_irq_type result is:%d\n", result1);
    printk("out irq_set_irq_type_init\n");
    return 0;
}

模块退出函数定义:

static void __exit irq_set_irq_type_exit(void)
{
    free_irq(irq, NULL);
    printk("Goodbye irq_set_irq_type\n");
    return;
}

模块加载、退出函数调用:

module_init(irq_set_irq_type_init);
module_exit(irq_set_irq_type_exit);

实例运行结果及分析:

编译模块,执行命令insmod irq_set_irq_type.ko插入内核模块,然后输入命令dmesg -c查看内核输出信息,出现如图所示的信息。

Linux内核API irq_set_irq_type

结果分析:

由图可以看出函数irq_set_irq_type( )的返回值是0,并且中断处理函数执行一次。但返回0并不代表设置中断触发类型成功,因为动态申请的中断描述符其字段chip的值为NULL,所以返回0是必然。

如果想设置中断的类型成功,必须满足以下条件:

  • 中断描述符存在数组irq_desc中;
  • 参数type不是IRQ_TYPE_NONE;
  • 中断描述符的chip字段的值不为NULL;
  • 中断描述符的字段chip的字段set_type的值不为NULL。

但是满足以上条件,也不一定能设置成功,还需要看字段set_type代表的函数的实现。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程