In layman's ~linux device driven key device driver

Source: Internet
Author: User

In the above-mentioned Drive series blog, we have learned about blocking and non-blocking, asynchronous notification, polling, memory and I/O port access, concurrency control and other knowledge, the key device driver is relatively simple, this chapter content can deepen our character device driver architecture, blocking and non-blocking, Interrupt timer and other relevant knowledge of the understanding. In the embedded system, the hardware of the key is simple, that is, the external interrupt pin of the processor is pulled high by a pull-up resistor, and the other end of the resistor is connected to the button and grounded.

1. The confirmation process of the key is as follows

2 Key data structures in the drive

2.1 Key device structure and timer

#define MAX Key BUF 16//Key buffer size                                   typedef unsigned char key RET;//device structure: typedef struct {                                   unsigned int keystatus[k EY NUM]; 4 key key State key     RET Buf[max key BUF];//key buffer     unsigned int head, tail;//Key buffer header and tail     wait queue head T Wq;//wait queues     struct Cdev cdev;      Cdev Structural Body   

2.2 Keys hardware resource, key value information structure body

static struct Key info       {                        int IRQ no;      Interrupt number                                   unsigned int gpio port;//gpio Port                          int key no;     Key value                 } key Info tab [4] =       The          CPU resource used by the {/* key */         {  IRQ EINT10, GPIO G2, 1         }        ,         {                  IRQ E INT13, Gpio G5, 2         }        ,         {                      IRQ EINT14, Gpio G6, 3         }        ,         {                              IRQ EINT15, Gpio G7, 4         }        ,      

2.3 Key device driver file operation structure

Static struct file operations s3c2410 Key FoPs =      {                         owner:this MODULE,                            open:s3c2410 key Open,  //boot device c30/>release:s3c2410 key release,  //Shutdown device                            read:s3c2410 key read,//  read key key value      

module load and unload functions for 3-button devices

3.1 Load function

static int    init s3c2410 key init (void)       {         ...//apply for device number, add Cdev                               request IRQs ();//register interrupt function         Keydev. Head = Keydev. tail = 0; Initialize struct for                                     (i = 0; i < KEY NUM; i++)                                                      keydev.keystatus[i] = keystatus up;                   Init waitqueue Head (& (Keydev. Wq)); Wait for              the queue//initialization timer to implement the software's jitter for                                  (i = 0; i < KEY NUM; i++)                      Setup timer (&key timer[i], KEY timer handler, i);        Use the key ordinal as the parameter of the incoming timer handler function      }

3.2 Unload function

static void     exit s3c2410 key exit (void)      {                    free IRQs ();//Logoff interrupt        ...//release device number, delete Cdev      

3.3 Interrupt Request function

/* Request system Interrupt, interrupt mode for falling edge trigger *                                  /static int request IRQs (void)       {                             struct key info *k;         int i;                                       for (i= 0; i < sizeof (key info tab)/sizeof (Key Info tab [1]); i++)         {                           k = key info tab + i;                     Set external IRQ (K->IRQ No, EXT lowlevel, GPIO pullup DIS);                       Set the low-level trigger                                     if   (Request IRQ (K->IRQ No,  &buttons IRQ,  SA INTERRUPT,     DEVICE NAME,            i )  //Application interrupt, the key sequence number as a parameter into the Interrupt service program          {            return  -1;          }        }        return 0;      }

3.4 Interrupt Release function

/* Release Interrupt *                               /static void free IRQs (void)       {                          struct key info *k;         int i;                                     for (i= 0; i < sizeof (key info tab)/sizeof (Key Info tab [1]); i++)         {                            k = key info tab + i;                       Free IRQ (K->irq no, buttons IRQ); Release Interrupt        }      

4 Key device driver interrupt and timer handler

After the key is pressed, an interrupt will occur, in the interrupt handler, the interrupt in the query mode should be closed first, delay to eliminate the following interrupt processing process only the top half, no bottom half of the.

4.1 Interrupt Handlers

static void s3c2410 eint key (int IRQ, void *dev ID, struct PT regs *reg)      {                          int key = Dev ID;                    Disable IRQ (Key Info tab [KEY].IRQ NO);  Off interrupt, into query type                                                      keydev.keystatus[key] = keystatus downx;//status is pressed            _                            key Timer [key].expires = jiffies + key Timer delay1;//delay          Add timer (&key Timer[key]);//Start Timer      

4.2 Timer Processing Flow

When the key is pressed, the key will record the word buffer, while the timer starts the delay, each time the new key value is recorded, the waiting queue is awakened, its code is as follows.

Key device-driven timer handler function static void key Timer handler (unsigned Long data)       {         int key = data;                 if (IsKey down (key))         {                              if (keydev.keystatus[key] = = Keystatus downx)           //Enter           {                                      Keydev from interrupt. keystatus[ Key] = Keystatus down;                         Key Timer[key].expires = = jiffies + key timer DELAY; Delayed            keyevent ();  Record key value, wake wait queue                        Add timer (&key timer [key]);          }          else          {                         key timer[key].expires = = jiffies + key timer delay;//delay                         Add timer (&key timer [key]);          }        }        else       //key lifted        {                                                       Keydev.keystatus[key] = keystatus up;                      Enable IRQ (Key Info tab [KEY].IRQ NO);        

5 opening and releasing functions

Here is mainly set Keydev.head and Keydev.tail and key event function pointer keyevent value, key device driver open, release function as follows:

static int s3c2410 key open (struct inode *inode, struct file *filp)       {         Keydev. Head = keydev. Tail = 0;//clear Key action buffer Zone                                                                    keyevent = KeyEvent raw;//function pointer to key handling function KeyEvent raw         return 0;       }                                      static int s3c2410 key release (struct inode *inode, struct file *filp)       {                                  keyevent = KeyEvent dummy;//function pointer pointing to NULL function 
   return 0;}

6 Read function

Read function is mainly to provide the key device structure buffer read and copy to the user space, when keydev.head! = keydev.tail, the description buffer has data, using the Copy_to_user () function to copy to the user space, Conversely, depending on whether the user space is blocked or non-blocking reads are divided into the following two scenarios:

    • Non-blocking read: No key cache, direct return-eagain;
    • Blocking reads: Sleeps on the keydev.wq wait queue until a keystroke is logged to the buffer and is awakened.
Key device-driven read function       static ssize t s3c2410 key Read (struct file *filp,char *buf,ssize t count,                     loff t*ppos)       {         re Try:if (Keydev.head! = Keydev. Tail)         //Current loop queue has data         {                         key ret = Keyread ();//Read button                          copy to user (..);//Data from The kernel space is transferred to user space         }        else        {                             if (filp->f flags &o nonblock)          //If the user reads          {            by non-blocking mode} return  -eagain;          }                                Interruptible Sleep On (& (Keydev. Wq));            The user reads in a blocking manner, calling the function to make the process sleep          goto retry;        }        return 0;      

  

All rights reserved, reprint please specify reprint address: http://www.cnblogs.com/lihuidashen/p/4498025.html

In layman's ~linux device driven key device driver

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.