Linux drive interrupt mode get key value

Source: Internet
Author: User
Tags volatile

Linux drive interrupt mode get key value

--------------------------------------------------------------------------------------------------------------- ---------------------------------------

Recall the interrupt processing under the single-chip microcomputer
    1. Tell me which one was interrupted.
    2. Call handler function
    3. Clear Interrupt
--------------------------------------------------------------------------------------------------------------- ----------------------------------------
1. Interrupt Frame

Construction in Trap_int

Trap_intFunctions are some jump commands

B...

B...

b Vector_irq + stubs_offset; Vector_irq is the link address stubs_offset is the offset address


VECTOR_IRQ:
    1. Save the interrupted scene
    2. Asm_do_irq
    3. Recovery site
    4. 。。

ASM_DO_IRQ:

The processing of interrupts.


REQUEST_IRQ Registration Interruption

REQUEST_IRQ (irq,handle,irqflags,devname,dev_id)

1. Assigning irqaction structure

2, SETUP_IRQ (irq,action)

0. Assigning a irqaction structure

A, in IRQ_DESC[IRQ], action

B, Desc-and Chip->settype

C, DESC, chip-and startup/enable

Irq The hardware interrupt number to be requested +
Handle Is the interrupt handler that is registered with the system is a callback function, when the function is short, the system will call this function and pass the dev_id to it
Irqflags is the interrupt processing property

FREE_IRQ Uninstall Interrupt

FREE_IRQ (IRQ, dev_id)

1, out of the chain

2. No interruption

2. Write code 1, apply for IRQ

Here I want to special instructions: (to me such a small white in the use of REQUEST_IRQ this function encountered a problem is irq_eint1, Irq_eint4, Irq_eint2, irq_eint0 these four macros can not find, finally the reason to find. When I configured eclipse, there were minor problems with the path to the kernel tree.

Irqs.h This file is under /linux-2.6.30.4/arch/arm/mach-s3c2410/include this path. I thought this would have this path in mach-s3c2440. In fact, otherwise. Other pins are also defined in the 2410 path, which should be noted here.


REQUEST_IRQ (IRQ_EINT1,BUTTONS_IRQ, Irq_type_edge_both, "Key1", &pins_desc[0]); REQUEST_IRQ (IRQ_EINT4,buttons_ IRQ, Irq_type_edge_both, "Key2", &pins_desc[1]); REQUEST_IRQ (IRQ_EINT2,BUTTONS_IRQ, Irq_type_edge_both, "Key3", &PINS_DESC[2]); REQUEST_IRQ (IRQ_EINT0,BUTTONS_IRQ, Irq_type_edge_both, "Key4", &pins_desc[3]);

The Pins_desc here is an array of structural bodies

struct Pin_desc pins_desc[4] ={{s3c2410_gpf1,0x01},{s3c2410_gpf4,0x02},{s3c2410_gpf2,0x03},{s3c2410_gpf0,0x04},};

This array contains the four interrupt pins and the key values of the PIN.

The structure prototype is this:

struct pin_desc{unsigned int pin;unsigned int key_value;};

2, write interrupt processing function

static irqreturn_t buttons_irq (int irq,void *dev_id) {struct Pin_desc * Pindesc = (struct Pin_desc *) dev_id;unsigned int P Inval;pinval = S3c2410_gpio_getpin (Pindesc-pin); if (pinval)//Loosen {keyval = 0x80|pindesc->key_value;} Else{keyval = Pindesc->key_value;} Ev_press =1;//interrupt occurs wake_up_interruptible (&button_wait_q);p rintk ("button is pressed:%d \ n", IRQ); return irq_ HANDLED;}
Description

PINDESC: This structure realizes which button was pressed.
S3c2410_gpio_getpin: This function is a function provided by the kernel to obtain the current PIN's high and low level
Ev_press: Interrupt event flag. The Interrupt service program will reset him to the 1,read function 0

Wake_up_interruptible (&BUTTON_WAIT_Q); Wakes the dormant process and wakes up the process on the waiting queue, where button_wait_q is obtained through, for example, the following:

Static Declare_wait_queue_head (BUTTON_WAIT_Q); generate a wait queue header wait_queue_head_t, named button_wait_q

3. Change the Read function

ssize_t button_dev_read (struct file *file,char __user *buf,size_t size,loff_t *ppos) {if (size!=1) {return-einval;} /* Assume that there is no keystroke action occurring  on Sleep */wait_event_interruptible (button_wait_q,ev_press);/* Assume that a keystroke action occurs and return directly to */copy_to_user (BUF, &keyval,1); ev_press = 0;return 0;}

Of

Wait_event_interruptible (button_wait_q,ev_press); Suppose Ev_press is false. It will sleep.

ev_press = 0; After each reading, the event flag is zeroed.

4, filling file_operations structure body

static struct file_operations button_sdv_fops ={.owner = This_module,.open  = Button_dev_open,.read = Button_dev_ Read,.release = Button_dev_close,};

Among the Button_dev_close functions are:

int button_dev_close (struct inode* inode, struct file *file) {FREE_IRQ (irq_eint1,&pins_desc[0]); FREE_IRQ (irq_ EINT4,&PINS_DESC[1]); FREE_IRQ (irq_eint2,&pins_desc[2]); FREE_IRQ (irq_eint0,&pins_desc[3]); return 0;}

FREE_IRQ to release interrupts. Two parameters are required.


This code is changed on the basis of the previous key post.

Full Driver Code:

#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h > #include <asm/io.h> #include <linux/cdev.h> #include <linux/device.h> #include <linux/irq.h > #include <asm/uaccess.h> #include <asm/irq.h> #include <mach/regs-gpio.h> #include <mach/ irqs.h>//this in/opt/embedsky/linux-2.6.30.4/arch/arm/mach-s3c2410/include/mach path # include <linux/interrupt.h >module_license ("Dual BSD/GPL"); static struct class *buttondrv_class;static struct class_devices *buttondrv_class_ dev;/* */static Declare_wait_queue_head (BUTTON_WAIT_Q);/* Interrupt event Flag, interrupt service program will reset the 1,read function to set him 0*/static volatile int ev_press =0;volatile unsigned long *gpfcon = null;volatile unsigned long *gpfdat = null;static unsigned keyval;struct pin_desc{unsi gned int pin;unsigned int key_value;};/ * When the button is pressed: 0x01 0x02 0x03 0x04*//* When the button is released: 0x81 0x82 0x83 0x84*/struct pin_desc pins_desc[4] ={{s3c2410_gpf1,0x01},{s3c2410_ Gpf4,0x02},{s3c2410_gpf2,0x03},{s3c2410_gpf0,0x04},};/* * Determine 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)//Loosen {keyval = 0x80|pindesc- >key_value;} Else{keyval = Pindesc->key_value;} Ev_press =1;//interrupt occurs wake_up_interruptible (&button_wait_q);p rintk ("button is pressed:%d \ n", IRQ); return irq_ HANDLED;} The static int button_dev_open (struct inode *inode, struct file* file) {//Configure the PIN gpf0,1,2,4 for the key to the input pin REQUEST_IRQ (irq_eint1, BUTTONS_IRQ, Irq_type_edge_both, "Key1", &pins_desc[0]); REQUEST_IRQ (IRQ_EINT4,BUTTONS_IRQ, IRQ_TYPE_EDGE_BOTH, "Key2", &pins_desc[1]); REQUEST_IRQ (IRQ_EINT2,BUTTONS_IRQ, Irq_type_edge_both, "Key3", &pins_desc[2]); REQUEST_IRQ (IRQ_EINT0,BUTTONS_IRQ, Irq_type_edge_both, "Key4", &pins_desc[3]); return 0;} ssize_t button_dev_read (struct file *file,char __user *buf,size_t size,loff_t *ppos) {if (size!=1) {return-einval;} /* Assume that no keystroke action occurs on the Hibernate */wait_event_interruptible (button_wait_q,ev_press);/* Assume that a keystroke action occurs, return directly to */copy_to_user (buf,&keyval,1); ev_press = 0;return 0;} int button_dev_close (struct inode* inode, struct file *file) {FREE_IRQ (irq_eint1,&pins_desc[0]); FREE_IRQ (irq_ EINT4,&AMP;PINS_DESC[1]); FREE_IRQ (irq_eint2,&pins_desc[2]); FREE_IRQ (irq_eint0,&pins_desc[3]); return 0;} static struct file_operations button_sdv_fops ={.owner = This_module,.open = Button_dev_open,.read = Button_dev_read,.re lease = button_dev_close,};int major;static int button_dev_init (void)//Entry function {major = Register_chrdev (0, "Button_drv", &button_sdv_fops); buttondrv_class = Class_create (This_module, "button_drv"); if (Is_err (Buttondrv_class)) return Ptr_err (Buttondrv_class); buttondrv_class_dev= device_create (Buttondrv_class,null,mkdev (major,0), NULL, "Wq_button "), if (Unlikely (Is_err (Buttondrv_class_dev))) return Ptr_err (Buttondrv_class_dev);/* Map Physical Address */gpfcon = (volatile unsigned long *) Ioremap (0x56000050, +); Gpfdat = Gpfcon + 1;return 0;} static void Button_dev_exit (void) {Unregister_cHrdev (Major, "Button_drv");d Evice_unregister (Buttondrv_class_dev); Class_destroy (Buttondrv_class); Iounmap (Gpfcon );} Module_init (Button_dev_init); Module_exit (Button_dev_exit);

Test code:

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h>/* * wq_ Device <dev> <on|off> */int main (int argc, char **argv) {int Cnt=0;int fd;unsigned char key_val;fd = open ("/dev /wq_button ", O_RDWR); if (fd<0) {printf (" can ' t open \ n ");} while (1) {read (fd,&key_val,1);p rintf ("Key_val = 0x%x\n", key_val);} return 0;}


























Linux drive interrupt mode get key value

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.