2017-08-14 6 views
1

Ich lerne gerade von Derek Molloys Beispiel in seinem Buch "Exploring Raspberry Pi - Schnittstelle zur realen Welt mit Embedded Linux". Ich nahm das Beispiel unter Listing 16-3, das konnte ich leider nicht online finden.Wie drei IRQ-Handler in einem Kernel-Modul enthalten?

Das Beispiel enthält einen Kernelmodulcode für einen einzelnen Interrupt. Es liest ein Signal von einer Taste am GPIO 17 und sendet dann einen Interrupt, um eine LED an GPIO 27 einzuschalten. Das Buch verwendet die Standard-GPIO-Pin-Nummerierung, also mache ich das gleiche.

Was ich tun möchte, ist die Änderung des Codes, um 2 andere Taste-LED-Paare zu enthalten. Ich möchte es, wie dies zu tun:

  • GPIO 17 Ein-/Ausschalten GPIO 23
  • GPIO 27 Ein-/Ausschalten GPIO 24
  • GPIO 22 ein-/auszuschalten GPIO 25

Dies ist der modifizierte Code, den ich verwende.

static unsigned int gpioDevice1 = 17; 
static unsigned int gpioDevice2 = 27; 
static unsigned int gpioDevice3 = 22; 
static unsigned int gpioButton1 = 24; 
static unsigned int gpioButton2 = 23; 
static unsigned int gpioButton3 = 25; 
static unsigned int irqNumber1On; 
static unsigned int irqNumber2On; 
static unsigned int irqNumber3On; 
static unsigned int buttonCounter1 = 0; 
static unsigned int buttonCounter2 = 0; 
static unsigned int buttonCounter3 = 0; 
static unsigned int totalCounter = 0; 
static bool devOn1 = 0; // Initial state of devices 
static bool devOn2 = 0; 
static bool devOn3 = 0; 

// prototype for the custom IRQ handler function, function below. Should I use IRQF_SHARED here? 

static irq_handler_t rpi3_gpio_irq_handler_1(unsigned int irq, void *dev_id, struct pt_regs *regs); 
static irq_handler_t rpi3_gpio_irq_handler_2(unsigned int irq, void *dev_id, struct pt_regs *regs); 
static irq_handler_t rpi3_gpio_irq_handler_3(unsigned int irq, void *dev_id, struct pt_regs *regs); 

/** LKM initialization function */ 

static int __init rpi3_gpio_init(void) { 
    int result1On = 0; 
    int result2On = 0; 
    int result3On = 0; 
    printk(KERN_INFO "GPIO_TEST: Initializing the GPIO_TEST LKM\n"); 

    /* GPIO validation on the three devices */ 
    if (!gpio_is_valid(gpioDevice1) || !gpio_is_valid(gpioDevice2) || !gpio_is_valid(gpioDevice3)) { 
     printk(KERN_INFO "GPIO_TEST: invalid GPIO for Devices\n"); 
     return -ENODEV; //wouldn't using ENXIO is more appropriate than ENODEV? 
    } 

    /* Configuring GPIO pins for the pairs */ 
    gpio_request(gpioDevice1, "sysfs"); // request LED GPIO 
    gpio_direction_output(gpioDevice1, devOn1); // set in output mode 
    gpio_export(gpioDevice1, false); // appears in /sys/class/gpio 
    // false prevents in/out change 

    gpio_request(gpioDevice2, "sysfs"); 
    gpio_direction_output(gpioDevice2, devOn2); 
    gpio_export(gpioDevice2, false); 

    gpio_request(gpioDevice3, "sysfs"); 
    gpio_direction_output(gpioDevice3, devOn3); 
    gpio_export(gpioDevice3, false); 

    gpio_request(gpioButton1, "sysfs"); // set up gpioButton1 
    gpio_direction_input(gpioButton1); // set up as input 
    gpio_set_debounce(gpioButton1, 200); // debounce delay of 200ms to avoid erratic and uncontrolled interrupt 
    gpio_export(gpioButton1, false); // appears in /sys/class/gpio 

    gpio_request(gpioButton2, "sysfs"); 
    gpio_direction_input(gpioButton2); 
    gpio_set_debounce(gpioButton2, 200); 
    gpio_export(gpioButton2, false); 

    gpio_request(gpioButton3, "sysfs"); 
    gpio_direction_input(gpioButton3); 
    gpio_set_debounce(gpioButton3, 200); 
    gpio_export(gpioButton3, false); 

    printk(KERN_INFO "GPIO_TEST: button1 value is currently: %d\n", gpio_get_value(gpioButton1)); 
    irqNumber1On = gpio_to_irq(gpioButton1); // map GPIO to IRQ number 189? 
    printk(KERN_INFO "GPIO_TEST: button1 mapped to IRQ: %d\n", irqNumber1On); 

    printk(KERN_INFO "GPIO_TEST: button2 value is currently: %d\n", gpio_get_value(gpioButton2)); 
    irqNumber2On = gpio_to_irq(gpioButton2); // map GPIO to IRQ number 190? 
    printk(KERN_INFO "GPIO_TEST: button2 mapped to IRQ: %d\n", irqNumber2On); 

    printk(KERN_INFO "GPIO_TEST: button3 value is currently: %d\n", gpio_get_value(gpioButton3)); 
    irqNumber3On = gpio_to_irq(gpioButton3); // map GPIO to IRQ number 191? 
    printk(KERN_INFO "GPIO_TEST: button3 mapped to IRQ: %d\n", irqNumber3On); 

    /* Interrupt lines when tactile button is pressed */ 
    result1On = request_irq(irqNumber1On, // interrupt number requested 
      (irq_handler_t) rpi3_gpio_irq_handler_1, // handler function 
      // TO DO: Insert IRQF_SHARED here? 
      IRQF_TRIGGER_RISING, // on rising edge (press, not release) 
      "rpi3_gpio_handler", // used in /proc/interrupts 
      NULL); // *dev_id for shared interrupt lines shouldn't be NULL 
    printk(KERN_INFO "GPIO_TEST: IRQ request result for device 1 is: %d\n", result1On); 
    return result1On; 

    result2On = request_irq(irqNumber2On, 
      (irq_handler_t) rpi3_gpio_irq_handler_2, 
      IRQF_TRIGGER_RISING, 
      "rpi3_gpio_handler", 
      NULL); 
    printk(KERN_INFO "GPIO_TEST: IRQ request result for device 2 is: %d\n", result2On); 
    return result2On; 

    result3On = request_irq(irqNumber3On, 
      (irq_handler_t) rpi3_gpio_irq_handler_3, 
      IRQF_TRIGGER_RISING, 
      "rpi3_gpio_handler", 
      NULL); 
    printk(KERN_INFO "GPIO_TEST: IRQ request result for device 3 is: %d\n", result3On); 
    return result3On; 
} 

static void __exit rpi3_gpio_exit(void) { 

    printk(KERN_INFO "GPIO_TEST: button 1 value is currently: %d\n", gpio_get_value(gpioButton1)); 
    printk(KERN_INFO "GPIO_TEST: button 1 was pressed %d times\n", buttonCounter1); 
    printk(KERN_INFO "GPIO_TEST: button 2 value is currently: %d\n", gpio_get_value(gpioButton2)); 
    printk(KERN_INFO "GPIO_TEST: button 2 was pressed %d times\n", buttonCounter2); 
    printk(KERN_INFO "GPIO_TEST: button 3 value is currently: %d\n", gpio_get_value(gpioButton3)); 
    printk(KERN_INFO "GPIO_TEST: button 3 was pressed %d times\n", buttonCounter3); 
    printk(KERN_INFO "GPIO_TEST: in total the buttons was pressed %d times\n", totalCounter); 

    gpio_set_value(gpioDevice1, 0); // turn the LED off 
    gpio_unexport(gpioDevice1); // unexport the LED GPIO 
    free_irq(irqNumber1On, NULL); // free the IRQ number, no *dev_id? 
    gpio_unexport(gpioButton1); // unexport the Button GPIO 
    gpio_free(gpioDevice1); // free the LED GPIO 
    gpio_free(gpioButton1); // free the Button GPIO 

    gpio_set_value(gpioDevice2, 0); 
    gpio_unexport(gpioDevice2); 
    free_irq(irqNumber2On, NULL); 
    gpio_unexport(gpioButton2); 
    gpio_free(gpioDevice2); 
    gpio_free(gpioButton2); 

    gpio_set_value(gpioDevice3, 0); 
    gpio_unexport(gpioDevice3); 
    free_irq(irqNumber3On, NULL); 
    gpio_unexport(gpioButton3); 
    gpio_free(gpioDevice3); 
    gpio_free(gpioButton3); 

    printk(KERN_INFO "GPIO_TEST: Goodbye from the LKM!\n"); 
} 

/** GPIO IRQ Handler functions */ 

static irq_handler_t rpi3_gpio_irq_handler_1(unsigned int irq, void *dev_id, struct pt_regs *regs) { 
    devOn1 = !devOn1; // invert the LED state 
    gpio_set_value(gpioDevice1, devOn1); // set LED accordingly 
    printk(KERN_INFO "GPIO_TEST: Interrupt! (button 1 is %d)\n", 
    gpio_get_value(gpioButton1)); 
    buttonCounter1++; 
    totalCounter++; // global counter 
    return (irq_handler_t) IRQ_HANDLED; // announce IRQ handled 
} 

static irq_handler_t rpi3_gpio_irq_handler_2(unsigned int irq, void *dev_id, struct pt_regs *regs) { 
    devOn2 = !devOn2; 
    gpio_set_value(gpioDevice2, devOn2); 
    printk(KERN_INFO "GPIO_TEST: Interrupt! (button 2 is %d)\n", 
    gpio_get_value(gpioButton2)); 
    buttonCounter2++; 
    totalCounter++; 
    return (irq_handler_t) IRQ_HANDLED; 
} 

static irq_handler_t rpi3_gpio_irq_handler_3(unsigned int irq, void *dev_id, struct pt_regs *regs) { 
    devOn3 = !devOn3; 
    gpio_set_value(gpioDevice3, devOn3); 
    printk(KERN_INFO "GPIO_TEST: Interrupt! (button 3 is %d)\n", 
    gpio_get_value(gpioButton3)); 
    buttonCounter3++; 
    totalCounter++; 
    return (irq_handler_t) IRQ_HANDLED; 
} 

module_init(rpi3_gpio_init); 
module_exit(rpi3_gpio_exit); 

Um die IRQ-Nummern erhalten ich gpio_to_irq() wie im Beispiel zu verwenden, weil ich nicht weiß, welche Werte eine gültige Zahl sein würden.

Das erste Paar funktionierte gut, aber die anderen Paare funktionieren nicht, egal wie oft ich die Tasten drückte. Wenn ich die IRQ-Nummern mit cat /proc/interrupts geprüft I got this display in the terminal. I've inverted the colors to make it easier to skim through

Es scheint, dass nur der erste eine IRQ-Nummer erhalten, die ist. Hypothetisch sollten die anderen zwei wahrscheinlich und bekommen, aber sie sind nicht da.

Die printk() Funktionen auch angezeigt, nur die Linien für irqnumber1On, während die Leitungen für irqnumber2On und irqnumber3On nicht erschienen.

Ich gab die Interrupts NULL dev_id, weil ich nicht weiß, wie ID für Schaltflächen geben/lesen. Ich versuchte Random-Nummer-Kombinationen, wie , und aber Terminal warning: passing argument 5 of 'request_irq' makes pointer from integer without a cast.

Also, was habe ich hier schrecklich falsch gemacht? Ich stecke eine ganze Weile hier fest. Sollte ich versuchen, IRQF_SHARED zu verwenden? Aber es benötigt bestimmte dev_id für jeden Interrupt (oder Tasten in diesem Fall). Mein Neuling denkt, dass es so ziemlich unmöglich ist.

PS: Ich weiß, der Code sieht chaotisch und schrecklich aus, aber bitte bitte mit mir.

PPS: Ich könnte einen Teil des Codes löschen, wenn nötig.

Antwort

1

beliebiger Code nach dieser Aussage:

return result1On; 

wird nie ausgeführt werden.

, dass die beiden anderen Taste Interrupts bedeutet nie

+0

Oops behandelt werden, verpasste ich diesen Punkt. Ich werde dann versuchen, eine Struktur zu verwenden. Ich werde wiederkommen, nachdem ich es versucht habe. –

Verwandte Themen