GPIO Kernel driver
the goal of this project is just to implement a simple module that registers an interrupt handler which keeps track of how many interrupts it receives. On the Beagleboard, we can use the User buttons as source of interrupts. Make sure you properly change the multiplexing configuration of the associated pad to configure it as a GPIO. To show off that the interrupt handler is working, switch on an LED whenever the button is pressed and switch it off when the button is released. In your module init function, register your handler on the GPIO’s interrupt line, which is defined by a irq module parameter.
C language :
#include <linux/kernel.h> #include <linux/console.h> #include <linux/init.h> #include <linux/time.h> #include <asm/string.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/signal.h> #include <linux/sched.h> #include <linux/workqueue.h> #define USE_GPIO #define USE_INTERRUPT static void mykmod_work_handler (struct work_struct *myWorkQueue); static struct workqueue_struct *myWorkQueue = 0; static DECLARE_DELAYED_WORK (mykmod_work, mykmod_work_handler); static unsigned long onesec; #ifdef USE_INTERRUPT static void workInInte (void) { printk ("***Interrupt detected***\n"); queue_delayed_work (myWorkQueue, &mykmod_work, onesec); } static irqreturn_t interruption (int irq, void *dev_id) { workInInte (); return IRQ_HANDLED; } #endif static void mykmod_work_handler (struct work_struct *myWorkQueue) { int i = 0; printk ("***myWorkQueue flash time:200ms***\n"); for (i = 0; i < 6; i++) { gpio_set_value (150, (i % 2)); mdelay (200); } } static int __init mykmod_init (void) { int ret; printk ("*******************************************************\n"); printk ("*Hello Mras2an*\n"); printk ("*******************************************************\n\n"); #ifdef USE_GPIO printk ("***LED D7***\n"); /*set a LED D7 on beagleboard*/ gpio_request (150, "LED D7"); gpio_direction_output (150, 1); gpio_set_value (150, 0); #endif #ifdef USE_INTERRUPT /*use interrupt */ if (gpio_is_valid (4) == 0) { printk ("you can't use the GPIO\n"); } else { printk ("you can use the GPIO\n"); } gpio_request (4, "IntQu"); gpio_direction_input (4); gpio_get_value (4); if ((ret = request_irq (gpio_to_irq (4), interruption, IRQF_TRIGGER_FALLING, "IntQu", NULL)) != 0) { printk (KERN_DEBUG "erreur request_irq : %d \n", ret); } else { printk ("***Interrupt : Ok***\n"); } #endif /*use woekqueue */ onesec = msecs_to_jiffies (100); printk ("myWorkQueue init"); if (!myWorkQueue) { myWorkQueue = create_singlethread_workqueue ("myWorkQueue"); } return 0; } static void __devexit mykmod_exit (void) { struct timeval *start = NULL; start = kmalloc (sizeof (start), GFP_ATOMIC); #ifdef USE_GPIO gpio_free (150); #endif #ifdef USE_INTERRUPT free_irq (gpio_to_irq (4), NULL); gpio_free (4); #endif do_gettimeofday (start); kfree (start); if (myWorkQueue) { destroy_workqueue (myWorkQueue); } printk ("myWorkQueue exit,\nfree GPIO,\nfree interrupt.\n"); printk ("\nstart->tv_usec:%ld \n", start->tv_usec); printk ("start->tv_sec:%ld \n", start->tv_sec); printk ("*********************************************************\n"); printk ("*Goodbye Mras2an*\n"); printk ("*********************************************************\n\n"); } /************************************************************* hello.c *************************************************************/ module_init (mykmod_init); module_exit (mykmod_exit); MODULE_LICENSE ("GPL"); MODULE_DESCRIPTION ("test module"); MODULE_AUTHOR ("Mras2an"); |
Makefile :
obj-m := hello_version.o KDIR := /kernel/linux-omap-2.6 PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules |
KDIR: it's your kernel path.
You can compile the code with make command, copy "helo.ko" on your board and mount the driver with "insmod helo.ko" commande.
Sujet: GPIO Kernel driver
Aucun message nʼ a été trouvé.