首先定义一个定时器button_timer
在init入口函数中初始化该定时器、定义定时器处理函数、add_timer
按下按键后,发生中断,在中断服务函数中不再处理中断,而是修改定时器的超时时间为10ms,超时后触发定时器处理函数来处理中断(读取按键值等过程)。
若按键按下后不断有抖动导致中断发生,这些中断将使得中断服务程序不断的重新修改定时器的超时时间为10ms,由于各个抖动之间的时间间隙不太可能超过10ms,所以抖动过程中不会触发
触发定时器处理函数来处理中断,这期间的按键值也不会被读取。最后一个抖动结束后,由于没有新的中断来修改定时器超时时间,经过10ms后定时器超时,触发定时器处理函数来处理中断,读取按键值。
驱动程序代码如下
-
//moudle.h 包含了大量加载模块需要的函数和符号的定义
-
#include <linux/module.h>
-
//kernel.h以便使用printk()等函数
-
#include <linux/kernel.h>
-
//fs.h包含常用的数据结构,如struct file等
-
#include <linux/fs.h>
-
//uaccess.h 包含copy_to_user(),copy_from_user()等函数
-
#include <linux/uaccess.h>
-
//io.h 包含inl(),outl(),readl(),writel()等IO口操作函数
-
#include <linux/io.h>
-
#include <linux/miscdevice.h>
-
#include <linux/pci.h>
-
//init.h来指定你的初始化和清理函数,例如:module_init(init_function)、module_exit(cleanup_function)
-
#include <linux/init.h>
-
#include <linux/delay.h>
-
#include <linux/device.h>
-
#include <linux/cdev.h>
-
#include <linux/gpio.h>
-
#include <linux/irq.h>
-
#include <linux/sched.h>
-
#include <linux/interrupt.h>
-
#include <linux/poll.h>
-
//irq.h中断与并发请求事件
-
#include <asm/irq.h>
-
//下面这些头文件是IO口在内核的虚拟映射地址,涉及IO口的操作所必须包含
-
//#include <mach/gpio.h>
-
#include <mach/regs-gpio.h>
-
#include <plat/gpio-cfg.h>
-
#include <mach/hardware.h>
-
#include <mach/map.h>
-
-
-
static struct class *button_stab_class;
-
static int major;
-
-
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
-
/* 中断事件标志, 中断服务程序将它置1,button_stab_read将它清0 */
-
static volatile int ev_press = 0;
-
-
static struct fasync_struct *button_async;
-
-
static struct timer_list button_timer;//定时器
-
-
//static atomic_t canopen = ATOMIC_INIT(1); //定义原子变量并初始化为1
-
-
static DEFINE_SEMAPHORE(button_lock); //linux-2.6.36后DECLARE_MUTEX换成了DEFINE_SEMAPHORE
-
-
struct pin_desc {
-
unsigned int pin;
-
unsigned int button_val;
-
};
-
-
static unsigned char button_val;
-
-
static struct pin_desc pins_desc[6] = {
-
{S3C64XX_GPN(0), 0x01},
-
{S3C64XX_GPN(1), 0x02},
-
{S3C64XX_GPN(2), 0x03},
-
{S3C64XX_GPN(3), 0x04},
-
{S3C64XX_GPN(4), 0x05},
-
{S3C64XX_GPN(5), 0x06},
-
};
-
-
static struct pin_desc *irq_pd;
-
-
/*中断服务函数*/
-
/* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 ...*/
-
/* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 ...*/
-
static irqreturn_t button_stab_irq(int irq, void *dev_id)
-
{
-
/* 10ms后启动定时器 */
-
irq_pd = (struct pin_desc *)dev_id;
-
mod_timer(&button_timer, jiffies+HZ/100); //jiffies是系统的定时器时间,HZ/100表示10ms
-
return IRQ_HANDLED;
-
}
-
-
static void button_timer_function(unsigned long data)
-
{
-
struct pin_desc * pindesc = irq_pd;
-
unsigned int pinval;
-
-
if (!pindesc)
-
return;
-
-
pinval = gpio_get_value(pindesc->pin);
-
-
if (pinval)
-
{
-
/* 松开 */
-
button_val = 0x80 | pindesc->button_val;
-
}
-
else
-
{
-
/* 按下 */
-
button_val = pindesc->button_val;
-
}
-
-
ev_press = 1; /* 表示中断发生了 */
-
-
wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */
-
-
kill_fasync (&button_async, SIGIO, POLL_IN);//通过这个函数去发送信号给应用程序
-
}
-
-
-
static int button_stab_open(struct inode *inode, struct file *file)
-
{
-
int ret;
-
-
#if 0
-
if (!atomic_dec_and_test(&canopen))
-
{
-
atomic_inc(&canopen);
-
return -EBUSY;
-
}
-
#endif
-
-
if (file->f_flags & O_NONBLOCK)
-
{
-
if (down_trylock(&button_lock))
-
return -EBUSY;
-
}
-
else
-
{
-
/* 获取信号量 */
-
down(&button_lock);
-
}
-
-
-
/*request_irq注册中断
-
*第一个参数是中断号,也是中断处理函数button_stab的第一个参数
-
*第二个参数是中断处理函数
-
*第三个参数是中断触发方式
-
*第四个参数是设备名称
-
*第五个参数是设备ID,也是中断处理函数button_stab的第二个参数
-
*/
-
ret = request_irq(IRQ_EINT(0), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k1", &pins_desc[0]);
-
if (ret){
-
printk("request IRQ_EINT(0) error!\n");
-
free_irq(IRQ_EINT(0), &pins_desc[0]);
-
}
-
ret = request_irq(IRQ_EINT(1), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k2", &pins_desc[1]);
-
if (ret){
-
printk("request IRQ_EINT(1) error!\n");
-
free_irq(IRQ_EINT(1), &pins_desc[1]);
-
}
-
-
ret = request_irq(IRQ_EINT(2), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k3", &pins_desc[2]);
-
if (ret){
-
printk("request IRQ_EINT(2) error!\n");
-
free_irq(IRQ_EINT(2), &pins_desc[2]);
-
}
-
-
ret = request_irq(IRQ_EINT(3), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k4", &pins_desc[3]);
-
if (ret){
-
printk("request IRQ_EINT(3) error!\n");
-
free_irq(IRQ_EINT(3), &pins_desc[3]);
-
}
-
-
ret = request_irq(IRQ_EINT(4), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k5", &pins_desc[4]);
-
if (ret){
-
printk("request IRQ_EINT(4) error!\n");
-
free_irq(IRQ_EINT(4), &pins_desc[4]);
-
}
-
-
ret = request_irq(IRQ_EINT(5), button_stab_irq, IRQ_TYPE_EDGE_BOTH, "k6", &pins_desc[5]);
-
if (ret){
-
printk("request IRQ_EINT(5) error!\n");
-
free_irq(IRQ_EINT(5), &pins_desc[5]);
-
}
-
return 0;
-
}
-
-
static ssize_t button_stab_read(struct file *file, char __user *buf, size_t size, loff_t * ppos)
-
{
-
if (size != 1)
-
return -EINVAL;
-
-
if (file->f_flags & O_NONBLOCK)
-
{
-
if (!ev_press)
-
return -EAGAIN;
-
}
-
else
-
{
-
/* 如果没有按键动作, 休眠 */
-
/*ev_press=0时休眠,ev_press=1时继续向下执行程序*/
-
wait_event_interruptible(button_waitq, ev_press);
-
}
-
-
/* 如果有按键动作, 返回键值 */
-
if( copy_to_user(buf, &button_val, 1) ){
-
printk("error in function ‘copy_to_user’ !\n");
-
return -EFAULT;
-
}
-
-
ev_press = 0;
-
return 0;
-
}
-
-
static ssize_t button_stab_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
-
{
-
return 0;
-
}
-
-
static int button_stab_release(struct inode *inode, struct file *file)
-
{
-
//atomic_inc(&canopen);
-
free_irq(IRQ_EINT(0), &pins_desc[0]);
-
free_irq(IRQ_EINT(1), &pins_desc[1]);
-
free_irq(IRQ_EINT(2), &pins_desc[2]);
-
free_irq(IRQ_EINT(3), &pins_desc[3]);
-
free_irq(IRQ_EINT(4), &pins_desc[4]);
-
free_irq(IRQ_EINT(5), &pins_desc[5]);
-
up(&button_lock);
-
-
return 0;
-
}
-
-
static unsigned button_stab_poll(struct file *file, poll_table *wait)
-
{
-
unsigned int mask = 0;
-
poll_wait(file, &button_waitq, wait); // 不会立即休眠
-
-
if (ev_press)
-
mask |= POLLIN | POLLRDNORM;
-
-
return mask;
-
}
-
-
static int button_stab_fasync (int fd, struct file *filp, int on)
-
{
-
printk("driver: button_stab_fasync\n");
-
return fasync_helper (fd, filp, on, &button_async);
-
}
-
-
static struct file_operations button_stab_fops = {
-
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
-
.open = button_stab_open,
-
.read = button_stab_read,
-
.write = button_stab_write,
-
.release = button_stab_release,
-
.poll = button_stab_poll,
-
.fasync = button_stab_fasync,
-
};
-
-
static int button_stab_init(void)
-
{
-
init_timer(&button_timer);//初始化定时器
-
button_timer.function = button_timer_function;//设置定时器处理函数
-
add_timer(&button_timer);
-
-
major = register_chrdev(0, "button_stab_dev", &button_stab_fops);//注册,告诉内核
-
button_stab_class = class_create(THIS_MODULE, "button_stab_cls");
-
device_create(button_stab_class, NULL, MKDEV(major, 0), NULL, "button_stab");/* /dev/button_stab */
-
-
return 0;
-
}
-
-
static void button_stab_exit(void)
-
{
-
unregister_chrdev(major, "button_stab_cls");
-
device_destroy(button_stab_class, MKDEV(major, 0));
-
class_destroy(button_stab_class);
-
}
-
-
module_init(button_stab_init);
-
module_exit(button_stab_exit);
-
-
MODULE_LICENSE("GPL");
阅读(1055) | 评论(0) | 转发(0) |