Multi-key driver optimization
Optimized code that supports two keys for supported code: DUOKEY.C:
#include <linux/module.h>/* for module specific items */
#include <linux/fs.h>/* for file operations */
#include <linux/ioport.h>/* for io-port access * *
#include <linux/io.h>/* for inb/outb/... * *
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#define GPNCON 0x7f008830
#define GPNDAT 0x7f008834
struct Work_struct *work1;
struct Timer_list key_timer;//defining timers
unsigned int *gpio_data;
void Work1_func (struct work_struct *work)
{
Start Timer 100 ms timeout =hz/10,hz=1 seconds. Jiffies is the current time of the system
Mod_timer (&KEY_TIMER,JIFFIES+HZ/10);
}
void Key_timer_func (unsigned Long data)
{///Timer timeout function needs to be modified, need to determine which key is timed out
unsigned int key_val;
When you time out, you need to read the data
KEY_VAL=READW (gpio_data) &0x01;//reads the value of a key EINT0.
When he was pressed, it was low, it was pressed. is a valid key.
if (0==key_val)//Real Press
PRINTK ("<0> key1 down!\n");
KEY_VAL=READW (gpio_data) &0x02;//reads the value of a key EINT1.
When he was pressed, it was low, it was pressed. is a valid key.
if (0==key_val)//Real Press
PRINTK ("<0> key2 down!\n");
}
irqreturn_t key_int (int irq, void *dev_id)
{
1. Detect if a key interrupt has occurred
2. Clear the key interrupt that has occurred
The previous hardware-related work must be performed in the interrupt
The following is hardware-independent work, which we refer to as a work1_func function outside of the interrupt to handle.
3. Print Key values
Schedule_work (WORK1);
return 0;
}
void Key_hw_init ()
{
unsigned int *gpio_config;
unsigned short data;
Gpio_config = Ioremap (gpncon,4);
data = READW (Gpio_config);
Data &= ~0b1111;//Add a button
Data |= 0b1010;
Writew (Data,gpio_config);
Gpio_data = Ioremap (gpndat,4);
}
int Key_open (struct inode *node, struct file *filp)
{
return 0;
}
struct File_operations key_fops =
{
. open = Key_open,
};
struct Miscdevice Key_miscdevice =
{
. minor = 200,
. Name = "Ok6410key",
. FoPs = &key_fops,
};
static int Key_init ()
{
Misc_register (&key_miscdevice);
Registering an interrupt handler
REQUEST_IRQ (irq_eint (0), Key_int, irqf_trigger_falling, "Ok6410key", 0);
Added support for one key
REQUEST_IRQ (Irq_eint (1), Key_int, irqf_trigger_falling, "Ok6410key", 0);
Hardware initialization
Key_hw_init ();//The corresponding bit is set
2. Create a job
Work1 = kmalloc (sizeof (struct work_struct), gfp_kernel);
Init_work (Work1, Work1_func);
Timer initialization
Init_timer (&key_timer);
Key_timer.function=key_timer_func;
Register Timer
Add_timer (&key_timer);
return 0;
}
static void Key_exit ()
{
Misc_deregister (&key_miscdevice);
}
Module_init (Key_init);
Module_exit (Key_exit);
/* Optimization: More than one interrupt, Gpio is also a multi-key initialization, interrupt generation to determine which key generated by the interrupt. */
Result of Make:
Generate. ko drive files, copy to board to run. Press 1 and the 2nd number key will output the appropriate information.
The first is to create the corresponding character device file.
Mknod/dev/6410key C 10 200
Key application Design
Application code KEY_APP.C: The main function is to read out the values of the pressed key:
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int FD;
int key_num;
1. Turn on the device
Fd=open ("/dev/6410key", 0);
if (fd<0)
printf ("Open device fail!\n");
2. Read the device
Read (fd,&key_num,4);
printf ("Key is%d\n", key_num);
3. Turn off the device
Close (FD);
return 0;
}
Compilation: Arm-linux-gcc-static Key_app.c-o Key_app
This is our key test application.
In fact, it's not possible to test our previous drivers: because we have only the open function in our previous file_operations structure. Read is not supported.
struct File_operations key_ops =
{
. open = Key_open,
};
These functions do not have to learn to go to the kernel code to find prototypes.
Finished, make, error: implicit declaration of function ' Copy_to_user ' without his head file, header file is linux/eaccess.h. Final make success:
Improved DUOKEY.C:
#include <linux/module.h>/* for module specific items */
#include <linux/fs.h>/* for file operations */
#include <linux/ioport.h>/* for io-port access * *
#include <linux/io.h>/* for inb/outb/... * *
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#define GPNCON 0x7f008830
#define GPNDAT 0x7f008834
struct Work_struct *work1;
struct Timer_list key_timer;//defining timers
unsigned int *gpio_data;
Global variables
unsigned int key_num;
Read button
ssize_t key_read (struct file *filp, char __user *buf, size_t size, loff_t *pos)
{
Return the kernel to the user
Copy_to_user (buf,&key_num,4);
return 4;
}
void Work1_func (struct work_struct *work)
{
Start Timer 100 ms timeout =hz/10,hz=1 seconds. Jiffies is the current time of the system
Mod_timer (&KEY_TIMER,JIFFIES+HZ/10);
}
void Key_timer_func (unsigned Long data)
{///Timer timeout function needs to be modified, need to determine which key is timed out
unsigned int key_val;
When you time out, you need to read the data
KEY_VAL=READW (gpio_data) &0x01;//reads the value of a key EINT0.
When he was pressed, it was low, it was pressed. is a valid key.
if (0==key_val)//Real Press
key_num=1;//Read Key number
KEY_VAL=READW (gpio_data) &0x02;//reads the value of a key EINT1.
When he was pressed, it was low, it was pressed. is a valid key.
if (0==key_val)//Real Press
key_num=2;
}
irqreturn_t key_int (int irq, void *dev_id)
{
1. Detect if a key interrupt has occurred
2. Clear the key interrupt that has occurred
The previous hardware-related work must be performed in the interrupt
The following is hardware-independent work, which we refer to as a work1_func function outside of the interrupt to handle.
3. Print Key values
Schedule_work (WORK1);
return 0;
}
void Key_hw_init ()
{
unsigned int *gpio_config;
unsigned short data;
Gpio_config = Ioremap (gpncon,4);
data = READW (Gpio_config);
Data &= ~0b1111;//Add a button
Data |= 0b1010;
Writew (Data,gpio_config);
Gpio_data = Ioremap (gpndat,4);
}
int Key_open (struct inode *node, struct file *filp)
{
return 0;
}
struct File_operations key_fops =
{
. open = Key_open,
. Read = key_read,//increased read operations
};
struct Miscdevice Key_miscdevice =
{
. minor = 200,
. Name = "6410key",
. FoPs = &key_fops,
};
static int Key_init ()
{
Misc_register (&key_miscdevice);
Registering an interrupt handler
REQUEST_IRQ (irq_eint (0), Key_int, irqf_trigger_falling, "6410key", 0);
Added support for one key
REQUEST_IRQ (Irq_eint (1), Key_int, irqf_trigger_falling, "6410key", 0);
Hardware initialization
Key_hw_init ();//The corresponding bit is set
2. Create a job
Work1 = kmalloc (sizeof (struct work_struct), gfp_kernel);
Init_work (Work1, Work1_func);
Timer initialization
Init_timer (&key_timer);
Key_timer.function=key_timer_func;
Register Timer
Add_timer (&key_timer);
return 0;
}
static void Key_exit ()
{
Misc_deregister (&key_miscdevice);
}
Module_init (Key_init);
Module_exit (Key_exit);
/* Optimization: More than one interrupt, Gpio is also a multi-key initialization, interrupt generation to determine which key generated by the interrupt. */
The next step is to test the Development Board: first, copy the generated key driver files to the Development Board: install.
Next is the creation of the character device file:
Mknod/dev/6410key C 10 200
6410key is the device file that we use, C is the symbol of the character device file, 10 is the fixed main device number of the hybrid device, and 200 is the secondary device number we define in the character driver.
After you have created it, run the application Key_app:
[Email protected]]#./key_app
Key is 0
6. Driver supports multi-key operation