驱动程序实例(四):按键驱动程序(platform + input子系统 + 外部中断方式)
结合之前对Linux内核的platform总线与input子系统的分析 ,本文将编写基于platform总线和input子系统的Button设备的实例代码并对其进行分析。
platform总线的分析,详见Linux platform驱动模型。
input子系统的分析,详见Linux字符设备驱动框架(四):Linux内核的input子系统。
硬件接口:
CPU:s5pv210;
Button的GPIO:GPIO_H0_2,EINT2;
LED的工作方式:按键弹起,低电平;按键按下,高电平。
1. device
在/kernel/arch/arm/mach-s5pv210/include/mach目录下,建立一个buttons_gpio.h文件,并填充如下内容。
#ifndef __ASM_ARCH_BUTTONSGPIO_H #define __ASM_ARCH_BUTTONSGPIO_H "buttons-gpio.h"//定义一个Button设备的数据结构 struct s5pv210_button_platdata {char *name;unsigned int gpio;unsigned int irqnum;unsigned int flags; };#endif
在/kernel/arch/arm/mach-s5pv210/mach-x210.c下,添加如下内容,并添加对buttons_gpio.h的包含。
/*Buttons*/static struct s5pv210_button_platdata s5pv210_button_pdata = {.name = "button1",.gpio = S5PV210_GPH0(2),.irqnum = IRQ_EINT2,//中断号.flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,//上升沿触发+下降沿触发 };static struct platform_device s5pv210_button = {.name = "s5pv210_button",.id = 1,.dev = {.platform_data = &s5pv210_button_pdata,}, };
将LED设备信息集成至smdkc110_devices,内核初始化时smdkc110_devices中的设备将被注册进内核。
static struct platform_device *smdkc110_devices[] __initdata = {......&s5pv210_button,};
2. driver
#include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/slab.h> #include <linux/input.h> #include <mach/buttons_gpio.h> #include <mach/hardware.h> #include <mach/regs-gpio.h> #include <mach/irqs.h> #include <linux/interrupt.h>static struct s5pv210_button_platdata *pdata; static struct input_dev *button_dev = NULL;static irqreturn_t button_interrupt(int irq, void *dummy) { int flag;s3c_gpio_cfgpin(pdata->gpio, S3C_GPIO_SFN(0x0)); //设置GPIO为input模式flag = gpio_get_value(pdata->gpio); //读取GPIO的值s3c_gpio_cfgpin(pdata->gpio, S3C_GPIO_SFN(0x0f));//设置GPIO为eint2模式 input_report_key(button_dev, KEY_LEFT, !flag); //上报事件input_sync(button_dev); //同步事件return IRQ_HANDLED; }static int s5pv210_button_remove(struct platform_device *dev) {input_free_device(button_dev); //释放button_dev内存free_irq(pdata->irqnum, button_interrupt);//释放中断资源gpio_free(pdata->gpio); //释放GPIOreturn 0; }static int s5pv210_button_probe(struct platform_device *dev) {int ret;pdata = dev->dev.platform_data;/*****************************申请资源******************************///申请GPIOret = gpio_request(pdata->gpio, pdata->name);if (ret) {printk(KERN_ERR "gpio_request failed, ret = %d.\n", ret);return -EBUSY;} //申请IRQif (request_irq(pdata->irqnum, button_interrupt, pdata->flags, pdata->name, NULL)) { printk(KERN_ERR "key-s5pv210.c: Can't allocate irq %d\n", pdata->irqnum);ret = -EBUSY;goto ERR_STER0;}/************************初始化GPIO资源*************************/s3c_gpio_setpull(pdata->gpio, S3C_GPIO_PULL_UP); //设置GPIO为上拉模式s3c_gpio_cfgpin(pdata->gpio, S3C_GPIO_SFN(0x0f));//设置GPIO为eint模式/*******************************创建接口*******************************///申请button_dev内存空间button_dev = input_allocate_device();if(!button_dev){ret = -ENOMEM;goto ERR_STER1;}//初始化button_devset_bit(EV_KEY, button_dev->evbit); //支持EV_KEY事件set_bit(KEY_LEFT, button_dev->keybit); //支持KEY_LEFT子事件//注册button_devif(input_register_device(button_dev) != 0){printk("s5pv210-button input register device fail!!\n");ret = -ENODEV;goto ERR_STER2;}return 0;/****************************倒映式错误处理****************************/ ERR_STER2:input_free_device(button_dev);ERR_STER1:free_irq(pdata->irqnum, button_interrupt);ERR_STER0:gpio_free(pdata->gpio);return ret; }//定义并初始化驱动信息 static struct platform_driver s5pv210_button_driver = {.probe = s5pv210_button_probe,.remove = s5pv210_button_remove,.driver = {.name = "s5pv210_button",.owner = THIS_MODULE,}, };//注册驱动 static int __init s5pv210_button_init(void) {return platform_driver_register(&s5pv210_button_driver); }//注销驱动 static void __exit s5pv210_button_exit(void) {platform_driver_unregister(&s5pv210_button_driver); }module_init(s5pv210_button_init); module_exit(s5pv210_button_exit);MODULE_AUTHOR("Lin"); MODULE_DESCRIPTION("S5PV210 BUTTON driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:s5pv210_button");
3. 测试
编写一个简易的应用程序,来测试上述驱动程序。
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <linux/input.h> #include <string.h>#define X210_KEY "/dev/input/event1"int main(void) {int fd = -1, ret = -1;struct input_event ev;//打开设备文件fd = open(X210_KEY, O_RDONLY);if (fd < 0){perror("open");return -1;}while (1){//读取一个event事件包memset(&ev, 0, sizeof(struct input_event));ret = read(fd, &ev, sizeof(struct input_event));if (ret != sizeof(struct input_event)){perror("read");close(fd);return -1;}//解析event包printf("-------------------------\n");printf("type: %hd\n", ev.type);printf("code: %hd\n", ev.code);printf("value: %d\n", ev.value);printf("\n");}//关闭设备 close(fd);return 0; }
装载驱动模块后,在Linux终端运行该应用程序。在一次按键按下并弹起的过程中,终端中将打印出如下的信息,表明驱动程序工作正常。
-------------------------//按键按下 type: 1 code: 105 value: 1-------------------------//同步事件 type: 0 code: 0 value: 0-------------------------//按键弹起 type: 1 code: 105 value: 0-------------------------//同步事件 type: 0 code: 0 value: 0
转载于:https://www.cnblogs.com/linfeng-learning/p/9468018.html
驱动程序实例(四):按键驱动程序(platform + input子系统 + 外部中断方式)相关推荐
- CC2530学习(四)休眠模式配置及外部中断/睡眠时钟唤醒
文章目录 一.硬件连接 二.寄存器描述(外部中断) (一).睡眠模式设置 (二).电源模式控制设置 三.示例代码(外部中断) 四.实验现象(外部中断) 五.寄存器描述(睡眠时钟中断) (一).睡眠模式 ...
- platform框架--Linux MISC杂项框架--Linux INPUT子系统框架--串行集成电路总线I2C设备驱动框架--串行外设接口SPI 设备驱动框架---通用异步收发器UART驱动框架
platform框架 input. pinctrl. gpio 子系统都是 Linux 内核针对某一类设备而创建的框架, input子系统是管理输入的子系统 pinctrl 子系统重点是设置 PIN( ...
- Linux 驱动开发 四十八:Linux INPUT 子系统实验
一.input 子系统简介 input 就是输入的意思,因此 input 子系统就是管理输入的子系统,是 Linux 内核针对某一类设备而创建的框架. 比如按键输入.键盘.鼠标.触摸屏等等这些都属于输 ...
- 三个子系统_「正点原子Linux连载」第五十八章Linux INPUT子系统实验(一)
1)实验平台:正点原子Linux开发板 2)摘自<正点原子I.MX6U嵌入式Linux驱动开发指南> 关注官方微信号公众号,获取更多资料:正点原子 第五十八章Linux INPUT子系统实 ...
- input type类型_设备树下的input子系统
更多文章请关注公众号 :麻瓜技术闲谈 input 就是输入的意思,因此 input 子系统就是管理输入的子系统,和 pinctrl 和 gpio 子系统一样,都是 Linux 内核针对某一类设备而 ...
- Linux Input子系统
1. Input子系统 按键.鼠标.键盘.触摸屏等都属于输入(input)设备,Linux 内核为此专门做了一个叫做 input子系统的框架来处理输入事件.输入设备本质上还是字符设备,只是在此基础上套 ...
- (五)DSP28335基础教程——外部中断控制(按键触发)
0 前言 本期实验目标:采用外部中断方式响应按键触发,实现LED电平反转. 外部中断是DSP十分常用的功能,通常用来响应一些控制操作,比如判断按键是否按下,传感器是否接收到信号等等.那么通过该例程,大 ...
- STM32按键消抖的几种实现方式-STM32 Button Debouncing
一.按键抖动的现象 按键按下和松开的时候,按键金属片之间的贴合.分离有一个过程.给STM32输入的信号并不是理想的0和1切换的过程.而是如下图所示的,按下和松开的一小段时间内按键信号出现抖动(jitt ...
- 嵌入式linux设备驱动程序是,嵌入式Linux设备驱动开发之:按键驱动程序实例-嵌入式系统-与非网...
11.6 按键驱动程序实例 11.6.1 按键工作原理 LED和蜂鸣器是最简单的GPIO的应用,都不需要任何外部输入或控制.按键同样使用GPIO接口,但按键本身需要外部的输入,即在驱动程序中要处理 ...
最新文章
- CCNP-22 路由重发布2(BSCI)
- ATG中的定时Job处理
- 北大教授:到底什么才是有效的教育?
- 图论学习四之Disjoint set union并查集
- Maven多模块打包遇到的问题详解
- iscsi-target
- 输入URL经历的过程
- linux浮动ip添加 手动,在Linux 双机下自己手动实现浮动ip技术
- Atitit 提升开发效率 通道化驱动化数据操作与查询 目录 1. xiaoguo	1 1.1. Atitit mybatis 简化开发与提升开发效率法	1 2. Code	1 3. ref	4
- 国内著名高校飞跃手册整理
- 初识DNA甲基化芯片
- phpcms修改了配置文件之后出现Warning: date() expects parameter 2 to be long..错误
- 国产CAD_谁说国产系统没有CAD软件可以用?
- 认识Http协议(超文本传输协议)
- tesseract的使用
- QCustomPlot 连续快速地调用replot()改善速度
- UE4贴图自适应屏幕大小
- Android开发踩坑之旅
- AD中的机械尺寸定位的使用
- 安卓图像更新学习总结