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

给自己一个城堡

文章分类
文章存档

2017年(3)

2016年(8)

我的朋友

分类: 嵌入式

2016-01-17 02:33:11

1.TQ2440按键资源
     k1  --  GPF1 -- EINT1
     k2  --  GPF4 -- EINT4
     k3  --  GPF2 -- EINT2
     k4  --  GPF0 -- EINT0
2.内核介绍
    本驱动基于linux-2.6.32.67内核
3.platform介绍
  platform是linux2.6之后加入的一种虚拟总线,主要由platfor_device和platform_driver两部分构成。
  (1)平台设备  platfor_device

点击(此处)折叠或打开

  1. struct platform_device {
  2.     const char    * name;
  3.     int        id;
  4.     struct device    dev;
  5.     u32        num_resources;
  6.     struct resource    * resource;

  7.     struct platform_device_id    *id_entry;

  8.     /* arch specific additions */
  9.     struct pdev_archdata    archdata;
  10. };
    (2)平台驱动 platform_driver

点击(此处)折叠或打开

  1. struct platform_driver {
  2.     int (*probe)(struct platform_device *);
  3.     int (*remove)(struct platform_device *);
  4.     void (*shutdown)(struct platform_device *);
  5.     int (*suspend)(struct platform_device *, pm_message_t state);
  6.     int (*resume)(struct platform_device *);
  7.     struct device_driver driver;
  8.     struct platform_device_id *id_table;
  9. };
4.平台设备实现
plat_device.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 "linux/interrupt.h"
  8. #include "linux/device.h"
  9. #include "linux/io.h"

  10. //resource
  11. static struct resource s3c_buttons_resource[]={
  12.   [0]={
  13.     .start=S3C24XX_PA_GPIO,
  14.     .end=S3C24XX_PA_GPIO+S3C24XX_SZ_GPIO-1,
  15.     .flags=IORESOURCE_MEM,
  16.   },
  17.   [1]={
  18.     .start=IRQ_EINT1,
  19.     .end=IRQ_EINT1,
  20.     .flags=IORESOURCE_IRQ,
  21.   },
  22.   [2]={
  23.     .start=IRQ_EINT4,
  24.     .end=IRQ_EINT4,
  25.     .flags=IORESOURCE_IRQ,
  26.   },
  27.   [3]={
  28.     .start=IRQ_EINT2,
  29.     .end=IRQ_EINT2,
  30.     .flags=IORESOURCE_IRQ,
  31.   },
  32.   [4]={
  33.     .start=IRQ_EINT0,
  34.     .end=IRQ_EINT0,
  35.     .flags=IORESOURCE_IRQ,
  36.   },
  37. };

  38. static struct platform_device *s3c_buttons;

  39. static int platform_init(void){
  40.   //alloc and register device
  41.   s3c_buttons=platform_device_alloc("2440-buttons",-1);
  42.   platform_device_add_resources(s3c_buttons,s3c_buttons_resource,5);
  43.   platform_device_add(s3c_buttons);
  44.   
  45.   return 0;
  46. }
  47. static void platform_exit(void){
  48.   platform_device_unregister(s3c_buttons);
  49. }
  50. module_init(platform_init);
  51. module_exit(platform_exit);

  52. MODULE_LICENSE("GPL");
5.平台驱动实现
  platform_driver.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 "linux/interrupt.h"
  8. #include "linux/device.h"
  9. #include "linux/io.h"
  10. #include "linux/miscdevice.h"
  11. #include "linux/clk.h"
  12. #include "linux/uaccess.h"
  13. //#include "linux/map.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 int key_value;
  21. static struct resource *button_mem;
  22. static struct resource *button_irq;
  23. static void __iomem *button_base;
  24. static int button_irqs[6]; //record irq no

  25. //isr
  26. static irqreturn_t buttons_isr(int irq,void *dev_id){
  27.   int i;

  28.   printk("==>intrupt number=%d\n",irq);
  29.   for(i=0;i<4;i++){
  30.     if(irq==button_irqs[i]){
  31.       key_value=i;
  32.       ev_press=1;
  33.       wake_up_interruptible(&button_waitq);
  34.     }
  35.   }
  36.   return IRQ_RETVAL(IRQ_HANDLED);
  37. }

  38. //misc opt
  39. static int s3c2440_buttons_open(struct inode *inode,struct file *file){
  40.   int i;
  41.   int err=0;

  42.   for(i=0;i<4;i++){
  43.     if(button_irqs[i]<0){
  44.       continue;
  45.     }

  46.     err=request_irq(button_irqs[i],buttons_isr,IRQ_TYPE_EDGE_RISING,NULL,NULL);
  47.     if(err)
  48.       break;
  49.   }

  50.   if(err){
  51.     i--;
  52.     for(;i>=0;i--){
  53.       if(button_irqs[i]<0)
  54.         continue;
  55.       disable_irq(button_irqs[i]);
  56.       free_irq(button_irqs[i],NULL);
  57.     }
  58.     return -EBUSY;
  59.   }

  60.   ev_press=0;
  61.   return 0;
  62. }
  63. static int s3c2440_buttons_close(struct inode *inode,struct file *file){
  64.   int i;
  65.   for(i=0;i<4;i++){
  66.     if(button_irqs[i]<0)
  67.       continue;
  68.     free_irq(button_irqs[i],NULL);
  69.   }
  70.   return 0;
  71. }
  72. static int s3c2440_buttons_read(struct file *filp,char __user *buff,size_t count,loff_t *offp){
  73.   unsigned long err;
  74.   if(!ev_press){
  75.     if(filp->f_flags&O_NONBLOCK)
  76.       return -EAGAIN;
  77.     else
  78.       wait_event_interruptible(button_waitq,ev_press);
  79.   }
  80.   ev_press=0;
  81.   err=copy_to_user(buff,&key_value,sizeof(key_value));
  82.   return sizeof(key_value);
  83. }
  84. static unsigned int s3c2440_buttons_poll(struct file *file,struct poll_table_struct *wait){
  85.   unsigned int mask=0;
  86.   poll_wait(file,&button_waitq,wait);

  87.   if(ev_press)
  88.     mask |= (POLLIN|POLLRDNORM); //can read
  89.   return mask;
  90. }
  91. //misc ops
  92. static struct file_operations s3c2440_buttons_fops={
  93.   .owner=THIS_MODULE,
  94.   .open=s3c2440_buttons_open,
  95.   .release=s3c2440_buttons_close,
  96.   .read=s3c2440_buttons_read,
  97.   .poll=s3c2440_buttons_poll,
  98. };

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

  105. //driver
  106. static int s3c2440_buttons_probe(struct platform_device *pdev){
  107.   struct resource *res;
  108.   struct device *dev;
  109.   int ret;
  110.   int size;
  111.   int i;

  112.   printk("probe:driver-device mach ok.\n");
  113.   dev=&pdev->dev;
  114.   
  115.   res=platform_get_resource(pdev,IORESOURCE_MEM,0);
  116.   if(res==NULL){
  117.     dev_err(dev,"no memory resource specified.\n");
  118.     return -ENOENT;
  119.   }
  120.   
  121.   //alloc PA
  122.   size=(res->end-res->start)+1;
  123.   button_mem=request_mem_region(res->start,size,pdev->name);
  124.   if(button_mem==NULL){
  125.     dev_err(dev,"failed to get memory region.\n");
  126.     ret=-ENOENT;
  127.     goto err_req;
  128.   }
  129.   //remap:PA->VA
  130.   button_base=ioremap(res->start,size);
  131.   if(button_base==NULL){
  132.     dev_err(dev,"failed to ioremap region.\n");
  133.     ret=-EINVAL;
  134.     goto err_req;
  135.   }
  136.   printk(KERN_DEBUG"probe:mapped button_base=%p.\n",button_base);
  137.   
  138.   for(i=0;i<4;i++){
  139.     button_irq=platform_get_resource(pdev,IORESOURCE_IRQ,i);
  140.     if(button_irq==NULL){
  141.       dev_err(dev,"no irq resource specified.\n");
  142.       ret=-ENOENT;
  143.       goto err_map;
  144.     }
  145.     button_irqs[i]=button_irq->start;
  146.     printk("button_irqs[%d]=%d.\n",i,button_irqs[i]);
  147.   }
  148.   
  149.   ret=misc_register(&s3c2440_miscdev);

  150.   return 0;

  151. err_map:
  152.   iounmap(button_base);
  153. err_req:
  154.   release_resource(button_mem);
  155.   kfree(button_mem);

  156.   return ret;
  157. }
  158. static int s3c2440_buttons_remove(struct platform_device *dev){
  159.   release_resource(button_mem);
  160.   kfree(button_mem);
  161.   button_mem=NULL;

  162.   iounmap(button_base);
  163.   misc_deregister(&s3c2440_miscdev);
  164.   printk("dirver find device unliuged.\n");
  165.   return 0;
  166. }

  167. static struct platform_driver buttons_driver={
  168.   .probe=s3c2440_buttons_probe,
  169.   .remove=s3c2440_buttons_remove,
  170.   .driver={
  171.     .owner=THIS_MODULE,
  172.     .name="2440-buttons",
  173.   },
  174. };


  175. static int buttons_init(void){
  176.   printk("2440 buttons driver init.\n");

  177.   //driver register
  178.   platform_driver_register(&buttons_driver);

  179.   return 0;
  180. }

  181. static void buttons_exit(void){
  182.   platform_driver_unregister(&buttons_driver);
  183. }
  184. module_init(buttons_init);
  185. module_exit(buttons_exit);

  186. MODULE_LICENSE("GPL");
6.测试程序
   根据驱动设计特点,编写测试程序如下:
app_button.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.   int key_value;

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

  20.   for(;;){
  21.     fd_set rds;
  22.     int ret;

  23.     FD_ZERO(&rds);
  24.     FD_SET(buttons_fd,&rds);

  25.     ret=select(buttons_fd+1,&rds,NULL,NULL,NULL);
  26.     if(ret<0){
  27.       perror("select error.\n");
  28.       exit(1);
  29.     }
  30.     if(ret==0){
  31.       printf("timerout.\n");
  32.     }
  33.     else{
  34.       if(FD_ISSET(buttons_fd,&rds)){
  35.         int ret1=read(buttons_fd,&key_value,sizeof(key_value));
  36.         if(ret1!=sizeof(key_value)){
  37.           if(errno!=EAGAIN)
  38.             perror("read buttons\n");
  39.           continue;
  40.         }
  41.         else{
  42.           printf("buttons_value:%d.\n",key_value+1);
  43.         }
  44.       }
  45.     }
  46.   }
  47.   close(buttons_fd);
  48.   return 0;
  49. }
7.编译内核模块和测试程序,生成plat_device.ko、plat_driver.ko和app_button,通过nfs方式下载至TQ2440开发板,运行后,结果如下:

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