我正在学习linux内核中的中断处理,并在下面的代码片段中尝试在IRQ2上注册虚拟irq处理程序。但它似乎没有注册,因为我看到负面的返回值和内核中的消息如下所示,这是由于试图free_irq()
的清理功能引起的:
[ 2203.989585] Trying to free already-free IRQ 2
下面的是来自内核日志的printk,表明它尚未注册:
Here with registering IRQ handler on IRQ2 for flowTest...retval_irqreg= -22
以下是我的代码的相关部分,它有四个功能
1 the bottom half
2. handler
3. init function
4. cleanup function
我还没有安排下半部分,尽管它存在于下方。我正在研究内核3.5.0-17。
//Bottom half for the irq handler
static void bh_flowTest()
{
printk(KERN_INFO "Inside bottom half for flowTest.\n");
}
// IRQ handler function
static irqreturn_t flow_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
printk(KERN_INFO "This is flowTest IRQ handler.\n");
//static struct tq_struct task = {NULL, 0, bh_flowTest, NULL};
/* Schedule bottom half to run */
//queue_task(&task, &tq_immediate);
// mark_bh(IMMEDIATE_BH);
return IRQ_HANDLED;
}
static int flow_init(void)
{
printk(KERN_ALERT "Here with flowTest module ... loading...\n");
int result=0;
dev_t dev=0;
result = alloc_chrdev_region(&dev, minor_num,
num_devices,"mod_flowtest"); // allocate major number dynamically.
i=MAJOR(dev);
printk(KERN_ALERT "Major allocated = %d",i);
cdev_init(&ms_flow_cd,&flow_fops);
cdev_add(&ms_flow_cd,dev,1);
//Registering interrupt handler on IRQ2 since IRQ2 is free as per /proc/interrupts
int retval_irqreg;
retval_irqreg=request_irq(2,(irq_handler_t)flow_irq_handler, /* our handler. It has been typecasted to remove warnings of incompatible pointer type , and enum irqreturn_t. Try removing the cast and see the warnings */
IRQF_SHARED,
"test_flow_irq_handler", NULL);
printk(KERN_ALERT "Here with registering IRQ handler on IRQ2 for flowTest...retval_irqreg= %d\n",retval_irqreg);
return 0;
}
static void flow_terminate(void)
{
dev_t devno=MKDEV(i,0); // wrap major/minor numbers in a dev_t structure , to pass for deassigning.
printk(KERN_ALERT "Going out... exiting...\n");
unregister_chrdev_region(devno,num_devices); //remove entry from the /proc/devices
free_irq(2, NULL);
}
我觉得有一些基本的错误,但是如果有人可以指出我那个......!
答案 0 :(得分:1)
看起来您的硬件上还没有IRQ 2
。即,当你调用request_irq()
时,Linux内核还不知道必须将外围硬件必须作为IRQ编号“ 2 ”的触发器的哪条物理线路中断,因为它只是一个尚未与任何实际物理中断相关联的数字。)
基本上首先需要将特定的IRQ号与实际物理量相关联
尝试为该IRQ号注册ISR之前的硬件中断。 thsi通常使用irq_domain_add_linear()
在Linux内核中完成。
过去,可以选择IRQ编号,使它们将硬件IRQ线与根中断控制器(即实际触发中断线的组件)相匹配,现在这个数字只是一个数字。
irq_alloc_desc*()
和irq_free_desc*()
API提供irq编号的分配,但它们不提供对控制器反向映射的任何支持-local IRQ(hwirq)编号进入Linux IRQ编号空间。Linux内核的当前设计使用单个大数字空间,其中每个单独的IRQ源被分配不同的数字。当只有一个中断控制器时,这很简单,但在具有多个中断控制器的系统中,内核必须确保为每个中断控制器分配非重叠的Linux IRQ编号分配。
Linux内核中的更多详细信息 Documentation/IRQ-domain.txt 。
您也可能有兴趣为现有中断注册ISR(比如键盘IRQ?)当为单个IRQ注册多个ISR时,Linux内核将调用{{3}中每个驱动程序中的每个ISR。 }。