c - How to include three IRQ handlers in one kernel module? -


i'm learning derek molloy's example in book "exploring raspberry pi - interfacing real world embedded linux". took example @ listing 16-3, unfortunately not found online.

the example contains kernel module code single interrupt. read signal button @ gpio 17 , send interrupt turn on led @ gpio 27. book uses default gpio pin numbering, same.

what want modifying code include 2 other button-led pairs. want this:

  • gpio 17 turns on/off gpio 23
  • gpio 27 turns on/off gpio 24
  • gpio 22 turns on/off gpio 25

this modified code use.

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 custom irq handler function, function below. should 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 gpio_test lkm\n");      /* gpio validation on 3 devices */     if (!gpio_is_valid(gpiodevice1) || !gpio_is_valid(gpiodevice2) || !gpio_is_valid(gpiodevice3)) {         printk(kern_info "gpio_test: invalid gpio devices\n");         return -enodev; //wouldn't using enxio more appropriate enodev?     }      /* configuring gpio pins 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 gpiobutton1     gpio_direction_input(gpiobutton1); // set input     gpio_set_debounce(gpiobutton1, 200); // debounce delay of 200ms avoid erratic , 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 currently: %d\n", gpio_get_value(gpiobutton1));     irqnumber1on = gpio_to_irq(gpiobutton1); // map gpio irq number 189?     printk(kern_info "gpio_test: button1 mapped irq: %d\n", irqnumber1on);      printk(kern_info "gpio_test: button2 value currently: %d\n", gpio_get_value(gpiobutton2));     irqnumber2on = gpio_to_irq(gpiobutton2); // map gpio irq number 190?     printk(kern_info "gpio_test: button2 mapped irq: %d\n", irqnumber2on);      printk(kern_info "gpio_test: button3 value currently: %d\n", gpio_get_value(gpiobutton3));     irqnumber3on = gpio_to_irq(gpiobutton3); // map gpio irq number 191?     printk(kern_info "gpio_test: button3 mapped irq: %d\n", irqnumber3on);      /* interrupt lines when tactile button pressed */     result1on = request_irq(irqnumber1on, // interrupt number requested             (irq_handler_t) rpi3_gpio_irq_handler_1, // handler function             // do: insert irqf_shared here?             irqf_trigger_rising, // on rising edge (press, not release)             "rpi3_gpio_handler", // used in /proc/interrupts             null); // *dev_id shared interrupt lines shouldn't null     printk(kern_info "gpio_test: irq request result 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 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 device 3 is: %d\n", result3on);     return result3on; }  static void __exit rpi3_gpio_exit(void) {      printk(kern_info "gpio_test: button 1 value currently: %d\n", gpio_get_value(gpiobutton1));     printk(kern_info "gpio_test: button 1 pressed %d times\n", buttoncounter1);     printk(kern_info "gpio_test: button 2 value currently: %d\n", gpio_get_value(gpiobutton2));     printk(kern_info "gpio_test: button 2 pressed %d times\n", buttoncounter2);     printk(kern_info "gpio_test: button 3 value currently: %d\n", gpio_get_value(gpiobutton3));     printk(kern_info "gpio_test: button 3 pressed %d times\n", buttoncounter3);     printk(kern_info "gpio_test: in total buttons pressed %d times\n", totalcounter);      gpio_set_value(gpiodevice1, 0); // turn led off     gpio_unexport(gpiodevice1); // unexport led gpio     free_irq(irqnumber1on, null); // free irq number, no *dev_id?     gpio_unexport(gpiobutton1); // unexport button gpio     gpio_free(gpiodevice1); // free led gpio     gpio_free(gpiobutton1); // free 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 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 led state     gpio_set_value(gpiodevice1, devon1); // set led accordingly     printk(kern_info "gpio_test: interrupt! (button 1 %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 %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 %d)\n",     gpio_get_value(gpiobutton3));     buttoncounter3++;     totalcounter++;      return (irq_handler_t) irq_handled; }  module_init(rpi3_gpio_init); module_exit(rpi3_gpio_exit); 

to irq numbers use gpio_to_irq() in example, because don't know values valid number.

the first pair worked well, other pairs won't work no matter how many times pushed buttons. when checked irq numbers cat /proc/interrupts i got display in terminal. i've inverted colors make easier skim through

it seems first 1 irq number, 189. hypothetically, other 2 should 190 , 191, not there.

the printk() functions displayed lines irqnumber1on, while lines irqnumber2on , irqnumber3on did not appear.

i gave interrupts null dev_id because don't know how give/read id buttons. tried random number combinations, 500, 505, , 550 terminal said warning: passing argument 5 of 'request_irq' makes pointer integer without cast.

so, did terribly wrong here? i'm stuck on quite while. should try using irqf_shared? needs particular dev_id each interrupt (or buttons in case). newbie mind think quite impossible so.

ps: know code looks messy , horrible, please bear me.

pps: erase part of code if deemed necessary.

any code after statement:

return result1on;  

will never executed.

that means other 2 button interrupts never handled


Comments

Popular posts from this blog

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

python Tkinter Capturing keyboard events save as one single string -

sql server - Why does Linq-to-SQL add unnecessary COUNT()? -