`

linux按键驱动程序心得

 
阅读更多
linux按键驱动程序心得
在前一章所讲的按键驱动的时候,用的是循环扫描的方式,在运行的时候通过ps命令查看当前的进程,可以看到这个时候按键驱动程序的cpu占有率是最高的,这是因为,在写应用程序的时候,用的是一个死循环,不管有没有按键按下,都会一直的读取驱动程序传过来的数据,这个死循环是占用cpu最高的,下面这种方法是通过中断的方式来对按键的值进行采样,当有按键按下的时候,驱动程序会唤醒应用程序,应用程序处理所得到的数据,当没有按键按下的时候,驱动程序会一直处于休眠状态,这个时候再用ps命令的时候,查看我们的请用程序,可以看到的是,应用程序的状态时s,是sleep的简称,说明其处于休眠状态。下面就通过对程序的详细注释,来解释其工作原理。
/*
* 注 ,此程序是在友善之臂的基础上面修改简化而来
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/gpio.h> /* 头文件 */
/* 宏定义设备的名称 */
#define DEVICE_NAME "key_init"
/* 默认的按键是处于弹起的状态 */
#define PIN_UP 1
/* 注设备号 */
static int key_major = 191;

/* 采用的是中断表述的方式安排中断 */
/* 这样的好处是在外部中断函数中科一方便中断函数的处理*/
struct button_irq_desc {
int irq; //保存的中断号
int pin; //中断所对的引脚
int pin_setting; //引脚所设置的功能
int number; //在后面可以体会
char *name; //名字
};

static struct button_irq_desc button_irqs [] = {
{IRQ_EINT8 , S3C2410_GPG(0) , S3C2410_GPG0_EINT8 , 0, "KEY0"},
{IRQ_EINT11, S3C2410_GPG(3) , S3C2410_GPG3_EINT11 , 1, "KEY1"},
{IRQ_EINT13, S3C2410_GPG(5) , S3C2410_GPG5_EINT13 , 2, "KEY2"},
{IRQ_EINT14, S3C2410_GPG(6) , S3C2410_GPG6_EINT14 , 3, "KEY3"},
{IRQ_EINT15, S3C2410_GPG(7) , S3C2410_GPG7_EINT15 , 4, "KEY4"},
{IRQ_EINT19, S3C2410_GPG(11), S3C2410_GPG11_EINT19, 5, "KEY5"},
};

/* 默认的按键数组状态,当没有按下的时候,数组的值都是零, */
static volatile char key_values [6] = {0, 0, 0, 0, 0, 0};
/* 创建等待队列,当满足条件的时候 */
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
/* 这个变量很重要。后面赘述 */
static volatile int ev_press = 0;

/* 这个是中断处理函数 */
static irqreturn_t buttons_interrupt(int irq, void *dev_id) /* 这个函数,当中断发生的时候,传过来的参数是中断号,和中断的描述信息 */
{
struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id; // 得到这个描述结构
int down; //用来保存当前的引脚状态

down = s3c2410_gpio_getpin(button_irqs->pin);//如果被按下的话,必为零

if ( !down ) { // down被设置为0,然后设置数组

key_values[button_irqs->number] = PIN_UP; //前面定义的一个宏,为1,这个的意思是,当有按键按下的时候,就把相应的按键所对应的值进行置位
//ev_press = 1; //这个就是刚才定义的变量关于等待队列的作用,与睡眠和唤醒的条件
//wake_up_interruptible(&button_waitq);这个是唤醒相应队列的函数
//wait_event_interruptible(button_waitq, ev_press);这个是休眠的函数
//当ev_press为1的时候唤醒,当为0的时候休眠
wake_up_interruptible(&button_waitq);
}
return IRQ_RETVAL(IRQ_HANDLED);
}


static int s3c24xx_buttons_open(struct inode *inode, struct file *file)
{
int i;
int err = 0;
for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
if (button_irqs[i].irq < 0) {
continue;
}
//这个是注册中断用的。
err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_FALLING,
button_irqs[i].name, (void *)&button_irqs[i]);
if (err)
break;
}

if (err) {
i--;
for (; i >= 0; i--) {
if (button_irqs[i].irq < 0) {
continue;
}
disable_irq(button_irqs[i].irq);
free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
}
return -EBUSY;
}

ev_press = 1;
return 0;
}


static int s3c24xx_buttons_close(struct inode *inode, struct file *file)
{
int i;
for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
if (button_irqs[i].irq < 0) {
continue;
}
//free_irq();反注册中断
free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
}

return 0;
}


static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
unsigned long err;
unsigned int numb;

wait_event_interruptible(button_waitq, ev_press);
ev_press = 0;
/* 已经传递完成 */
err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count));
/* 已经清除这个关键的数组 */
for(numb=0;numb<=5;numb++)
{
key_values[numb]=0;
}
return err ? -EFAULT : min(sizeof(key_values), count);
}



static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = s3c24xx_buttons_open,
.release = s3c24xx_buttons_close,
.read = s3c24xx_buttons_read,
};


static int __init dev_init(void)
{
int ret;

ret = register_chrdev(key_major, DEVICE_NAME,&dev_fops);

printk (DEVICE_NAME"\tinitialized\n");

return ret;
}

static void __exit dev_exit(void)
{
unregister_chrdev(key_major,DEVICE_NAME);
}

module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("friendlyarm inc.");
到这里就完成了驱动程序的编写

下面是应用程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>

int main(void)
{
int buttons_fd;
char buttons[6] = {0, 0, 0, 0, 0, 0};

buttons_fd = open("/dev/key_int", 0);
if (buttons_fd < 0) {
perror("open device key_int");
exit(1);
}

for (;;) {
int i;
if (read(buttons_fd, buttons, sizeof buttons) != sizeof buttons) {
perror("read buttons:");
exit(1);
}

for (i = 0; i < sizeof buttons / sizeof buttons[0]; i++) { //当读到的数组中有变化,说明有按键被按下,读取那个按键,并标记
if (buttons[i]) {
printf("key[%d] has pressed\n",i+1);
}
}
}

close(buttons_fd);
return 0;
}


至此这个驱动加测试完成了,效果如下图所示

图片

当按键按下的时候就会出现如图所示的输出。

用ps命令查看当前的进程

图片

key_test程序在没有按键按下的时候一直处于s状态,也就是休眠状态

重点详解,容易不解
-------仅供自己参考

分享到:
评论

相关推荐

    linux按键驱动程序

    "Linux按键驱动程序" Linux按键驱动程序是嵌入式Linux系统中的一种设备驱动程序,负责处理按键输入事件。本驱动程序使用了Linux内核提供的各种API和数据结构来完成按键事件的检测和处理。 Linux按键驱动程序的主要...

    嵌入式linux按键驱动程序的设计.pdf

    嵌入式Linux按键驱动程序的设计 Linux操作系统在嵌入式系统中的应用非常广泛, Linux操作系统凭借其功能强大、免费以及开发资源丰富等优势,占据了嵌入式操作系统的主导地位。在Linux系统下键盘驱动程序设计的方法...

    LINUX设备驱动程序

    在Linux系统中,设备驱动程序是操作系统与硬件设备之间的桥梁,它们使得操作系统能够高效地管理和控制硬件资源。这里我们主要探讨的是与嵌入式开发相关的Linux设备驱动程序,特别是针对ARM架构,如6410处理器的开发...

    嵌入式linux按键驱动程序源代码和Makefile编译文件源代码

    本文将深入探讨嵌入式Linux下的按键驱动程序源代码及其Makefile编译文件,帮助理解如何在这样的环境中实现硬件交互。 首先,让我们关注按键驱动程序。在嵌入式设备上,按键通常作为用户输入设备,用于触发特定操作...

    嵌入式Linux按键驱动,支持短按和长按检测

    在嵌入式Linux系统中,按键驱动是与用户交互的重要组成部分。本文将深入探讨如何实现一个支持短按和长按检测的按键驱动,利用平台驱动框架、按键中断、内核定时器以及POLL机制,确保在休眠-唤醒场景下也能高效工作,...

    Linux设备驱动程序开发基础(PPT)

    驱动程序的注册与注销是指驱动程序与 Linux 内核的交互,设备的打开与释放是指驱动程序与设备的交互,设备的读写操作是指驱动程序对设备的读写操作,设备的控制操作是指驱动程序对设备的控制操作,设备的中断和轮询...

    ARM11 linux按键驱动程序

    ARM11 Linux 按键驱动程序是针对基于 ARM11 架构的嵌入式设备设计的关键软件组件,用于处理硬件按键的输入事件。在 Linux 内核中,驱动程序是连接硬件设备与操作系统之间的桥梁,使得操作系统能够识别和控制硬件。在...

    Linux 设备驱动程序(PDF版)

    Linux设备驱动程序是一种特殊的软件模块,它为操作系统提供了与硬件通信的接口。驱动程序能够控制硬件设备的行为,使得操作系统能够安全、有效地使用这些硬件资源。编写Linux设备驱动程序通常需要深入了解操作系统的...

    一个完美的tq2440的linux按键驱动程序

    本主题聚焦于一个特别针对tq2440嵌入式平台的按键驱动程序,该驱动程序被称为“一个近乎完美的按键驱动程序”,并且包含了一个完整的Makefile,方便编译构建。 tq2440是一款基于Samsung S3C2440处理器的开发板,...

    linux按键驱动 轮询input上报可做linux 矩阵键盘的按键驱动

    linux按键驱动 轮询input上报可做linux 矩阵键盘的按键驱动,通过input子系统上报,devinputeventx 接收事件可用于指定QT产生类似键盘的输入事件.zip

    深入Linux设备驱动程序内核机制.pdf

    Linux设备驱动程序是操作系统与硬件之间的重要桥梁,它们负责处理硬件操作,使应用程序能够与硬件进行通信。在Linux内核中,设备驱动程序是作为内核模块编写的,可以动态加载或卸载,以增强系统的灵活性。本文深入...

    linux设备驱动程序 (中文第二版)

    《Linux设备驱动程序》(中文第二版)是一本深度探讨Linux系统下设备驱动程序开发的专业书籍,对于想要深入了解Linux内核以及如何与硬件交互的开发者来说,是不可或缺的参考资料。这本书详细介绍了Linux环境下设备...

    深入linux设备驱动程序内核机制

    《深入Linux设备驱动程序内核机制》一书探讨了Linux内核与设备驱动程序的紧密关系,旨在帮助读者深入理解如何有效地编写和优化Linux设备驱动。书中不仅关注内核模块的构建,还涉及驱动程序与内核交互的关键技术,如...

    Linux设备驱动程序

    《Linux设备驱动程序》是关于Linux操作系统下设备驱动程序开发的重要参考书籍,尤其适用于嵌入式ARM平台的开发者。在Linux系统中,设备驱动程序是操作系统与硬件设备之间的桥梁,它使得操作系统能够控制和管理硬件...

    Linux设备驱动程序设计入门

    Linux 设备驱动程序设计入门 本文将对 Linux 设备驱动程序设计入门进行详细的解释,并对相关知识点进行总结。 1. Linux 设备驱动程序设计的重要性 Linux 设备驱动程序设计是 Linux 软件工程师中最重要和最复杂的...

    linux按键驱动讲解

    在 Linux 内核中,按键驱动是用于处理输入设备(如键盘)的一种特殊类型的驱动程序。这类驱动的主要任务是从硬件读取按键状态,并将这些状态转换为用户空间可以理解的形式。按键驱动通常需要支持多个按键的检测,并...

    Linux设备驱动程序.pdf

    Linux设备驱动程序是操作系统与硬件设备之间的通信中介,负责管理硬件设备与Linux内核间的交互。Linux设备驱动第三版是一本详细讲解Linux设备驱动开发的书籍,涵盖了从基础知识到高级技术的广泛主题。 在第1章中,...

    如何编写Linux设备驱动程序

    "如何编写Linux设备驱动程序" 一、Linux设备驱动程序的概念 Linux设备驱动程序是操作系统内核和机器硬件之间的接口,设备驱动程序为应用程序屏蔽了硬件的细节,使应用程序可以象操作普通文件一样对硬件设备进行...

    精通LINUX设备驱动程序开发.pdf

    Linux设备驱动程序开发是Linux操作系统中一项非常核心的技术,涉及到底层硬件与操作系统之间的交互。精通这一技术,意味着可以开发出适合特定硬件设备的驱动程序,进而实现设备功能的充分发挥。本书《精通LINUX设备...

    Linux设备驱动程序 第三版 附源码)

    《Linux设备驱动程序 第三版》是一本专为Linux初学者和进阶者设计的教程,旨在帮助读者深入理解Linux操作系统中的设备驱动程序开发。这本书是Linux学习路径中不可或缺的一环,作者建议在阅读完《Unix环境高级编程》...

Global site tag (gtag.js) - Google Analytics