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

本文作者通过三个星期的学习和实践,深入理解了驱动开发,尤其是平台总线上的按键驱动。文章介绍了如何将按键驱动分为kbd_driver.c和kbd_device.c两个模块,并重点探讨了按键的消抖与中断处理。中断被比喻为看电影时被叫出去处理事情,再返回继续的过程,帮助读者形象理解中断概念。
摘要由CSDN通过智能技术生成

驱动做了三个多星期了,从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;//还记得后面的if语句吗?这里是负值,如果不能正确执行就返回这个值哦!
    struct input_dev            *input_dev = NULL;
    s3c_kbd_platform_data_t     *pdata = pdev->dev.platform_data;//*pdata指向设备信息	从这里看出,驱动和设备的信息被隔离开

    /* malloc s3c_kbd struct	给按键分配结构体  */
    s3c_kbd = kmalloc(sizeof(s3c_kbd_t), GFP_KERNEL);
    if( !s3c_kbd )
    {
        printk("error: s3c_kbd_probe kmalloc() for s3c_kbd failure\n");
        goto fail;
    }
    memset(s3c_kbd, 0, sizeof(s3c_kbd_t));//void *memset(void *s,int c,size_t n)   总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c。内存空间初始化

    /* malloc cancel dithering timer for every key */
    s3c_kbd->timers = (struct timer_list *) kmalloc(pdata->nkeys*sizeof(struct timer_list), GFP_KERNEL);//在linux/gfp.h中定义的一个宏,是分配内核空间的内存时的一个标志位。
    if( !s3c_kbd->timers )
    {
        printk("error: s3c_kbd_probe kmalloc() for s3c_kbd timers failure\n");
        goto fail;
    }
    memset(s3c_k
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值