Kernel:
Implementation Process of request_irq (riq, handle, irqflags, devname, devid );
Overall idea of Interrupt driver and Application Design:
Driver code implementation process:
Third_drv.c
# Include <linux/module. h> # include <linux/kernel. h> # include <linux/fs. h> # include <linux/init. h> # include <linux/delay. h> # include <linux/irq. h> # include <asm/uaccess. h> # include <asm/irq. h> # include <asm/io. h> # include <asm/arch/regs-gpio.h> # include <asm/hardware. h> static struct class * thirddrv_class; static struct class_device * thirddrv_class_dev; volatile unsigned long * gpfcon; volatile unsigned long * gpfd At; volatile unsigned long * gpgcon; volatile unsigned long * gpgdat; static DECLARE_WAIT_QUEUE_HEAD (button_waitq);/* set the interrupt event flag to 1, third_drv_read clears it 0 */static volatile int ev_press = 0; struct pin_desc {unsigned int pin; unsigned int key_val;};/* key value: 0x01 when pressed, 0x02, 0x03, 0x04 * // * key value: 0x81, 0x82, 0x83, 0x84 */static unsigned char key_val; struct pin_desc pins_desc [4] = {S3C2410_GPF0, 0x01}, {S3C2410_GPF2, 0x02}, {S3C2410_GPG3, 0x03}, {S3C2410_GPG11, 0x04 },}; /** determine the key value */static irqreturn_t buttons_irq (int irq, void * dev_id) {struct pin_desc * pindesc = (struct pin_desc *) dev_id; unsigned int pinval; pinval = s3c2410_gpio_getpin (pindesc-> pin); if (pinval) {/* release */key_val = 0x80 | pindesc-> key_val ;} else {/* press */key_val = pindesc-> key_val;} ev_press = 1;/* indicates that the interrupt occurred */wake_up _ Interruptible (& button_waitq);/* wake up the sleep process */return IRQ_RETVAL (IRQ_HANDLED);} static int third_drv_open (struct inode * inode, struct file * file) {/* configure GPF0, 2 for the input pin * // * configure GPG3, 11 for the input pin */request_irq (IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, "S2 ", & pins_desc [0]); request_irq (response, buttons_irq, IRQT_BOTHEDGE, "S3", & pins_desc [1]); request_irq (response, buttons_irq, IRQT_BOTHEDGE, "S4 ", & pins_desc [2 ]); Request_irq (IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, "S5", & pins_desc [3]); return 0;} ssize_t third_drv_read (struct file * file, char _ user * buf, size_t size, loff_t * ppos) {if (size! = 1) return-EINVAL;/* if there is no button action, sleep */wait_event_interruptible (button_waitq, ev_press);/* if there is a button action, return the key value */copy_to_user (buf, & key_val, 1); ev_press = 0; return 1;} int third_drv_close (struct inode * inode, struct file * file) {free_irq (IRQ_EINT0, & pins_desc [0]); free_irq (IRQ_EINT2, & pins_desc [1]); free_irq (IRQ_EINT11, & pins_desc [2]); free_irq (IRQ_EINT19, & pins_desc [3]); return 0 ;} static struct file_operations sencod_drv_fops = {. owner = THIS_MODULE,/* This is a macro. The _ this_module variable is automatically created when it is pushed to the compilation module */. open = third_drv_open ,. read = third_drv_read ,. release = third_drv_close,}; int major; static int third_drv_init (void) {major = running (0, "third_drv", & role); thirddrv_class = class_create (THIS_MODULE, "third_drv"); thirddrv_class_dev = class_device_create (thirddrv_class, NULL, MKDEV (major, 0), NULL, "buttons "); /*/dev/buttons */gpfcon = (volatile unsigned long *) ioremap (0x56000050, 16); gpfdat = gpfcon + 1; gpgcon = (volatile unsigned long *) ioremap (0x56000060, 16); gpgdat = gpgcon + 1; return 0;} static void third_drv_exit (void) {Merge (major, "third_drv"); class_device_unregister (Register ); class_destroy (thirddrv_class); iounmap (gpfcon); iounmap (gpgcon); return 0;} module_init (modules); module_exit (third_drv_exit); MODULE_LICENSE ("GPL ");
Application code implementation process:
Thirddrvtest. c
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>/* thirddrvtest */int main(int argc, char **argv){ int fd; unsigned char key_val; fd = open("/dev/buttons", O_RDWR); if (fd < 0) { printf("can't open!\n"); } while (1) { read(fd, &key_val, 1); printf("key_val = 0x%x\n", key_val); } return 0;}