platform总线按键驱动分析(精华版)

本文详述了Linux平台下按键驱动的实现,重点在于理解按键的消抖和中断处理。通过分析kbd_driver.c和kbd_device.c,阐述了如何在设备链表和驱动链表中进行绑定。介绍了request_irq()函数用于申请中断,以及利用定时器进行消抖的操作。文章还提及中断的上半部和下半部的概念,帮助读者深入理解驱动工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:之前关于platform总线按键驱动的分析,几天返回去看时发现排版有很多问题,现在用Markdown重新弄一下,方便阅读。下面是原文:

驱动做了三个多星期了,从helloworld到LED再到PlatformLED,现在终于到了按键驱动,对于驱动的理解深刻了不少,从完全看不懂到现在能够独立分析,进步很大,今天完成了按键驱动,做一个总结性的分享,给后面的自己看!加油!

按键驱动:

与之前不同,这次将按键驱动按照platform总线的理解,设备链表和驱动链表,做成了两个模块,一个kbd_driver.c 一个kbd_device.c 侧重点在理解按键的消抖和中断

中断:我个人理解为你正在看电影,有人叫你出去,你就得暂停出去处理,然后才能回来继续看电影,这就是一个生活中的中断。在开发板上,你也可以带入的理解。

消抖:当你按下按键时,会有微小的抖动,硬件很难消除,我们通过延时来达到消抖的目的。

上代码分析代码:

kbd_driver.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <mach/hardware.h>
#include <asm/gpio.h>
#include <asm/irq.h>
#include <linux/slab.h>
#include <mach/regs-gpio.h>

#include "kbd_driver.h"

/* 1HZ=100*jiffies 1*jiffies=10ms => 1HZ=100*10ms = 1s  这是在设置时钟/
#define CANCEL_DITHERING_DELAY          (HZ/50)   /* Remove button push down dithering timer delay 20ms     延时 */ 

typedef struct s3c_kbd_s 
{
    struct timer_list           *timers; /* every key get a cancel dithering timer 消抖时间*/
    struct input_dev            *input_dev;
    s3c_kbd_platform_data_t     *pdata;
} s3c_kbd_t;  /*---  end of struct s3c_kbd_s  ---*/


s3c_kbd_t                       *s3c_kbd = NULL;

static irqreturn_t s3c_kbd_intterupt(int irq, void *dev_id)     //见139行,一旦发生中断后,将中断号传过来
{
    int                         i;
    int                         found = 0;
    struct platform_device      *pdev =  dev_id;
    s3c_kbd_t                   *s3c_kbd = NULL;

    s3c_kbd = platform_get_drvdata(pdev);

    for(i=0; i<s3c_kbd->pdata->nkeys; i++)  //寻找中断号
    {
        if(irq == s3c_kbd->pdata->keys[i].nIRQ)
        {
            found = 1;
            break;
        }
    }

    if(!found) /*  An ERROR interrupt */
        return IRQ_NONE;

    mod_timer(&s3c_kbd->timers[i], jiffies+CANCEL_DITHERING_DELAY); //消抖定时器,延时      jiffies是当前时间由内核维护
    //中断的处理涉及到上半部和下半部,上半部进行响应然后离开,下半部例如定时器会在这里执行,提高效率。
    return IRQ_HANDLED;  
}

static void  cancel_dithering_timer_handler(unsigned long data)//消抖定时器处理方式:当62行延时结束后就来到这里调用这个函数,看看是否按键按下,这样就利用timer(定时器)来消抖
{
    int                      which =(int)data;
    unsigned int             pinval;  

    pinval = s3c2410_gpio_getpin(s3c_kbd->pdata->keys[which].gpio); //获取按键引脚电平

    if( pinval ) 
    {
        //printk("s3c_kbd key[%d] code[%d] released\n", which, s3c_kbd->pdata->keys[which].code);
        input_event(s3c_kbd->input_dev, EV_KEY, s3c_kbd->pdata->keys[which].code, 0);  
    }
    else
    {
        //printk("s3c_kbd key[%d] code[%d] pressed\n", which, s3c_kbd->pdata->keys[which].code);
        input_event(s3c_kbd->input_dev, EV_KEY, s3c_kbd->pdata->keys[which].code, 1);  
    }

    input_sync(s3c_kbd->input_dev);
}

static int s3c_kbd_probe(struct platform_device *pdev)      //probe()函数传参调用platform_device相应的设备信息,在总线上device和driver name匹配时调用
{
    int                         i = 0;
    int                         rv = -ENOMEM;/*
在内核当中ENOMEM这个宏是这样定义的,表示内存不足
#define ENOMEM    0x05
Description:
ENOMEM - no memory can be allocated by a function in the library. Note that malloc, calloc, and realloc do not set errno to ENOMEM on failure, but other l
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值