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
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
Post a Comment