Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GPIO IRQ on ARM based Embedded Linux

I'm trying to program an GPIO IRQ on AT91SAM9M10-EKES evaluation board. I successfully registered the IRQ, and the IRQ is working. However, some interrupts are missed. I'm sending 26, and I get only 22.

The code:

static irqreturn_t wiegand_interrupt(int irq, void *dev_id){
  atomic_inc(&counter);
  printk(KERN_WARNING "IRQ recieved, counting... %d\n",atomic_read(&counter));
  return 0;
}
irq1 = gpio_to_irq(AT91_PIN_PA21);
if (irq1 < 0) {
    err = irq1;
    printk("Unable to get irq number for GPIO %d, error %d\n",AT91_PIN_PA21, err);
    goto fail;
}

err = request_irq(irq1,wiegand_interrupt,0 ,"wiegand",NULL);

irq2 = gpio_to_irq(AT91_PIN_PA20);
if (irq2 < 0) {
    err = irq2;
    printk("Unable to get irq number for GPIO %d, error %d\n",AT91_PIN_PA21, err);
    goto fail;
}

err = request_irq(irq2,wiegand_interrupt,0 ,"wiegand",NULL);

This is not the whole driver, but this is the actual part that deals with the IRQ. If someone see a problem in the code, or can suggest a way to know why I lose 4 interrupts, please reply. I'm stuck on this for hours... :(

Thanks. Ramon.

like image 870
stdcall Avatar asked Aug 17 '11 11:08

stdcall


2 Answers

I assume you are triggering your interrupts with an external system (maybe a microcontroller or something that can toggle the GPIOS). Since I do not see a real ack of the interrupt, I assume the external system does not wait for the interrupt to be handled to maybe trigger a new one.

printk is a very slow function and that's why you can miss some interrupts: a new one can be triggered while you are still handling the previous one.

So I would advise not to use printk in the handler. If you want to achieve something like this, it would be better to use a tasklet or a workqueue as the bottom half of the interrupt handler.

I can only recommend the reading of the Chapter 10 of Linux Device Drivers.

Oh and by the way, your IRQ handler should not return 0 but IRQ_HANDLED.

like image 66
Longfield Avatar answered Oct 31 '22 12:10

Longfield


Ok, actually, the problem is that I used the GPIO pins, while the GPIO pins don't support IRQF_TRIGGER_FALLING flag, which is exactly what I need. so probably, the interrupt handler doesn't recognize the signal correctly. I found out that I need to use the external pins for IRQF_TRIGGER_FALLING enables IRQ's.

like image 31
stdcall Avatar answered Oct 31 '22 14:10

stdcall