GPIO IRQ в Embedded Linux на базе ARM

Я пытаюсь запрограммировать GPIO IRQ на оценочной плате AT91SAM9M10-EKES. Я успешно зарегистрировал IRQ, и IRQ работает. Однако некоторые прерывания пропускаются. Я отправляю 26, а получаю только 22.

Код:

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);

Это не весь драйвер, но это фактическая часть, связанная с IRQ. Если кто-то увидит проблему в коде или может предложить способ узнать, почему я теряю 4 прерывания, пожалуйста, ответьте. Я застрял на этом в течение нескольких часов... :(

Спасибо. Рамон.


person stdcall    schedule 17.08.2011    source источник


Ответы (2)


Я предполагаю, что вы запускаете свои прерывания с помощью внешней системы (возможно, микроконтроллера или чего-то, что может переключать GPIOS). Поскольку я не вижу реального подтверждения прерывания, я предполагаю, что внешняя система не ждет обработки прерывания, чтобы, возможно, вызвать новое.

printk — очень медленная функция, и поэтому вы можете пропустить некоторые прерывания: новое может быть запущено, пока вы все еще обрабатываете предыдущее.

Поэтому я бы посоветовал не использовать printk в обработчике. Если вы хотите добиться чего-то подобного, было бы лучше использовать тасклет или рабочую очередь в качестве нижней половины обработчика прерывания.

Я могу только порекомендовать прочитать главу 10 Драйверы устройств Linux.

Да, и кстати, ваш обработчик IRQ должен возвращать не 0, а IRQ_HANDLED.

person Longfield    schedule 18.08.2011
comment
@Longfield: Не могли бы вы ответить на этот stackoverflow.com/questions/24608817/ ? - person Sagar Jain; 07.07.2014

Хорошо, на самом деле проблема в том, что я использовал выводы GPIO, а выводы GPIO не поддерживают флаг IRQF_TRIGGER_FALLING, а это именно то, что мне нужно. поэтому, вероятно, обработчик прерывания неправильно распознает сигнал. Я обнаружил, что мне нужно использовать внешние контакты для IRQF_TRIGGER_FALLING, который включает IRQ.

person stdcall    schedule 18.08.2011
comment
Привет у меня похожая проблема. Не могли бы вы изучить stackoverflow.com/questions/24608817/ - person Sagar Jain; 07.07.2014