Linux key interrupt driver-S3C2440

Source: Internet
Author: User
Driver
# Include <Linux/module. h> # include <Linux/init. h> # include <Linux/types. h >#include <Linux/kdev_t.h> # include <Linux/kernel. h> // you can use the ptintk function # include <Linux/Fs. h> # include <Linux/interrupt. h> // The interrupt-related header file # include <Linux/cdev. h> // register character devices # include <Linux/err. h> // error check function # include <Linux/slab. h> // related to memory allocation # include <Linux/sched. h> // The interrupt-related header file # include <ASM/Io. h> // operate the IO port # include <Linux/Wait. h> // waiting queue # include <ASM/uaccess. h> // User and kernel space data copy # include <ASM/ARCH/regs-gpio.h> // I/O port Register address and usage (input, output, interrupt or others) # include <ASM/ARCH/regs-irq.h> // interrupt-related registers # include <ASM/arch-s3c2410/irqs. h> // definition of the platform-related interrupt number # include <Linux/delay. h> // time delay function # define key_major 234 // defines the master device number # define key_minor 0 // defines the next device number # define device_name "key_interrupt"/static struct cdev * key_cdev; // static dev_t dev_num; static volatile int key_flags = 0; // declare_wait _ Queue_head (Queue); // initialize the wait queue static volatile int key_value [] = {1, 2, 4}; // press the key value static volatile int key_press = 0; // record the key that was pressed static dev_t dev_num; // The dev_t of the device number indicates static struct cdev * key_cdev; struct key_irq_description {unsigned int IRQ; unsigned long flags; const char * dev_name;}; struct key_irq_description key_irq [] ={{ irq_eint0, sa_interrupt, "key" },{ signature, sa_interrupt, "key" },{ signature, sa_interrupt, "key" },{ Irq_eint4, sa_interrupt, "key" },};/* interrupt processing function */static irqreturn_t key_interrupt (int irq, void * dev_id, struct pt_regs * regs) {__ raw_writel (_ raw_readl (s3c2410_srcpnd) & 0 xffffffda, s3c2410_srcpnd); // clear srcpnd 0 2 3 4 (this is important) mdelay (1 ); key_press = * (int *) dev_id; // pay the key value to key_presskey_flags = 1; // set the queue sign to wake_up_interruptible (& Queue ); // wake up Wait queue return irq_handled;}/* only apply for interruption here, which can save interrupted Resources */static int key_open (Struct inode * inode, struct file * filp) {printk ("now in key_open \ n"); int ret; int I; for (I = 0; I <sizeof (key_irq) /sizeof (key_irq [0]); I ++) {ret = request_irq (key_irq [I]. IRQ, key_interrupt, key_irq [I]. flags, key_irq [I]. dev_name, (void *) & key_value [I]); // request to interrupt printk ("Please IRQ \ n"); If (RET) break;} If (RET) {printk ("now at free_irq \ n"); I --; For (; I> = 0; I --) {free_irq (key_irq [I]. IRQ, (void *) & key_value [I]); Return-ebusy ;}} Return 0;}/* release interruption when related resources are not used */static int key_close (struct inode * inode, struct file * filp) {int I; for (I = 0; I <sizeof (key_irq)/sizeof (key_irq [0]); I ++) {free_irq (key_irq [I]. IRQ, (void *) & key_value [I]);} return 0 ;} /* Copy data from the kernel space to the user control */static ssize_t key_read (struct file * filp, char _ User * Buf, size_t count, loff_t * OFFP) {unsigned long err; wait_event_interruptible (queue, key_flags); // enable the waiting queue key_flags = 0; // when K When ey_flags = 1, the waiting queue err = copy_to_user (BUF, (const void *) & key_press, count) can be released; // note that the method key_press = 0; return err? -Efault: 0;} static struct file_operations key_fops = {. owner = this_module ,. read = key_read ,. open = key_open ,. release = key_close,};/* fill in the cdev structure */static void key_cdev_setup (void) {int err; cdev_init (key_cdev, & key_fops ); // initialize the allocated structure key_cdev-> owner = this_module; // set the owner field key_cdev-> Ops = & key_fops; err = cdev_add (key_cdev, dev_num, 1 ); // inform the kernel of the structure information if (is_err (& ERR) {// check whether the returned pointer is an error code printk (kern_notice "error % d add Ing key_interrupt ", err) ;}/ * initialization register */static void initbutton (void) {__ raw_writel (_ raw_readl (s3c2410_gpfcon )&(~ (3 <8) | (3 <6) | (3 <4) | (3 <0) | (2 <8) | (2 <6) | (2 <4) | (2 <0), s3c2410_gpfcon); // gpf2, 0, 3, 4 set Eint _ raw_writel (_ raw_readl (s3c2410_extint0 )&(~ (7 | (7 <8) | (7 <12) | (7 <16), s3c2410_extint0 ); _ raw_writel (_ raw_readl (s3c2410_extint0) | (0 | (0 <8) | (0 <12) | (0 <16 ))), s3c2410_extint0); // set eint0, 2, 3, 4 falling edge int _ raw_writel (_ raw_readl (s3c2410_eintpend) | (1 <4), s3c2410_eintpend ); // clear Eint 4 _ raw_writel (_ raw_readl (s3c2410_eintmask )&(~ (1 <4), s3c2410_eintmask); // enable Eint 4}/* module initialization function, assign device numbers, initialize registers, allocate memory for the cdev structure and initialize the cdev structure */static int _ init key_init (void) {int ret; initbutton (); // initialize the relevant register if (key_major) {dev_num = mkdev (key_major, key_minor); ret = primary (dev_num, 1, device_name); // statically assigned device ID} else {ret = alloc_chrdev_region (& dev_num, key_minor, 1, device_name); // dynamically allocate the device number} If (Ret <0) {printk (kern_warning "key: Can't Get key_majo R % d \ n ", key_major); return ret;} key_cdev = kmalloc (sizeof (struct cdev), gfp_kernel); // allocate memory for the cdev structure if (! Key_cdev) {printk ("Can't get this ram \ n"); ret =-enomem;} memset (key_cdev, 0, sizeof (struct cdev )); // key_cdev_setup () is cleared in the memory area of the cdev structure; // register the device structure cdevreturn 0;}/* the module exits the function, the execution sequence of internal functions must be the opposite to that of module initialization */static void _ exit key_exit (void) {cdev_del (key_cdev); // Delete the cdev structure kfree (key_cdev ); // release the allocated memory unregister_chrdev_region (dev_num, 1); // release the device number} module_init (key_init); module_exit (key_exit); module_license ("GPL "); module_author ("lizhibin"); module_description ("key and interrupt ");

Test procedure
#include <stdio.h>  #include <stdlib.h>  #include <unistd.h>  #include <sys/ioctl.h>     int main(int argc,char **argv)  {      int i;      int ret;      int fd;      char press_cnt;      printf("Hi I am come in\n");    sleep(5);    printf("5 seconds after\n");      fd=open("/dev/key_interrupt",0);    printf("key_interrupt by open\n");      if(fd<0)  {          printf("Can't open /dev/interrupt \n");          return -1;      }       while(1) {          printf("come in while(1)\n");        ret = read(fd,&press_cnt,sizeof(press_cnt));          if(ret<0)  {              printf("read err !\n");              continue;          }              if(press_cnt)                  printf("Key%d has been pressed  \n",press_cnt);             }                }

After compilation, download it to the Development Board, use insmod to load the driver, create a device node for mknod, run the test program, and press the button to view the result on dnw.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.