Linux drive interrupt mode get key value
--------------------------------------------------------------------------------------------------------------- ---------------------------------------
Recall the interrupt processing under the single-chip microcomputer
- Tell me which one was interrupted.
- Call handler function
- 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:
- Save the interrupted scene
- Asm_do_irq
- Recovery site
- 。
。。
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,&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