找回密码
 注册
搜索
查看: 1490|回复: 0

[ARM资料] tq2440 按键驱动 中断方式(转)

[复制链接]
发表于 2016-1-18 16:44:52 | 显示全部楼层 |阅读模式
  硬件平台: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);
高级模式
B Color Image Link Quote Code Smilies

本版积分规则

Archiver|手机版|小黑屋|52RD我爱研发网 ( 沪ICP备2022007804号-2 )

GMT+8, 2024-12-27 15:49 , Processed in 0.070024 second(s), 16 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表