Chinaunix首页 | 论坛 | 博客
  • 博客访问: 74450
  • 博文数量: 11
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 94
  • 用 户 组: 普通用户
  • 注册时间: 2015-12-11 15:27
个人简介

给自己一个城堡

文章分类
文章存档

2017年(3)

2016年(8)

我的朋友

分类: 嵌入式

2016-01-17 02:16:53

利用混杂设备实现按键驱动
1.TQ2440按键资源
     k1  --  GPF1 -- EINT1
     k2  --  GPF4 -- EINT4
     k3  --  GPF2 -- EINT2
     k4  --  GPF0 -- EINT0
2.内核介绍
    本驱动基于linux-2.6.32.67内核
3.混杂设备介绍
    linux中特殊的一类字符设备,他们共享一个主设备号(10),但是次设备号不同,其设备文件自动创建。结构如下:   

点击(此处)折叠或打开

  1. struct miscdevice {
  2.     int minor;
  3.     const char *name;
  4.     const struct file_operations *fops;
  5.     struct list_head list;
  6.     struct device *parent;
  7.     struct device *this_device;
  8.     const char *nodename;
  9.     mode_t mode;
  10. };
4.按键驱动程序(基于混杂设备实现)
   misc_button.c

点击(此处)折叠或打开

  1. #include "linux/module.h"
  2. #include "linux/types.h"
  3. #include "linux/fs.h"
  4. #include "linux/platform_device.h"
  5. #include "mach/regs-gpio.h"
  6. #include "mach/irqs.h"
  7. #include "mach/gpio-fns.h"
  8. #include "linux/interrupt.h"
  9. #include "linux/device.h"
  10. #include "linux/io.h"
  11. #include "linux/miscdevice.h"
  12. #include "linux/clk.h"
  13. #include "linux/uaccess.h"
  14. #include "linux/sched.h"
  15. #include "linux/poll.h"
  16. #include "linux/unistd.h"
  17. #include "linux/irq.h"

  18. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
  19. static volatile int ev_press=0;
  20. static volatile char key_value[]={'0','0','0','0'};

  21. struct button_irq_desc{
  22.   int irq;
  23.   int pin;
  24.   int pin_setting;
  25.   int number;
  26.   char *name;
  27. };

  28. static struct button_irq_desc button_irqs[]={
  29.   {IRQ_EINT1,S3C2410_GPF(1),S3C2410_GPF1_EINT1,0,"key1"},
  30.   {IRQ_EINT4,S3C2410_GPF(4),S3C2410_GPF4_EINT4,1,"key2"},
  31.   {IRQ_EINT2,S3C2410_GPF(2),S3C2410_GPF2_EINT2,2,"key3"},
  32.   {IRQ_EINT0,S3C2410_GPF(0),S3C2410_GPF0_EINT0,3,"key4"},
  33. };

  34. //isr
  35. static irqreturn_t buttons_isr(int irq,void *dev_id){
  36.   int down;
  37.   struct button_irq_desc *pirqs=(struct button_irq_desc*)dev_id;

  38.   down=!s3c2410_gpio_getpin(pirqs->pin);

  39.   if(down!=(key_value[pirqs->number]&1)){
  40.     key_value[pirqs->number]='0'+down;
  41.     ev_press=1;
  42.     wake_up_interruptible(&button_waitq);
  43.   }
  44.   return IRQ_RETVAL(IRQ_HANDLED);
  45. }

  46. //misc opt
  47. static int s3c2440_buttons_open(struct inode *inode,struct file *file){
  48.   int i;
  49.   int err=0;

  50.   for(i=0;i<sizeof(button_irqs)/sizeof(button_irqs[0]);i++){
  51.     if(button_irqs[i].irq<0){
  52.       continue;
  53.     }

  54.     err=request_irq(button_irqs[i].irq,buttons_isr,IRQ_TYPE_EDGE_BOTH,button_irqs[i].name,(void*)&button_irqs[i]);
  55.     if(err)
  56.       break;
  57.   }

  58.   if(err){
  59.     i--;
  60.     for(;i>=0;i--){
  61.       if(button_irqs[i].irq<0)
  62.         continue;
  63.       disable_irq(button_irqs[i].irq);
  64.       free_irq(button_irqs[i].irq,(void*)&button_irqs[i]);
  65.     }
  66.     return -EBUSY;
  67.   }

  68.   ev_press=0;
  69.   return 0;
  70. }
  71. static int s3c2440_buttons_close(struct inode *inode,struct file *file){
  72.   int i;
  73.   for(i=0;i<sizeof(button_irqs)/sizeof(button_irqs[0]);i++){
  74.     if(button_irqs[i].irq<0)
  75.       continue;
  76.     free_irq(button_irqs[i].irq,(void*)&button_irqs);
  77.   }
  78.   return 0;
  79. }
  80. static int s3c2440_buttons_read(struct file *filp,char __user *buff,size_t count,loff_t *offp){
  81.   unsigned long err;
  82.   if(!ev_press){
  83.     if(filp->f_flags&O_NONBLOCK)
  84.       return -EAGAIN;
  85.     else
  86.       wait_event_interruptible(button_waitq,ev_press);
  87.   }
  88.   ev_press=0;
  89.   err=copy_to_user(buff,&key_value,sizeof(key_value));
  90.   return sizeof(key_value);
  91. }
  92. //misc ops
  93. static struct file_operations s3c2440_buttons_fops={
  94.   .owner=THIS_MODULE,
  95.   .open=s3c2440_buttons_open,
  96.   .release=s3c2440_buttons_close,
  97.   .read=s3c2440_buttons_read,
  98. };

  99. //misc
  100. static struct miscdevice s3c2440_miscdev={
  101.   .minor=MISC_DYNAMIC_MINOR,
  102.   .name="buttons-test",
  103.   .fops=&s3c2440_buttons_fops,
  104. };

  105. static int dev_init(void){
  106.   int ret;
  107.   ret=misc_register(&s3c2440_miscdev);
  108.   printk("misc dev init.\n");
  109.   return ret;
  110. }

  111. static void dev_exit(void){
  112.   misc_deregister(&s3c2440_miscdev);
  113. }

  114. module_init(dev_init);
  115. module_exit(dev_exit);

  116. MODULE_LICENSE("GPL");
5.测试程序
  根据驱动的实现方法,实现测试程序如下:
  button_test.c

点击(此处)折叠或打开

  1. #include "stdio.h"
  2. #include "string.h"
  3. #include "stdlib.h"
  4. #include "unistd.h"
  5. #include "sys/ioctl.h"
  6. #include "sys/types.h"
  7. #include "sys/stat.h"
  8. #include "fcntl.h"
  9. #include "sys/select.h"
  10. #include "sys/time.h"
  11. #include "errno.h"


  12. int main(void){
  13.   int buttons_fd;
  14.   char key_value[4];
  15.   char first=1;
  16.   int i;

  17.   buttons_fd=open("/dev/buttons-test",0);
  18.   if(buttons_fd<0){
  19.     perror("open device buttons.\n");
  20.     exit(1);
  21.   }

  22.   for(;;){
  23.     char key_value_temp[4];
  24.     int ret;
  25.     ret=read(buttons_fd,key_value_temp,sizeof(key_value_temp));
  26.     if(ret!=sizeof(key_value_temp)){
  27.       perror("read button.");
  28.       exit(1);
  29.     }
  30.     for(i=0;i<sizeof(key_value);i++){
  31.       if(key_value[i]!=key_value_temp[i]){
  32.         key_value[i]=key_value_temp[i];
  33.         printf("k%d is %s%s",i+1,key_value[i]=='0'?"up":"down",first?",":"");
  34.       }
  35.     }
  36.     first=0;
  37.     if(first==0){
  38.       printf("\n");
  39.     }

  40.   }
  41.   close(buttons_fd);
  42.   return 0;
  43. }
6.编译,下载
   分别编译内核模块和测试程序,分别生成misc_button.ko和button_test,通过nfs方式下载到TQ2440开发板中。运行结果如下:

  




阅读(1726) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~