Obtain the key value in linux drive interruption mode and in linux drive interruption Mode

Source: Internet
Author: User

Obtain the key value in linux drive interruption mode and in linux drive interruption Mode
How to get the key value in linux drive interruption Mode

Certificate ------------------------------------------------------------------------------------------------------------------------------------------------------

Review of interrupt handling in Single Chip Microcomputer -------------------------------------------------------------------------------------------------------------------------------------------------------
1. Interrupt framework

Constructed in trap_int

Trap_intA function is a jump command.

B...

B...

B vector_irq + stubs_offset; vector_irq is the link address stubs_offset is the offset address


Vector_irq:Asm_do_IRQ:

Handling of interruptions.

Request_irq registration interrupted

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

1. Allocate irqaction Structure

2. setup_irq (irq, action)

0. Allocate an irqaction Structure

A. In irq_desc [irq]-> action

B. desc-> chip-> settype

C. desc-> chip-> startup/enable

Irq Hardware Interrupt number to be applied +
Handle Is the interrupt processing function registered with the System Is a callback function. When the main function is short, the system will call this function and pass dev_id to it.
Irqflags Is the Interrupt Processing attribute  

Free_irq unmount interrupted

Free_irq (irq, dev_id)

1. outbound links

2. Interruption prohibited

2. coding 1. Apply for IRQ

Here I would like to explain: (To Me, I encountered a problem when using the request_irq function. IRQ_EINT1, IRQ_EINT4, IRQ_EINT2, and IRQ_EINT0 macros cannot be found. The final cause is found, there are some minor issues with the kernel tree path when I configure eclipse. The irqs. h file is in/Linux-2.6.30.4/arch/arm/mach-s3c2410/includeUnder this path, I thought this will also have this path in the mach-s3c2440, in fact, it is not. Some pins are also defined in the 2410 path. Note that ).

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]);

Here, pins_desc is a struct array.

struct pin_desc pins_desc[4] ={{S3C2410_GPF1,0x01},{S3C2410_GPF4,0x02},{S3C2410_GPF2,0x03},{S3C2410_GPF0,0x04},};

The array contains the four interrupt pins and the key values of the pins.

The struct prototype is as follows:

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

2. Write interrupt processing functions

Static irqreturn_t buttons_irq (int irq, void * dev_id) {struct pin_desc * pindesc = (struct pin_desc *) dev_id; unsigned int pinval; pinval = trim (pindesc-> pin ); if (pinval) // release {keyval = 0x80 | pindesc-> key_value;} else {keyval = pindesc-> key_value;} ev_press = 1; // wake_up_interruptible (& button_wait_q); printk ("button is pressed: % d \ n", irq); return IRQ_HANDLED ;}
Note:

Pindesc: This structure shows which button is pressed
S3c2410_gpio_getpin: this function is provided by the kernel to obtain the high and low levels of the current pin.
Ev_press: indicates the interrupt event. The interrupt service sets it to 1, and the read function sets it to 0.

Wake_up_interruptible (& button_wait_q); the sleep process is wakened and the process registered to the waiting queue is wakened. In this case, button_wait_q is obtained in the following way:

Static DECLARE_WAIT_QUEUE_HEAD (button_wait_q); generates a waiting queue header wait_queue_head_t named button_wait_q

3. Modify 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;}/* if no button action occurs, sleep */wait_event_interruptible (button_wait_q, ev_press);/* If a button action occurs, directly return */copy_to_user (buf, & keyval, 1); ev_press = 0; return 0 ;}

Where:

Wait_event_interruptible (button_wait_q, ev_press); If ev_press is false, it will sleep

Ev_press = 0; the interruption event flag is cleared every time you finish reading.

4. Fill in the file_operations struct

static struct file_operations button_sdv_fops ={.owner = THIS_MODULE,.open  = button_dev_open,.read = button_dev_read,.release = button_dev_close,};

The button_dev_close function is:

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 indicates the release interruption, which requires two parameters.


This code is modified on the basis of the previous key blog.

Complete 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/G PL "); static struct class * buttondrv_class; static struct class_devices * buttondrv_class_dev;/*/static DECLARE_WAIT_QUEUE_HEAD (button_wait_q);/* indicates the interrupt event, which is set to 1 by the interrupt program, the read function sets it to 0 */static volatile int ev_press = 0; volatile unsigned long * gpfcon = NULL; volatile unsigned long * gpfdat = NULL; static unsigned keyval; struct pin_desc {unsigned int pin; unsigned int key_value ;};/* press 0x01 0x02 0x03 0x04 * // * when the key is released Yes: 0x81 0x82 0x83 0x84 */struct pin_desc pins_desc [4] = {S3C2410_GPF1, 0x01}, {S3C2410_GPF4, 0x02 }, {S3C2410_GPF2, 0x03}, {S3C2410_GPF0, 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 {keyval = 0x80 | pindesc-> key_value;} else {keyval = pindesc-> key_va Lue;} ev_press = 1; // wake_up_interruptible (& button_wait_q); printk ("button is pressed: % d \ n", irq); return IRQ_HANDLED ;} static int button_dev_open (struct inode * inode, struct file * file, "key1", & pins_desc [0]); request_irq (IRQ_EINT4, buttons_irq, encrypt, "key2", & pins_desc [1]); request_irq (IRQ_EINT2, buttons_irq, IRQ_TYPE_EDGE_BOTH, "key3", & pins_desc [2]); request_irq (IRQ_EINT0, buttons_irq, cosine, "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;}/* if no button action occurs, sleep */wait_event_interruptible (button_wait_q, ev_press);/* If a button action occurs, directly return */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 (records, & pins_desc [2]); free_irq (records, & pins_desc [3]); return 0;} static struct file_operations button_sdv_fops = {. owner = THIS_MODULE ,. open = button_dev_open ,. read = button_dev_read ,. release = button_dev_close,}; int major; static int button_dev_init (void) // entry function {major = equals (0, "button_drv", & signature); buttondrv_class = class_create (THIS_MODULE, "button_drv"); if (IS_ERR (buttondrv_class) return response (buttondrv_class); response = device_create (buttondrv_class, NULL, MKDEV (major, 0), NULL, "wq_button "); if (unlikely (IS_ERR (buttondrv_class_dev) return PTR_ERR (buttondrv_class_dev);/* ing physical address */gpfcon = (volatile unsigned long *) ioremap (0x56000050, 16 ); gpfdat = gpfcon + 1; return 0;} static void button_dev_exit (void) {encrypt (major, "button_drv"); device_unregister (batch); 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);printf("key_val = 0x%x\n",key_val);}return 0;}


























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.