button_drv.c驱动文件:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> 
#include <asm/uaccess.h> 
#include <linux/device.h> 
#include <asm/arch/regs-gpio.h> 
#include <linux/irq.h>
#include <asm-arm/irq.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/hardware.h>
#include <linux/poll.h>

#define DRIVER_NAME "button_drv"
#define DEVICE_NAME "button_dev"

int major;

static atomic_t openFlag = ATOMIC_INIT(1);     //定义原子变量openFlag并初始化为1

volatile unsigned long *gpfcon;
volatile unsigned long *gpfdat;
volatile unsigned long *gpgcon;
volatile unsigned long *gpgdat;

struct class *button_class;
struct class_device *button_class_device;

unsigned char ev_press;
DECLARE_WAIT_QUEUE_HEAD(button_waitq);       //注册等待队列

struct fasync_struct *button_fasync;        //定义fasync_struct结构体

unsigned char keyVal;

struct pin_desc{
  unsigned int pin;
  unsigned int key_val;
};
struct pin_desc pins_desc[4] = {
  {S3C2410_GPF0, 0x01},
  {S3C2410_GPF2, 0x02},
  {S3C2410_GPG3, 0x03},
  {S3C2410_GPG11, 0x04},
};

irqreturn_t buttons_irq(int irq, void *dev_id)
{
  unsigned int pin_val;
  struct pin_desc *pin_desc = (struct pin_desc *)dev_id;
  pin_val = s3c2410_gpio_getpin(pin_desc->pin);
  if(pin_val)
  {
    keyVal = 0x80 | pin_desc->key_val;
  }
  else
  {
    keyVal = pin_desc->key_val;
  }
  wake_up_interruptible(&button_waitq);
  ev_press = 1;
  kill_fasync(&button_fasync, SIGIO, POLL_IN); //发送信号给进程
  return IRQ_HANDLED;
}

int button_drv_open(struct inode *inode, struct file *file)
{
  int ret;
  if(atomic_dec_and_test(&openFlag)==0)     //自减后是否为0, 不为0说明已经被别的线程调用, 要是为0则返回为真, 否则返回为假
  {
    atomic_inc(&openFlag);
    return -EBUSY;
  }
  ret = request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, "S1", &pins_desc[0]);
  if(ret<0)
  {
    printk("failed 1 button_drv_open");
  }
  ret = request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, "S2", &pins_desc[1]);
  if(ret<0)
  {
    printk("failed 2 button_drv_open");
  }
  ret = request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "S3", &pins_desc[2]);
  if(ret<0)
  {
    printk("failed 3 button_drv_open");
  }
  ret = request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, "S4", &pins_desc[3]);
  if(ret<0)
  {
    printk("failed 4 button_drv_open");
  }
  return 0;
}

ssize_t button_drv_read(struct file *file, char __user *userbuf, size_t count, loff_t *off)
{
  int ret;
  ret = copy_to_user(userbuf, &keyVal, 1);
  if(ret<0)
  {
    printk("failed 1 button_drv_read \n");
    return -1;
  }
  ev_press = 0;
  return 1;
}

int button_drv_close(struct inode *inode, struct file *file)
{
  atomic_inc(&openFlag); //原子变量加1
  free_irq(IRQ_EINT0, &pins_desc[0]);
  free_irq(IRQ_EINT2, &pins_desc[1]);
  free_irq(IRQ_EINT11, &pins_desc[2]);
  free_irq(IRQ_EINT19, &pins_desc[3]);
  return 0;
}

unsigned int button_drv_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;
}

int button_drv_fasync(int fd, struct file *file, int on)
{
  int ret;
  ret = fasync_helper(fd, file, on, &button_fasync);
  if(ret<0)
  {
    printk("failed 1 button_drv_fasync \n");
    return ret;
  }
  return 0;
}

struct file_operations button_drv_fops = {
  .owner = THIS_MODULE,
  .open = button_drv_open,
  .read = button_drv_read,
  .release = button_drv_close,
  .poll = button_drv_poll,
  .fasync = button_drv_fasync,
};

int __init button_drv_init(void)
{
  major = register_chrdev(0, DRIVER_NAME, &button_drv_fops);
  if(major<0)
  {
    printk("failed 1 button_drv_init \n");
  }
  button_class = class_create(THIS_MODULE, DEVICE_NAME);
  if(button_class<0)
  {
    printk("failed 2 button_drv_init \n");
  }
  button_class_device = class_device_create(button_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
  if(button_class_device<0)
  {
    printk("failed 3 button_drv_init \n");
  }
  gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);
  gpfdat = gpfcon + 1;
  gpgcon = (volatile unsigned long *)ioremap(0x56000060, 16);
  gpgdat = gpgcon + 1;
  return 0;
}

void __exit button_drv_exit(void)
{
  unregister_chrdev(major, DEVICE_NAME);
  class_device_unregister(button_class_device);
  class_destroy(button_class);
  iounmap(gpfcon);
  iounmap(gpgcon);
}

module_init(button_drv_init);
module_exit(button_drv_exit);

MODULE_LICENSE("GPL");

Makefile文件:

obj-m += timer_drv.o

KERN_DIR = /work/system/linux-2.6.22.6

all:
make -C $(KERN_DIR) M=`pwd` modules 
clean:
rm -rf *.o *.ko *.order *.symvers *.mod.c

button_app.c文件:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <signal.h>

static int fd;

void button_signal(int signum)
{
  unsigned char keyVal;
  printf("signal = %d \n", signum);
  read(fd, &keyVal, 1);
  printf("keyVal = 0x%x \n", keyVal);
}

int main(int argc, char **argv)
{
  int oflags;
  char *filename;

  filename = argv[1];
  fd = open(filename, O_RDWR);
  if(fd<0)
  {
    printf("can not open \n");
  }
  signal(SIGIO, button_signal);       //注册一个信号, 启动信号驱动机制
  fcntl(fd, F_SETOWN, getpid());      //将本应用程序的进程号告诉给内核,最终使得驱动程序可以成功发送信号给应用程序
  oflags = fcntl(fd, F_GETFL);        //取得当前的状态
  fcntl(fd, F_SETFL, oflags|FASYNC);   //改变fasync标记, 最终会调用到驱动的fasync->fasync_helper
  while(1)
  {
    sleep(1000);
  }
  return 0;
}

编译生成button_drv.ko和button_app文件,运行./button_app /dev/button_dev

Linux 驱动——Button驱动5(atomic)原子量的更多相关文章

  1. Linux 驱动——Button驱动7(Timer)消抖

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  2. Linux 驱动——Button驱动6(mutex、NBLOCK、O_NONBLOCK)互斥信号量、阻塞、非阻塞

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  3. Linux 驱动——Button驱动4(fasync)异步通知

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  4. Linux 驱动——Button驱动3(poll机制)

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  5. Linux 驱动——Button驱动2

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  6. Linux 驱动——Button驱动1

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/i ...

  7. Linux GPIO键盘驱动开发记录_OMAPL138

    Linux GPIO键盘驱动开发记录_OMAPL138 Linux基本配置完毕了,这几天开始着手Linux驱动的开发,从一个最简单的键盘驱动开始,逐步的了解开发驱动的过程有哪些.看了一下Linux3. ...

  8. linux块设备驱动之实例

    1.注册:向内核注册个块设备驱动,其实就是用主设备号告诉内核这个代表块设备驱动 sbull_major  =  register_blkdev(sbull_major, "sbull&quo ...

  9. Linux 视频设备驱动V4L2最常用的控制命令

    http://blog.csdn.net/shaolyh/article/details/6583226 Linux 视频设备驱动V4L2最常用的控制命令使用说明(1.02) 命令 功能 VIDIOC ...

随机推荐

  1. vue keep-alive 取消某个页面缓存问题

    keep-alive keep-alive是Vue提供的一个抽象组件,用来对组件进行缓存,从而节省性能,由于是一个抽象组件,所以在v页面渲染完毕后不会被渲染成一个DOM元素 <keep-aliv ...

  2. 用EPPlus 读取excel,代码出错, the given key is not present in the dictionary

    using (ExcelPackage ep = new ExcelPackage(new FileInfo(path))) { ExcelWorksheet ws = ep.Workbook.Wor ...

  3. ClientDataSet使用locate或Filter定位到字段为空值的记录

    场景,程序想检查是否存在某个字段的值是空的,如果存在,则不允许增加记录,否则允许增加记录. 解决这个问题,我一开始用了两种错误的方法 if not clientdataset.locate('AFie ...

  4. CTeX安装警告

    CTeX在安装过程中总会覆盖系统全部的环境变量,之前曾经导致诸如ping.ipconfig以及CUDA全部无法工作,只能手动重装和手动恢复系统默认环境变量. 网上给出的解决方案有:在电脑未关机之前通过 ...

  5. centos 日志文件

    以下介绍的是20个位于/var/log/ 目录之下的日志文件.其中一些只有特定版本采用,如dpkg.log只能在基于Debian的系统中看到./var/log/messages — 包括整体系统信息, ...

  6. RuntimeError: Model class app_anme.models.User doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.---python学习错误记录

    untimeError: Model class app_anme.models.User doesn't declare an explicit app_label and isn't in an ...

  7. springboot秒杀课程学习整理1-3

    1)实现手机验证码功能,用户注册功能,用户登入功能(这里讲开发流程,及本人遇到的问题,具体实现请看代码) 1.拦截请求,获取请求参数(这里的consumes是个常量,可以定义在baseControll ...

  8. JS-5-循环

    循环结构 循环:反复执行有关操作 * for循环 for(var i=1; i<=50; i++) { console.log("第"+i+"次说我爱你" ...

  9. ubuntu16.04安装anaconda、环境配置

    anaconda默认3.7降级到3.6 conda install python=3.6 anaconda安装后找不到conda命令: 执行测试命令 conda info -e conda: comm ...

  10. canal-client无法获取数据

    在虚拟机单cpu环境下 canal.properties配置中 #canal.instance.parser.parallelThreadSize = 16 那么,MysqlMultiStageCop ...