S5PV210(TQ210)学习笔记——输入子系统驱动

发布者:幸福之路最新更新时间:2015-08-19 来源: eefocus关键字:S5PV210  输入子系统 手机看文章 扫描二维码
随时随地手机看文章
前面的文章简单的讲述了字符设备驱动程序的编写,用字符设备驱动的方式实现了按键驱动,但是,出了我们的自己编写的针对我们的这个驱动程序的应用程序之外,其他应用程序都无法接收我们这个驱动的键值输入,为了让所有应用程序都可以接收我们的按键驱动解析的键值,Linux内核定义了“输入子系统”的概念,也就是说,只要我们按照这个模型进行驱动开发,并为其提供必须的接口函数,那么,Linux内核就可以正常来获取我们的键盘值了。

输入子系统的原理分析强烈推荐观看韦东山老师的视频讲座,讲的非常清楚,我这里是按照输入子系统的方式实现的按键驱动,下面是源码,放在这里做个备份:

  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7.   
  8. static struct input_dev *buttons_dev;  
  9. static struct timer_list timer;  
  10. struct button_desc* button_desc = NULL;  
  11.   
  12. struct button_desc{  
  13.     char* name;  
  14.     unsigned int pin;  
  15.     unsigned int irq;  
  16.     unsigned int val;  
  17. };  
  18.   
  19. static struct button_desc buttons_desc[8] = {  
  20.     [0] = {  
  21.         .name = "S1",  
  22.         .pin = S5PV210_GPH0(0),  
  23.         .irq = IRQ_EINT(0),  
  24.         .val = KEY_L,  
  25.     },  
  26.   
  27.     [1] = {  
  28.         .name = "S2",  
  29.         .pin = S5PV210_GPH0(1),  
  30.         .irq = IRQ_EINT(1),  
  31.         .val = KEY_S,  
  32.     },  
  33.   
  34.     [2] = {  
  35.         .name = "S3",  
  36.         .pin = S5PV210_GPH0(2),  
  37.         .irq = IRQ_EINT(2),  
  38.         .val = KEY_C,  
  39.     },  
  40.   
  41.     [3] = {  
  42.         .name = "S4",  
  43.         .pin = S5PV210_GPH0(3),  
  44.         .irq = IRQ_EINT(3),  
  45.         .val = KEY_ENTER,  
  46.     },  
  47.   
  48.     [4] = {  
  49.         .name = "S5",  
  50.         .pin = S5PV210_GPH0(4),  
  51.         .irq = IRQ_EINT(4),  
  52.         .val = KEY_LEFTCTRL,  
  53.     },  
  54.   
  55.     [5] = {  
  56.         .name = "S6",  
  57.         .pin = S5PV210_GPH0(5),  
  58.         .irq = IRQ_EINT(5),  
  59.         .val = KEY_MINUS,  
  60.     },  
  61.   
  62.     [6] = {  
  63.         .name = "S7",  
  64.         .pin = S5PV210_GPH2(6),  
  65.         .irq = IRQ_EINT(22),  
  66.         .val = KEY_CAPSLOCK,  
  67.     },  
  68.   
  69.     [7] = {  
  70.         .name = "S8",  
  71.         .pin = S5PV210_GPH2(7),  
  72.         .irq = IRQ_EINT(23),  
  73.         .val = KEY_SPACE,  
  74.     },  
  75. };  
  76.   
  77. static void timer_function(unsigned long data){  
  78.     if(button_desc == NULL)  
  79.         return;  
  80.   
  81.     if(gpio_get_value(button_desc->pin)){  
  82.         input_event(buttons_dev, EV_KEY, button_desc->val, 0);  
  83.     }  
  84.     else{  
  85.         input_event(buttons_dev, EV_KEY, button_desc->val, 1);  
  86.     }  
  87.     input_sync(buttons_dev);  
  88. }  
  89.   
  90. static irqreturn_t irq_handler(int irq, void *devid){  
  91.     button_desc = (struct button_desc*)devid;  
  92.     mod_timer(&timer, jiffies + HZ/100);  
  93.     return IRQ_RETVAL(IRQ_HANDLED);  
  94. }  
  95.   
  96. static int buttons_init(void){  
  97.     int i;  
  98.       
  99.     buttons_dev = input_allocate_device();  
  100.     if(buttons_dev == NULL){  
  101.         printk(KERN_ERR "Error: allocate input device failed! ");  
  102.         return -ENOMEM;  
  103.     }  
  104.   
  105.     __set_bit(EV_KEY, buttons_dev->evbit);  
  106.     __set_bit(EV_REP, buttons_dev->evbit);  
  107.   
  108.     __set_bit(KEY_L,        buttons_dev->keybit);  
  109.     __set_bit(KEY_S,        buttons_dev->keybit);  
  110.     __set_bit(KEY_C,        buttons_dev->keybit);  
  111.     __set_bit(KEY_SPACE,    buttons_dev->keybit);  
  112.     __set_bit(KEY_MINUS,    buttons_dev->keybit);  
  113.     __set_bit(KEY_ENTER,    buttons_dev->keybit);  
  114.     __set_bit(KEY_LEFTCTRL, buttons_dev->keybit);  
  115.     __set_bit(KEY_CAPSLOCK, buttons_dev->keybit);  
  116.   
  117.     printk("1 ");  
  118.     if(input_register_device(buttons_dev)){  
  119.         goto error_1;  
  120.     }  
  121.   
  122.     printk("2 ");  
  123.     init_timer(&timer);  
  124.     timer.function = timer_function;  
  125.     add_timer(&timer);  
  126.   
  127.     printk("3 ");  
  128.     for(i = 0; i != 8; ++i){  
  129.         if(request_irq(buttons_desc[i].irq, irq_handler,   
  130.             IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, buttons_desc[i].name, &buttons_desc[i])){  
  131.             goto error_2;  
  132.         }  
  133.     }  
  134.     printk("4 ");  
  135.       
  136.     return 0;  
  137.   
  138. error_2:  
  139.     for(--i; i >= 0; --i){  
  140.         free_irq(buttons_desc[i].irq, &buttons_desc[i]);  
  141.     }  
  142.     input_unregister_device(buttons_dev);  
  143.   
  144. error_1:  
  145.     input_free_device(buttons_dev);  
  146.   
  147.     return -EBUSY;  
  148. }  
  149.   
  150. static void buttons_exit(void){  
  151.     int i;  
  152.     for(i = 0; i != 8; ++i){  
  153.         free_irq(buttons_desc[i].irq, &buttons_desc[i]);  
  154.     }  
  155.   
  156.     input_unregister_device(buttons_dev);  
  157.     input_free_device(buttons_dev);  
  158. }  
  159.   
  160. module_init(buttons_init);  
  161. module_exit(buttons_exit);  
  162. MODULE_LICENSE("GPL");  

 

很显然,基于输入子系统的按键驱动比起直接编写的字符驱动设备要简单的多,不过按键消抖还是要加的,上面的代码加上了按键消抖。如果在开发过程中遇到了什么问题,还是欢迎留言讨论。

关键字:S5PV210  输入子系统 引用地址:S5PV210(TQ210)学习笔记——输入子系统驱动

上一篇:S5PV210(TQ210)学习笔记——LCD驱动编写
下一篇:S5PV210(TQ210)学习笔记——按键驱动程序

推荐阅读最新更新时间:2024-03-16 14:29

TQ210——S5PV210中断体系
中断是指 CPU 在执行程序的过程中,遇到异常情况需要处理, CPU停 止当前程序的运行,保存当前程序运行处的必要参数,转去处理这些异常情况, 处理结束后再返回当前程序的间断处,继续执行原程序。 1、异常向量表 2、一级异常处理 #define pExceptionIRQ ( *((volatile unsigned long *)(0xD0037418)) ) pExceptionIRQ = (unsigned long)IRQ_handle; IRQ_handle: sub lr, lr, #4 // 保存现场 stmfdsp!, {r0-r12, l
[单片机]
TQ210——<font color='red'>S5PV210</font>中断体系
S5PV210串行通信接口详解-3
1、串行通信与中断的关系 (1)、串口通信分为发送 / 接收2部分。发送方一般不需要(也可以使用)中断即可完成发送,接收方必须(一般来说必须,也可以轮询方式接收就是CPU一直盯着收)使用中断来接收。 (2)、发送方可以选择使用中断,也可以选择不使用中断。使用中断的工作情景是:发送方先设置好中断并绑定一个中断处理程序,然后发送方丢一帧数据给transmitter,transmitter发送耗费一段时间来发送这一帧数据,这段时间内我们的发送方CPU可以去做别的事情,等transmitter发送完成后会产生一个TXD中断,该中断会导致事先绑定的中断处理程序执行,在这个中断处理程序中CPU会切换回来继续给transmitter放一帧数据,
[单片机]
<font color='red'>S5PV210</font>串行通信接口详解-3
TQ210 —— s5pv210 start.S分析
/* * armboot - Startup Code for S5PC110/ARM-Cortex CPU-core * * Copyright (c) 2009 Samsung Electronics * * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License
[单片机]
S5PV210的NandFlash应用(三)
准备分析 经过了《S5PV210的NandFlash应用(二)》对于二进制文件前16k的存取方式都了一定的了解。这次要证明的是第NandFlash第4页以后存取方式。《S5PV210的NandFlash应用(二)》里边的210.bin(大小为16k)是以存到4k为单位存到了前4页(0, 1, 2 ,3)的每页的前4k处。为此我自己写了一个8k的二进制文件(名字叫AB),贴在210.bin的后边,按照推断这8k应该存在了第4页。然后改到nand_cp.c以8k的方式,读取第4页,然后数据都输出到串口,再与原二进制文件对比。 资源工具 同《 S5PV210的LED应用(一)》 NandFlash: K9GAG08U0F (
[单片机]
<font color='red'>S5PV210</font>的NandFlash应用(三)
S5PV210(TQ210)学习笔记——内存配置(DDR2)
S5PV210有两个独立的DRAM控制器,分别是DMC0和DMC1,其中,DMC0最大支持512MByte,DMC1最大支持1GByte,而DMC0和DMC1又同时支持两个片选CS0和CS1。S5PV210的内存模块相比2440和6410来讲要更加复杂一些,要想正确的配置S5PV210的内存,应该仔细阅读芯片手册相关部分,在配置参数时也应该适当的阅读下内存芯片的手册。这部分的寄存器和配置过程比较复杂(但是不难),我只简单的讲一下我配置时遇到的问题。 一 接线原理 我的开发板是TQ210,开发板上有8片128M*8bits的内存芯片,从原理图上可以看到,其中4片并联接在DMC0上,另外四片并联在DMC1上,这里我只贴出一个链接方式,
[单片机]
<font color='red'>S5PV210</font>(TQ210)学习笔记——内存配置(DDR2)
S5PV210开发 -- 驱动开发相关硬件简介
到此,开发板已经是算跑起来了。系统移植部分稍后再讲。我们先举两个例子,让LED亮起来、蜂鸣器响起来。 一、LED亮起来 (1)LED 正负极 LED 发光二极管,这个没什么好介绍的。主要讲一下它如何判断正负极。 《1》实验法 使用万用表,在检测短路档,将发光二极管接至红黑两表笔之间测试,正负两极与红黑表笔相接时,会发现发光二极管发光,由此判断发光二级管正负极。 《2》目测法 LED 最常用的是直插型的和贴片这两种。 直插型发光二极管: 观察管脚,管脚较长的为正极,较短的为负极。 再者观察内部的两个电极大小。一般来说,电极较小的,个头较矮的一个是正极,电极较大的一个是负极。 贴片发光二极管:
[单片机]
<font color='red'>S5PV210</font>开发 -- 驱动开发相关硬件简介
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved