2013-04-08 2 views
4

Я сделал некоторый эксперимент с платой разработки cortex-A9. Я использовал gpio_to_irq(), чтобы получить irq num, и я запросил irq и написал с ним небольшой драйвер, это было 196 в syslog. И я добавил несколько printks в asm_do_IRQ. Когда я вызвал прерывание gpio, драйвер работает нормально, но irq num в asm_do_IRQ - 62. Я не могу понять. Почему номер irq отличается от того, который я запрашиваю? Драйвер выглядит следующим образом:IRQ в функции ядра asm_do_IRQ() отличается от той, которую я запрашиваю в модуле

#include <linux/module.h> 
    #include <linux/interrupt.h> 
    #include <linux/irq.h> 
    #include <linux/gpio.h> 

    #define GPIO_N 36  //gpio number 

    int flag = 0; 

    static irqreturn_t handler(int irq,void *dev_id) 
    { 
      printk("hello world hahahahahhahahah \n\n"); 
      return 0; 
    } 

    static int __init gpio_test_init(void) 
    { 
      if(gpio_request_one(GPIO_N,GPIOF_DIR_IN,"some test")<0) 
      { 
        printk(KERN_ERR "Oops! BAD! BAD! BAD!\n\n"); 
        return 0; 
      } 

      int irq,irq2; 
      irq = OMAP_GPIO_IRQ(TEST_GPIO); 
      printk("irq : %d \n",irq,irq2); 
      // .................. 
      // irq : 196 in dmesg 
      //...................... 
      set_irq_type(irq,IRQ_TYPE_EDGE_FALLING); 
      enable_irq(gpio_to_irq(GPIO_N)); 
      int err; 
      // request the irq ... 
      if((err = request_irq(irq,&handler,0,NULL,NULL))<0) 
      { 
        printk("err : %d\n",err); 
        return 0; 
      } 
      printk("gpio test init success!\n"); 
      flag = 1; 
      return 0; 
    } 
    static void __exit gpio_test_exit(void) 
    { 
      int irq = gpio_to_irq(TEST_GPIO); 
      if(flag == 1)free_irq(irq,NULL); 
      gpio_free(TEST_GPIO); 
      printk("gpio test exit byebye!\n"); 
    } 

    module_init(gpio_test_init); 
    module_exit(gpio_test_exit); 
    MODULE_LICENSE("GPL"); 

asm_do_IRQ в арку/руки/ядра/irq.c

asmlinkage void __exception_irq_entry 
    asm_do_IRQ(unsigned int irq, struct pt_regs *regs) 
    { 
      struct pt_regs *old_regs = set_irq_regs(regs); 
      printk("the irq : %d\n",irq); 
      //............... 
      // I get 62 here 
      //............... 
      irq_enter(); 

      /* 
      * Some hardware gives randomly wrong interrupts. Rather 
      * than crashing, do something sensible. 
      */ 
      if (unlikely(irq >= nr_irqs)) { 
        if (printk_ratelimit()) 
          printk(KERN_WARNING "Bad IRQ%u\n", irq); 
        ack_bad_irq(irq); 
      } else { 
        generic_handle_irq(irq); 
      } 

      /* AT91 specific workaround */ 
      irq_finish(irq); 

      irq_exit(); 

      set_irq_regs(old_regs); 

    } 

ответ

4

Это наблюдение, вероятно, связано с отображением между физическими и виртуальными номерами прерываний. Числа, отображаемые в вашем драйвере, являются виртуальными номерами IRQ, действительными только при использовании общей подсистемы обработки прерываний linux. Номер прерывания в asm_do_IRQ будет физическим номером прерывания, предоставляемым тканью прерывания ядра.

Я считаю, что процессоры OMAP поддерживают прерывания на выводах GPIO. Обычно это реализуется, чтобы выделить одну линию IRQ для банка входов GPIO, например 32 бита. Когда прерывание происходит в любом из GPIO, эта строка IRQ будет активирована. Вероятно, это число 62 на вашем процессоре. Если вы посмотрите в руководстве для своего процессора, вы должны увидеть, что IRQ 62 соответствует прерыванию в банке GPIO.

Теперь подсистема Linux GPIO позволит вам назначить обработчик прерываний любому из GPIO, предоставляя вам сопоставление от номера IRQ Linux до физического номера IRQ. Номер linux irq в вашем случае - 196. Подсистема GPIO настроена на обработку всех прерываний GPIO (например, прерывание 62), считывает регистр GPIO, чтобы определить, какой из битов GPIO в банке мог вызвать прерывание, а затем вызывает обработчик прерываний, назначенный с помощью request_irq.

Вот основной поток управления для прерывания GPIO:

  1. Изменение происходит на прерывание в банке GPIO. IRQ 62 повышается.
  2. asm_do_IRQ работает на IRQ 62. Подсистема GPIO зарегистрирована для обработки IRQ 62 кодом инициализации платформы.
  3. Подсистема GPIO считывает регистры GPIO и определяет, что бит X GPIO вызвал прерывание. Он вычисляет сопоставление от бит X к виртуальному номеру IRQ в Linux, в этом случае 196.
  4. Обработчик прерываний GPIO затем вызывает функцию generic_handle_irq с 196, которая вызывает ваш обработчик прерываний.

Существует, как правило статического отображение определяется платформой между виртуальными номерами IRQ и физическими номерами прерываний. Чтобы увидеть это отображение,

  • позволяют CONFIG_VIRQ_DEBUG на ядрах старше, чем Linux-3.4, или
  • позволяют CONFIG_IRQ_DOMAIN_DEBUG на новых ядрах.

Затем посмотрите файл irq_domain_mapping debugfs. Например. на PowerPC:

# mount -t debugfs none /sys/kernel/debug 
# cat /sys/kernel/debug/irq_domain_mapping 
irq hwirq chip name  chip data domain name 
    16 0x00009 IPIC    0xcf801c80 /[email protected]/[email protected] 
    18 0x00012 IPIC    0xcf801c80 /[email protected]/[email protected] 
    19 0x0000e IPIC    0xcf801c80 /[email protected]/[email protected] 
    20 0x0000f IPIC    0xcf801c80 /[email protected]/[email protected] 
    21 0x00010 IPIC    0xcf801c80 /[email protected]/[email protected] 
    77 0x0004d IPIC    0xcf801c80 /[email protected]/[email protected] 
+0

+1 Вы можете использовать термин * virtual * и * physical * IRQ.Тем не менее, это больше похоже на контроллер IRQ * master/parent * и контроллер IRQ * подчиненного/дочернего *. Поскольку Linux использует только одно число и карты * master *, соответствуют 1-1. Для других * прикованных * IRQ, обычно начинаются со смещения. Это раскалывание волос, и, вероятно, любой из способов взглянуть на него приводит вас к одной и той же точке. Что еще более важно, 'asm_do_IRQ' связан только с контроллером IRQ * master/parent *. –

+0

@ бесшумный шум, то есть 62 - это irq num в главном/родительском контроллере IRQ, а 196 - irq num на подчиненном/дочернем контроллере IRQ. – goodjesse

+0

@ goodjesse Точно. Описание Остина верное, но * master/slave * может лучше соответствовать структуре кода; или, по крайней мере, еще один способ понять одно и то же. Модуль GPIO, вероятно, имеет несколько регистров, которые действуют как контроллер мини-прерываний. –

Смежные вопросы