硬件平台:TQ2440
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "key-device"
MODULE_DESCRIPTION("759981398@qq.com");
MODULE_AUTHOR("traveler");
MODULE_LICENSE("Dual BSD/GPL");
//声明一个等待队列
static DECLARE_WAIT_QUEUE_HEAD(keys_wait_irq) ;
//事件 用于同步用户与驱动程序之间的数据
static volatile int key_event = 0;
//存储按键的值
static volatile int key_value = 0;
static void * key_devid = (void *)0;
//ISR中断服务程序
static irqreturn_t keys_irq(int irq,void *devid)
{
int down ;
//GPIO的 基址 虚拟地址
//对 GPIO的所有操作 都以此地址 作为 参考 地址
const unsigned int gpio_base = (unsigned int )S3C24XX_VA_GPIO;
//获取 GPFDAT寄存器 的 虚拟地址
const unsigned int gpfdat = gpio_base + 16 * 5 + 4;
if(devid!=key_devid)
{
printk("<1>DRIVER ERROR !devid=%dn",(int)devid);
return IRQ_RETVAL(IRQ_NONE);
}
//获取按键引脚状态
down = (*(unsigned int *)gpfdat) ;
//如果当前值和存储的值不相等 则唤醒等待队列
// if((down &0x01) != (key_value&0x01))
{
key_value = down & 0x01;
key_event = 1;
wake_up_interruptible(&keys_wait_irq);
}
//返回标志 中断已服务
return IRQ_RETVAL(IRQ_HANDLED);
}
//读取 按键 状态 用户 调用 参数 列表
static ssize_t key_read(struct file *filp,char __user *buf,
size_t count,loff_t *loff)
{
int err;
if(!key_event)
{
//如果事件未发生并且文件不允许阻塞,那么返回一个错误标识
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN ;
//等待事件
wait_event_interruptible(keys_wait_irq,key_event);
}
//拷贝数据到用户空间
err = copy_to_user(buf,(void *)(&key_value),min(sizeof(key_value),count));
//已经读取了数据,重设事件标志
key_event = 0;
//返回拷贝到的数据长度
return err ? -EFAULT : min(sizeof(key_value),count) ;
};
static int key_open(struct inode *inode,struct file *filp)
{
int err;
//GPIO的 基址 虚拟地址
//对 GPIO的所有操作 都以此地址 作为 参考 地址
const unsigned int gpio_base = (unsigned int )S3C24XX_VA_GPIO;
//获取 GPFCON的 地址
const unsigned int gpfcon = gpio_base + 16 * 5;
//获取 GPFDAT的 地址
unsigned int gpfup = gpfcon + 2*4;
//注册irq函数
err = request_irq(IRQ_EINT0,keys_irq,IRQ_TYPE_EDGE_BOTH,
"key0",key_devid);
if(err)
return -EBUSY;
//设置事件标志
key_event = 1;
//配置 GPF0 端口 为EINT0
(*(unsigned int *)gpfcon) &= ~(0x03);
(*(unsigned int *)gpfcon) |= 0x02;
//禁止 内部 上拉 电阻
(*(unsigned int *)gpfup) |= 0x01;
return 0;
}
static int key_release(struct inode *inode,struct file *filp)
{
//禁止中断
disable_irq(IRQ_EINT0);
//释放中断
free_irq(IRQ_EINT0,key_devid);
return 0;
}
static struct file_operations key_fops =
{
.owner= THIS_MODULE,
.open = key_open,
.read = key_read,
.release = key_release,
};
static struct miscdevice key_misc=
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &key_fops,
};
static int key_init_module(void)
{
int ret ;
//注册 杂项 设备
ret = misc_register(&key_misc);
printk("<1>Module key init,major:10,minor:%dn",key_misc.minor );
return 0;
}
static void key_exit_module(void)
{
//注销 杂项设备
misc_deregister(&key_misc);
printk("<1>Module key exitn" );
}
module_init(key_init_module);
module_exit(key_exit_module);