button timer to shake
The switch used for the key is a mechanical elastic switch, and when the mechanical contact is disconnected and closed, the switch will not be switched on or off immediately due to the elastic action of the mechanical contact point. Thus the moment of closure and disconnection is always accompanied by a series of jitter. There are two main ways to shake keys, one is hardware circuit jitter, the other is software delay jitter. And the delay is generally divided into two kinds, one for the waiting loop, the other is the timer delay. In the operating system, for efficiency reasons, it is generally not allowed to use a for loop to wait, only use timers.
Above is the structure of the kernel timer. Where expires is the time of the timer delay, function functions are the things to do after the timer expires.
As can be known from above, the use of timers is divided into four steps: 1. The variable that defines the timer is the timer_list structure. 2. To initialize the structure. Init_timer is an initialization function that is automatically run by the system and can initialize most of the members of a timer_list. However, the timeout function is required for our own setup, which is function. 3. Register the timer with the Add_timer function. 4.mod_timer Restart the timer. Note that the timer is not circular, and the Mod_timer function needs to be called repeatedly.
The following is an example:
NKEY.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)
{
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> key 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 &= ~0b11;
Data |= 0B10;
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);
Hardware initialization
Key_hw_init ();
Registering an interrupt handler
REQUEST_IRQ (irq_eint (0), Key_int, irqf_trigger_falling, "Ok6410key", 0);
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);
Compile successfully, copy the generated. Ko drive files to the Development Board to run.
5. button Timer to shake