linux驱动开发fl2440开发板按键驱动

本文介绍FL2440开发板上按键驱动的实现原理及应用过程,包括驱动程序设计、测试方法及故障排查等内容。

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

目录

一、fl2440开发板按键驱动介绍 

二、fl2440开发板按键驱动特点

三、应用

 四、驱动程序编写

五、在开发板上的操作:

六、fl2440开发板按键驱动故障如何排查


———————————————————————————————————————

主机操作系统:Centos 6.7
交叉编译器环境:arm-linux-gcc-4.5.4 
开发板平台: FL2440 
Linux内核版本: linux-3.0 
开发模块: LED_BUTTON
邮箱:leiyuxing205@gmail.com
———————————————————————————————————————

一、fl2440开发板按键驱动介绍 

FL2440开发板有4个按键,分别为K1、K2、K3、K4。这些按键都是矩阵式按键,需要通过按键扫描和矩阵按键原理进行驱动。

按键扫描是指通过程序循环扫描按键端口的状态,判断按键是否按下。矩阵按键原理是指将按键划分成按键矩阵,由行和列两个方向的IO口进行扫描和判断。通过这种方式可以减少IO口数量,降低系统成本。

具体的驱动方法如下:

  1. 初始化按键对应的IO口为输入口。

  2. 在程序中循环扫描每个按键口的状态,判断按键是否按下。

  3. 实现矩阵按键原理,将按键矩阵分组,通过行列扫描判断按键状态。

  4. 对于需要使用中断的按键,设置中断触发条件和中断处理函数。

  5. 在程序中处理按键事件,根据按键状态进行相应的操作。

  6. 避免按键重复触发,可以通过延时或者状态标记进行控制。

以上就是FL2440开发板按键驱动的基本介绍。在实际应用中,需要根据具体情况进行调整和优化。

二、fl2440开发板按键驱动特点

FL2440开发板按键驱动特点如下:

  1. 按键接口多样:FL2440开发板的按键驱动支持多种接口,包括GPIO、中断和ADC等,可以根据需要选择合适的接口。

  2. 抗扰动性强:按键驱动采用了消抖和滤波技术,可以有效地防止按键的误触和抖动,提高了按键的稳定性和可靠性。

  3. 软件编程灵活:按键驱动支持软件编程,可以灵活地配置按键的功能和响应方式,满足各种应用需求。

  4. 低功耗设计:按键驱动的设计采用了低功耗技术,可以最大程度地降低系统能耗,延长系统的使用寿命。

  5. 易于使用:按键驱动的使用非常简单,只需要进行简单的配置和初始化,即可实现按键的控制和响应。

三、应用

FL2440开发板上有多个按键,可以通过编写驱动程序来控制这些按键。下面是按键驱动程序的应用步骤:

  1. 首先需要在内核中注册一个输入设备,将按键输入映射为一个输入事件。

  2. 编写中断处理函数,当有按键按下时,中断控制器会触发中断,中断处理函数会被执行,通过读取GPIO的状态来判断是哪个按键被按下了。

  3. 在中断处理函数中,调用input_event函数,将按键输入映射为一个输入事件,包括输入的类型(EV_KEY),输入的按键编号和按键状态(按下或释放)等信息。

  4. 通过调用input_sync函数来告知输入子系统,输入事件已经准备好,可以进行处理了。

  5. 在应用程序中,通过打开/dev/input/eventX设备节点(X为输入设备的编号),可以读取到输入事件,然后进行相应的处理。

以上就是按键驱动程序的应用步骤,需要注意的是,需要保证输入事件的准确性和稳定性,以确保按键输入的正确性。

 四、驱动程序编写

[leiyuxing@centos6 input_kbd]$ ls
 kbd_device.c   kbd_driver.c  event_button.c  kbd_driver.h  Makefile

驱动相关头文件kbd_driver.h:

/*****************************************************************************
 *      Copyright:  (C) 2016 Guo Wenxue<guowenxue@aliyun.com>
 *                  All rights reserved.
 *
 *       Filename:  kbd_driver.h
 *    Description:  This head file is for s3c keyboard driver
 *
 *        Version:  1.0.0(07/26/2016)
 *         Author:  Guo Wenxue <guowenxue@aliyun.com>
 *      ChangeLog:  1, Release initial version on "07/26/2016 06:54:47 PM"
 *                 
 ********************************************************************************/


#ifndef  _KBD_DRIVER_H_
#define  _KBD_DRIVER_H_


/* keyboard hardware informtation structure definition */
typedef struct s3c_kbd_info_s
{
    int                     code;      /* input device key code  */
    int                     nIRQ;      /* keyboard IRQ number*/
    unsigned int            setting;   /* keyboard IRQ Pin Setting*/
    unsigned int            gpio;      /* keyboard GPIO port */
} s3c_kbd_info_t;


/* keyboard platform device private data structure */
typedef struct s3c_kbd_platform_data_s
{
    s3c_kbd_info_t         *keys;
    int                    nkeys;
} s3c_kbd_platform_data_t;


#endif   /* ----- #ifndef _KBD_DRIVER_H_  ----- */


platform_device相关驱动文件 kbd_device.c:

/*********************************************************************************
 *      Copyright:  (C) 2016 Guo Wenxue<guowenxue@aliyun.com>
 *                  All rights reserved.
 *
 *       Filename:  kbd_device.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(07/26/2016)
 *         Author:  Guo Wenxue <guowenxue@aliyun.com>
 *      ChangeLog:  1, Release initial version on "07/26/2016 05:01:25 PM"
 *                 
 ********************************************************************************/


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


static s3c_kbd_info_t  s3c_kbd_gpios[] = {
    [0] = {
        .code = KEY_1,
        .nIRQ = IRQ_EINT0,
        .gpio = S3C2410_GPF(0),
        .setting = S3C2410_GPF0_EINT0,
    },
    [1] = {
        .code = KEY_2,
        .nIRQ = IRQ_EINT2,
        .gpio = S3C2410_GPF(2),
        .setting = S3C2410_GPF2_EINT2,
    },
    [2] = {
        .code = KEY_3,
        .nIRQ = IRQ_EINT3,
        .gpio = S3C2410_GPF(3),
        .setting = S3C2410_GPF3_EINT3,
    },
    [3] = {
        .code = KEY_4,
        .nIRQ = IRQ_EINT4,
        .gpio = S3C2410_GPF(4),
        .setting = S3C2410_GPF4_EINT4,
    },
};


/* keyboard platform device private data */
static s3c_kbd_platform_data_t s3c_kbd_data = {
    .keys = s3c_kbd_gpios,
    .nkeys = ARRAY_SIZE(s3c_kbd_gpios),
};


static void platform_kbd_release(struct device * dev)
{
        return;
}


static struct platform_device s3c_keyboard_device = {
    .name    = "s3c_kbd",
    .id      = 1,
    .dev     =
    {
        .platform_data = &s3c_kbd_data,
        .release = platform_kbd_release,
    },
};




static int __init s3c_keyboard_dev_init(void)
{
    int            rv;


    rv = platform_device_register(&s3c_keyboard_device);
    if(rv)
    {
        printk("S3C keyboard platform device register failure\n");
        return rv;
    }


    printk("S3C keyboard platform device register ok\n");
    return 0;
}


static void __exit s3c_keyboard_dev_exit(void)
{
    printk("S3C keyboard device exit\n");


    platform_device_unregister(&s3c_keyboard_device);
    return ;
}


module_init(s3c_keyboard_dev_init);
module_exit(s3c_keyboard_dev_exit);


MODULE_DESCRIPTION("FL2440 board keyboard input driver platform_device");
MODULE_AUTHOR("Guo Wenxue<guowenxue@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:FL2440 keyboard device");


platform_driver相关驱动文件 kbd_driver.c:

/*********************************************************************************
 *      Copyright:  (C) 2016 Guo Wenxue<guowenxue@aliyun.com>
 *                  All rights reserved.
 *
 *       Filename:  kbd_driver.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(07/26/2016)
 *         Author:  Guo Wenxue <guowenxue@aliyun.com>
 *      ChangeLog:  1, Release initial version on "07/26/2016 05:01:25 PM"
 *                 
 ********************************************************************************/


#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) 
{
    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); 
    return IRQ_HANDLED;  
}


static void  cancel_dithering_timer_handler(unsigned long data)
{
    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)
{
    int                         i = 0;
    int                         rv = -ENOMEM;
    struct input_dev            *input_dev = NULL;
    s3c_kbd_platform_data_t     *pdata = pdev->dev.platform_data;


    /* 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));


    /* malloc cancel dithering timer for every key */
    s3c_kbd->timers = (struct timer_list *) kmalloc(pdata->nkeys*sizeof(struct timer_list), GFP_KERNEL);
    if( !s3c_kbd->timers )
    {
        printk("error: s3c_kbd_probe kmalloc() for s3c_kbd timers failure\n");
        goto fail;
    }
    memset(s3c_kbd->timers, 0, pdata->nkeys*sizeof(struct timer_list));


    /* malloc input_dev for keyboard */
    input_dev=input_allocate_device();
    if( !input_dev )
    {
        printk("error: s3c_kbd_probe input_allocate_device() failure\n");
        goto fail;
    }


    /* setup input_dev  */
    input_dev->name = pdev->name;
    input_dev->dev.parent = &pdev->dev;
    input_dev->id.bustype = BUS_HOST;
    input_dev->id.vendor = 0x0001;
    input_dev->id.product = 0x0001;
    input_dev->id.version = 0x0100;


    set_bit(EV_KEY,input_dev->evbit);  
    set_bit(EV_REP,input_dev->evbit); 


    /* Initialize all the keys and interrupt */
    for(i=0; i<pdata->nkeys; i++)
    {
        set_bit(pdata->keys[i].code, input_dev->keybit);
        s3c2410_gpio_cfgpin(pdata->keys[i].gpio, pdata->keys[i].setting);
        irq_set_irq_type(pdata->keys[i].nIRQ, IRQ_TYPE_EDGE_BOTH);
        
        rv = request_irq(pdata->keys[i].nIRQ, s3c_kbd_intterupt, IRQF_DISABLED, pdev->name, pdev);
        if( rv )
        {
            printk("error: request IRQ[%d] for key<%d> failure\n", pdata->keys[i].nIRQ, i);
            rv = -EBUSY;
            goto fail;
        }
        
        //printk("s3c_kbd request IRQ[%d] for key<%d> ok\n", pdata->keys[i].nIRQ, i);


         /* Initialize all the keys cancel dithering timer */
        setup_timer(&s3c_kbd->timers[i], cancel_dithering_timer_handler, i);
    }


    /* register input device */
    rv = input_register_device(input_dev);
    if( rv )
    {
        printk("error: s3c_kbd_probe input_register_device error!\n");
        goto fail;
    }


    /* set s3c_kbd as private data in pdev */
    s3c_kbd->input_dev = input_dev;
    s3c_kbd->pdata = pdata;
    platform_set_drvdata(pdev, s3c_kbd);


    printk("s3c_kbd_probe ok\n");
    return 0;


fail:
    while(i--)
    {
        disable_irq(pdata->keys[i].nIRQ);
        free_irq(pdata->keys[i].nIRQ, pdev);
        del_timer( &s3c_kbd->timers[i] );
    }


    if(input_dev)
    {
        input_free_device(input_dev);
    }


    if(s3c_kbd && s3c_kbd->timers)
    {
        kfree(s3c_kbd->timers);
    }


    if(s3c_kbd)
    {
        kfree(s3c_kbd);
    }
    printk("s3c_kbd_probe failed\n");


    return -ENODEV;
}


static int s3c_kbd_remove(struct platform_device *pdev)
{
    int                         i = 0;
    s3c_kbd_t                   *s3c_kbd = platform_get_drvdata(pdev);


    for(i=0; i<s3c_kbd->pdata->nkeys; i++)
    {
        del_timer( &s3c_kbd->timers[i] );
        disable_irq(s3c_kbd->pdata->keys[i].nIRQ);
        free_irq(s3c_kbd->pdata->keys[i].nIRQ, pdev);
    }


    input_unregister_device(s3c_kbd->input_dev);


    kfree(s3c_kbd->timers);
    kfree(s3c_kbd);


    printk("s3c_kbd_remove ok\n");


    return 0;
}


static struct platform_driver s3c_keyboard_driver = {
     .probe      = s3c_kbd_probe,
     .remove     = s3c_kbd_remove,
     .driver     = {
         .name       = "s3c_kbd",
         .owner      = THIS_MODULE,
     },
};


static int __init s3c_keyboard_drv_init(void)
{
    int            rv;


    rv = platform_driver_register(&s3c_keyboard_driver);
    if(rv)
    {
        printk("s3c keyboard platform driver register failure\n");
        return rv;
    }


    printk("s3c keyboard platform driver register ok\n");
    return 0;
}


static void __exit s3c_keyboard_drv_exit(void)
{
    printk("s3c keyboard driver exit\n");


    platform_driver_unregister(&s3c_keyboard_driver);
    return ;
}


module_init(s3c_keyboard_drv_init);
module_exit(s3c_keyboard_drv_exit);


MODULE_DESCRIPTION("FL2440 board keyboard input driver platform_driver");
MODULE_AUTHOR("Guo Wenxue<guowenxue@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:FL2440 keyboard driver");


驱动测试文件event_button.c:

/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<Email:guowenxue@gmail.com QQ:281143292>
 *                  All rights reserved.
 *
 *       Filename:  event_button.c
 *    Description:  This file used to test GPIO button driver builtin Linux kernel on ARM board
 *                 
 *        Version:  1.0.0(07/13/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "07/13/2012 02:46:18 PM"
 *                 
 ********************************************************************************/


#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <libgen.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include <linux/kd.h>
#include <linux/keyboard.h>


#if 0 /* Just for comment here, Reference to linux-3.3/include/linux/input.h */
struct input_event 
{
    struct timeval time;
    __u16 type;  /* 0x00:EV_SYN 0x01:EV_KEY 0x04:EV_MSC 0x11:EV_LED*/
    __u16 code;  /* key value, which key */
    __s32 value; /* 1: Pressed  0:Not pressed  2:Always Pressed */
};  
#endif


#define TRUE               1
#define FALSE              0


#define EV_RELEASED        0
#define EV_PRESSED         1
#define EV_REPEAT          2


#define BUTTON_CNT         5


#define MODE_POLL          0x01
#define MODE_NORMAL        0x02


void usage(char *name);
void display_button_event(struct input_event *ev, int cnt);


int main(int argc, char **argv)
{
    char                  *kbd_dev = NULL;
    char                  kbd_name[256] = "Unknown";
    int                   kbd_fd = -1;


    int                   rv, opt;
    int                   mode = MODE_NORMAL;
    int                   size = sizeof (struct input_event);


    struct input_event    ev[BUTTON_CNT]; 


    struct option long_options[] = {
        {"device", required_argument, NULL, 'd'},
        {"poll", no_argument, NULL, 'p'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };


    while ((opt = getopt_long(argc, argv, "d:ph", long_options, NULL)) != -1)
    { 
        switch (opt)
        {
            case 'd':
                kbd_dev = optarg;
                break;


            case 'p':
                mode = MODE_POLL;
                break;


            case 'h':
                usage(argv[0]);
                return 0;


            default:
                break;
        }
    }


    if(NULL == kbd_dev)
    {
        usage(argv[0]);
        return -1;
    }


    if ((getuid ()) != 0)
        printf ("You are not root! This may not work...\n");




    if ((kbd_fd = open(kbd_dev, O_RDONLY)) < 0)
    {
        printf("Open %s failure: %s", kbd_dev, strerror(errno));
        return -1;
    }


    ioctl (kbd_fd, EVIOCGNAME (sizeof (kbd_name)), kbd_name);
    printf ("Monitor input device %s (%s) event with %s mode:\n", kbd_dev, kbd_name, MODE_POLL==mode?"poll":"infilit loop");




#if 0 /* Not implement in the Linux GPIO button driver */
    unsigned char key_b[BUTTON_CNT/8 + 1];
    memset(key_b, 0, sizeof(key_b));
    if(ioctl(kbd_fd, EVIOCGKEY(sizeof(key_b)), key_b) < 0)
    {
        printf("EVIOCGKEY ioctl get error: %s\n", strerror(errno));
        return -1;
    }
#endif


#if 0 /* Not implement in the Linux GPIO button driver */
    /* rep[0]è?¨?¤???¨??‰é”?é???¤??????°????‰? delay????—?é—?,rep[1]è?¨?¤???‰é”?é???¤??????°????—?é—?é—?é?”?€? */
    int rep[2] ={2500, 1000} ;
    if(ioctl(kbd_fd, EVIOCSREP, rep) < 0)
    {
        printf("EVIOCSREP ioctl get error: %s\n", strerror(errno));
        return -1;
    }


    if(ioctl(kbd_fd, EVIOCGREP, rep) < 0)
    {
        printf("EVIOCGKEY ioctl get error: %s\n", strerror(errno));
        return -1;
    }
    else
    {
        printf("repeate speed: [0]= %d, [1] = %d/n", rep[0], rep[1]);
    }
#endif


    while (1)
    {
        if(MODE_POLL==mode)
        {
            fd_set rds;
            FD_ZERO(&rds);
            FD_SET(kbd_fd, &rds);


            rv = select(kbd_fd + 1, &rds, NULL, NULL, NULL);
            if (rv < 0)
            {
                printf("Select() system call failure: %s\n", strerror(errno));
                goto CleanUp;
            }
            else if (FD_ISSET(kbd_fd, &rds))
            { 
                if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)
                {
                    printf("Reading data from kbd_fd failure: %s\n", strerror(errno));
                    break;
                }
                else
                {
                    display_button_event(ev, rv/size);
                }
            }
        }
        else
        {
            if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)
            {
                printf("Reading data from kbd_fd failure: %s\n", strerror(errno));
                break;
            }
            else
            {
                display_button_event(ev, rv/size);
            }
        }
    }


CleanUp:
    close(kbd_fd);


    return 0;
}


void usage(char *name)
{
    char *progname = NULL;
    char *ptr = NULL;


    ptr = strdup(name);
    progname = basename(ptr);


    printf("Usage: %s [-p] -d <device>\n", progname);
    printf(" -d[device  ] button device name\n");
    printf(" -p[poll    ] Use poll mode, or default use infinit loop.\n");
    printf(" -h[help    ] Display this help information\n"); 


    free(ptr);


    return;
}


void display_button_event(struct input_event *ev, int cnt)
{
    int i;
    struct timeval        pressed_time, duration_time;


    for(i=0; i<cnt; i++)
    {
        //printf("type:%d code:%d value:%d\n", ev[i].type, ev[i].code, ev[i].value);
        if(EV_KEY==ev[i].type && EV_PRESSED==ev[i].value)
        {
            if(BTN_1 == ev[i].code)
            {
                pressed_time = ev[i].time;
                printf("S1 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
            }
            else if(BTN_2 == ev[i].code)
            {
                pressed_time = ev[i].time;
                printf("S2 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
            }
            else if(BTN_3 == ev[i].code)
            {
                pressed_time = ev[i].time;
                printf("S3 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
            }
            else if(BTN_4 == ev[i].code)
            {
                pressed_time = ev[i].time;
                printf("S4 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
            }
            else
            {
                pressed_time = ev[i].time;
                printf("button key[%d]  pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
            }
        }
        if(EV_KEY==ev[i].type && EV_RELEASED==ev[i].value)
        {
            if(BTN_1 == ev[i].code)
            {
                timersub(&ev[i].time, &pressed_time, &duration_time);
                printf("S1 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
                printf("S1 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
            }
            else if(BTN_2 == ev[i].code)
            {
                timersub(&ev[i].time, &pressed_time, &duration_time);
                printf("S2 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
                printf("S2 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
            }
            else if(BTN_3 == ev[i].code)
            {
                timersub(&ev[i].time, &pressed_time, &duration_time);
                printf("S3 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
                printf("S3 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
            }
            else if(BTN_4 == ev[i].code)
            {
                timersub(&ev[i].time, &pressed_time, &duration_time);
                printf("S4 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
                printf("S4 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
            }
            else
            {
                timersub(&ev[i].time, &pressed_time, &duration_time);
                printf("button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
                printf("button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
            }
        }
    } /*  for(i=0; i<cnt; i++) */
}


驱动和测试程序编译Makefile文件

TEST_APP=event_button


KERNEL_VER = linux-3.0
LINUX_SRC ?= /home/leiyuxing/fl2440/kernel/$(KERNEL_VER)


CROSS_COMPILE=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-


PWD := $(shell pwd)


obj-m += kbd_device.o
obj-m += kbd_driver.o


modules:
        @make -C $(LINUX_SRC) M=$(PWD) modules
        @make clear
        @chmod a+x *.ko && cp *.ko /tftp
        @make testapp


clear:
        @rm -f *.o *.cmd *.mod.c
        @rm -rf  *~ core .depend  .tmp_versions Module.symvers modules.order -f
        @rm -f .*ko.cmd .*.o.cmd .*.o.d


clean: clear
        @rm -f  *.ko ${TEST_APP}


testapp:
        ${CROSS_COMPILE}gcc ${TEST_APP}.c -o ${TEST_APP}

[leiyuxing@centos6 input_kbd]$ make
make[1]: Entering directory `/home/leiyuxing/fl2440/kernel/linux-3.0'
  CC [M]  /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_device.o
  CC [M]  /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_driver.o
  Building modules, stage 2.
  MODPOST 2 modules
  CC      /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_device.mod.o
  LD [M]  /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_device.ko
  CC      /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_driver.mod.o
  LD [M]  /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_driver.ko
make[1]: Leaving directory `/home/leiyuxing/fl2440/kernel/linux-3.0'
make[1]: Entering directory `/home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd'
make[1]: Leaving directory `/home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd'
[leiyuxing@centos6 input_kbd]$ ls
kbd_device.c   kbd_driver.c  kbd_driver.ko
event_button.c  kbd_device.ko  kbd_driver.h  Makefile
[leiyuxing@centos6input_kbd]$/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc
event_button.c
[leiyuxing@centos6 input_kbd]$ ls
a.out           kbd_device.c   kbd_driver.c  kbd_driver.ko
event_button.c  kbd_device.ko  kbd_driver.h  Makefile

五、在开发板上的操作:

下载设备驱动:

>: tftp -gr kbd_device.ko 192.168.1.2
kbd_device.ko        100% |*******************************|  3358   0:00:00 ETA
>: tftp -gr kbd_driver.ko 192.168.1.2
kbd_driver.ko        100% |*******************************|  5996   0:00:00 ETA

运行测试

>: insmod kbd_device.ko    
S3C keyboard platform device register ok
>: insmod kbd_driver.ko    
input: s3c_kbd as /devices/platform/s3c_kbd.1/input/input0
s3c_kbd_probe ok
s3c keyboard platform driver register ok

使用测试程序a.out分别测试4个按键:

>: ./a.out 
Usage: a.out [-p] -d <device>
 -d[device  ] button device name
 -p[poll    ] Use poll mode, or default use infinit loop.
 -h[help    ] Display this help information
>: ./a.out -p -d /dev/event0 
Monitor input device /dev/event0 (s3c_kbd) event with poll mode:
Monitor input device /dev/event0 (s3c_kbd) event with poll mode:
button key[2]  pressed time: 483.320105
button key[2] released time: 483.500073
button key[2] duration time: 1094956827.500065
button key[3]  pressed time: 485.265110
button key[3] released time: 485.520131
button key[3] duration time: 1094956829.520123
button key[4]  pressed time: 487.815109
button key[4] released time: 488.60077
button key[4] duration time: 1094956832.60069

经测试发现我的按键4坏了故无法显示。

六、fl2440开发板按键驱动故障如何排查

  1. 确认按键硬件连接是否正确,检查对应引脚是否有信号输出。
  2. 检查按键驱动代码是否正确,确认函数调用是否正确。
  3. 使用示波器检测按键是否产生有效信号,以确认按键是否工作正常。
  4. 如果经过上述步骤无法解决问题,可以使用调试工具(如 J-Link)进行单步调试,查看程序执行的过程,以确定问题出现的位置,并进一步解决故障。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的雷神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值