函数:irq_set_chip( )
文件包含:
#include<linux/irq.h>
函数定义:
在内核源码中的位置:linux-3.19.3/kernel/irq/chip.c
函数定义格式:
int irq_set_chip(unsigned int irq, struct irq_chip *chip)
函数功能描述:
此函数是为irq_desc数组中对应下标为irq的元素设定irq_chip的值,如果传入的参数chip为NULL,则使用系统定义好的no_irq_chip为它赋值:如果传入的参数chip不为NULL,则用传入的参数赋值。在赋值之前函数会调用函数irq_chip_set_defaults( )对传入的参数chip进行相应的设置处理,处理完之后把参数chip赋值给irq_desc数组中的变量的irq_chip。
输入参数说明:
参数irq是设备对应的中断编号,对应数组irq_desc中元素的下标,此数组的大小为16640。
参数chip是一个struct irq_chip型的结构体变量,是对应的硬件中断描述符的irq_chip字段的值,定义见文件linux-3.19.3/include/linux/irq.h如下:
struct irq_chip {
const char *name;
unsigned int (*irq_startup)(struct irq_data *data);
void (*irq_shutdown)(struct irq_data *data);
void (*irq_enable)(struct irq_data *data);
void (*irq_disable)(struct irq_data *data);
void (*irq_ack)(struct irq_data *data);
void (*irq_mask)(struct irq_data *data);
void (*irq_mask_ack)(struct irq_data *data);
void (*irq_unmask)(struct irq_data *data);
void (*irq_eoi)(struct irq_data *data);
int (*irq_set_affinity)(struct irq_data *data, const struct
cpumask *dest, bool force);
int (*irq_retrigger)(struct irq_data *data);
int (*irq_set_type)(struct irq_data *data, unsigned int flow_type);
int (*irq_set_wake)(struct irq_data *data, unsigned int on);
void (*irq_bus_lock)(struct irq_data *data);
void (*irq_bus_sync_unlock)(struct irq_data *data);
void (*irq_cpu_online)(struct irq_data *data);
void (*irq_cpu_offline)(struct irq_data *data);
void (*irq_suspend)(struct irq_data *data);
void (*irq_resume)(struct irq_data *data);
void (*irq_pm_shutdown)(struct irq_data *data);
void (*irq_calc_mask)(struct irq_data *data);
void (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
int (*irq_request_resources)(struct irq_data *data);
void (*irq_release_resources)(struct irq_data *data);
void (*irq_compose_msi_msg)(struct irq_data *data, struct msi_msg *msg);
void (*irq_write_msi_msg)(struct irq_data *data, struct msi_msg *msg);
unsigned long flags;
};
如果传入的参数chip为NULL,则系统用no_irq_chip进行初始化,no_irq_chip的定义见文件linux-3.19.3/kernel/irq/dummychip.c,如下:
struct irq_chip no_irq_chip = {
.name = "none",
.irq_startup = noop_ret,
.irq_shutdown = noop,
.irq_enable = noop,
.irq_disable = noop,
.irq_ack = ack_bad,
};
返回参数说明:
此函数的返回结果是int型变量,可能的取值是0、-22,如果返回0说明设置字段chip的值成功,如果返回-22说明设置字段chip的值失败,设置失败的原因是与irq对应的数组中的元素不存在。
实例解析:
编写测试文件:irq_set_chip.c头文件引用及全局变量定义:
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int irq=2; //中断号定义,可更改1000进行错误验证
中断处理函数定义及中断线程处理函数定义:
// 自定义中断处理函数
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_chip_init(void)
{
int result=0;
int result1=0;
printk("into irq_set_chip_init\n");
/*动态申请中断*/
result=request_threaded_irq(irq, irq_handler, irq_thread_fn, IRQF_DISABLED, "A_NEW_DEVICE", NULL);
result1=irq_set_chip(irq, NULL); //调用函数irq_set_chip()irq是对应的中断号
printk("the request_threaded_irq result is: %d\n", result);
//显示函数request_threaded_irq( )结果
printk("the irq_set_chip result is: %d\n", result1);
//显示函数irq_set_chip( )返回结果
printk("out irq_set_chip_init\n");
return 0;
}
模块退出函数定义:
static void __exit irq_set_chip_exit(void)
{
free_irq(irq, NULL); //释放申请的中断
printk("Goodbye irq_set_chip_exit\n");
return;
}
模块加载、退出函数调用:
module_init(irq_set_chip_init);
module_exit(irq_set_chip_exit);
实例运行结果及分析:
当设置的中断号为2时,编译模块,执行命令insmod irq_set_chip.ko插入内核模块,然后输入dmesg -c查看内核输出信息,出现如图A
所示的结果。
在卸载模块之前输入命令cat /proc/interrupts查看文件/proc/interrupts的内容,出现如图B
所示的结果。
如果将函数的第一个参数irq设置为1000,插入模块,会出现如图C
所示的结果。
结果分析:
由图A
函数irq_set_chip( )的返回结果可以判断设置中断描述符中的irq_chip字段成功;图B
中中断号2对应的信息可以看到函数irq_set_chip( )执行之后的效果,第六列的内容为none,如果没有函数irq_set_chip( ),此部位的内容应该为IO-APIC-
图C
中的显示信息是函数执行失败时的一种情况,显示内核的调试信息,因为传递的参数irq的值超过了数组irq_desc的范围。
酷客网相关文章:
评论前必须登录!
注册