tq2440 按键驱动 中断方式

来源:本站
导读:目前正在解读《tq2440 按键驱动 中断方式》的相关信息,《tq2440 按键驱动 中断方式》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《tq2440 按键驱动 中断方式》的详细说明。
简介:本文是关于tq2440 按键驱动 中断方式。

硬件平台: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);

提醒:《tq2440 按键驱动 中断方式》最后刷新时间 2024-03-14 01:00:57,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《tq2440 按键驱动 中断方式》该内容的真实性请自行鉴别。