linux驅動開發fl2440開發板按鍵驅動
———————————————————————————————————————
主機作業系統:Centos 6.7交叉編譯器環境:arm-linux-gcc-4.5.4 開發板平臺: FL2440 Linux核心版本: linux-3.0 開發模組: LED_BUTTON郵箱:[email protected]
———————————————————————————————————————
kbd_device.c kbd_driver.c event_button.c kbd_driver.h Makefile
驅動相關標頭檔案kbd_driver.h:
/***************************************************************************** * Copyright: (C) 2016 Guo Wenxue<[email protected]> * 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 <
[email protected]> * 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<[email protected]>
* All rights reserved.
*
* Filename: kbd_device.c
* Description: This file
*
* Version: 1.0.0(07/26/2016)
* Author: Guo Wenxue <[email protected]>
* 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<[email protected]>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:FL2440 keyboard device");
platform_driver相關驅動檔案 kbd_driver.c:
/*********************************************************************************
* Copyright: (C) 2016 Guo Wenxue<[email protected]>
* All rights reserved.
*
* Filename: kbd_driver.c
* Description: This file
*
* Version: 1.0.0(07/26/2016)
* Author: Guo Wenxue <[email protected]>
* 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<[email protected]>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:FL2440 keyboard driver");
驅動測試檔案event_button.c:
/*********************************************************************************
* Copyright: (C) 2012 Guo Wenxue<Email:[email protected] 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 <[email protected]>
* 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}
[[email protected] 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'
[[email protected] input_kbd]$ ls
kbd_device.c kbd_driver.c kbd_driver.ko
event_button.c kbd_device.ko kbd_driver.h Makefile
[[email protected]_kbd]$/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc
event_button.c
[[email protected] 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壞了故無法顯示。
相關推薦
linux驅動開發fl2440開發板按鍵驅動
——————————————————————————————————————— 主機作業系統:Centos 6.7交叉編譯器環境:arm-linux-gcc-4.5.4 開發板平臺: FL2440 Linux核心版本: linux-3.0 開發模組: LED_BUTTON郵
Linux驅動開發10:【裝置樹】nanopi的按鍵驅動
介紹 這一節在nanopi上實現按鍵驅動,和LED驅動一樣,通用的按鍵驅動在linux核心中已經實現好,我們只需要按照要求寫好裝置樹即可,不用我們自己實現按鍵驅動。這一節中首先修改裝置樹並測試按鍵驅動,然後分析drivers/input/keyboard/gpio_keys.c檔案,
《Linux驅動》iTop4412開發板LCD驅動 詳細分析 (三)
接下來我們來詳解介紹probe中的函式: 第一個函式: s3cfb_set_lcd_info(fbdev[i]); 1.該函式原始碼如下: /*該函式在s3cfb_wa101s.c 中*/ /* name should be fixed as
嵌入式Linux裝置驅動開發之:按鍵驅動程式例項
11.6 按鍵驅動程式例項 11.6.1 按鍵工作原理 高電平和低電平相接怎麼會變成低電平呢 就像你把電源正極的負極相連一樣會把電壓拉低。大電流會從高電平引腳流向低電平引腳,把高電平引腳拉低。 LED和蜂鳴器是最簡單的GPIO的應用,都不需要任何外部
linux驅動開發之蜂鳴器驅動源碼分析(一)
linux 蜂鳴器 驅動 蜂鳴器的驅動源碼在/driver/char/buzzer/x210-buzzer.c文件中,源碼如下#include <linux/module.h> #include <linux/kernel.h> #include <linux
Linux USB 驅動開發(二)—— USB 驅動幾個重要資料結構
Linux USB 驅動開發(二)—— USB 驅動幾個重要資料結構 前面我們學習了USB 驅動的一個描述符,下面來學習 USB 驅動的幾個重要資料結構 一、struct usb_interface&n
【核心】四、搭建完整的mini2440開發板驅動開發環境(仿照JZ2440驅動開發環境搭建)
一、mini2440開發板驅動環境搭建: 《mini2440使用者手冊》說明原文>>注意:本開發板提供的 linux 核心並不能直接用於 u-boot ,因為我們公司是不使用u-boot的,並且對其各個引數設定並不瞭解,關於 U-Boot 的使用方法使用者可以參考網上的資料。 我了個。。。鑑於
Linux驅動開發04:塊裝置驅動和網路裝置驅動
介紹 因為塊裝置驅動和網路裝置驅動實際中用得較少,所以只給出驅動模板,我也沒有具體測試,等到實際用到是再研究吧,溜了溜了。 塊裝置驅動模板 struct xxx_dev { int size; struct request_q
Linux USB 驅動開發(五)—— USB驅動程式開發過程簡單總結
裝置驅動程式是作業系統核心和機器硬體之間的介面,由一組函式和一些私有資料組成,是應用程式和硬體裝置之間的橋樑。在應用程式看來,硬體裝置只是一個裝置檔案,應用程式可以像操作普通檔案一樣對硬體裝置進行操作。 裝置驅動程式是核心的一部分,主要完成以下功能
Zynq-Linux移植學習筆記之14-RapidIO驅動開發
在對zynq進行linux驅動開發時,除了需要針對zynq內ARM自帶的控制器適配驅動外,還需要對zynq PL部分的IP核進行驅動開發。對於ARM來說,zynq PL部分的IP核就是一段地址空間,這段地址空間包含了該IP的一系列暫存器,ARM操作該IP核的暫存器也就是
ZYNQ Linux驅動開發——第一個字元裝置驅動
硬體平臺:XCZ7020 CLG484-1 完全適配Zedboard 開發環境:Widows下Vivado 2016.2 、 SDK2016.2 、 Linux機器:debin 目的:操作板載的LED燈LD9,受PS部分的MIO7控制 linux裝置驅
【4412開發板使用經驗分享】迅為4412開發板I2C驅動問題
我想寫DS3231 的驅動 但是讀回的資料老是-6 硬體: 我I2C裝置連線的這幾個GPIO,看了2.5的手冊,介面應該是連結正確的 軟體 分了兩個模組檔案 這個是dev 這個是drv.ko 紅框裡程式碼是讀取ds3231的秒暫存器,正常值應該是0-6
mt7601的ap驅動在s5pv210開發板上的編譯,裝載及配置使用
mt7601的驅動和其他的無線網絡卡有點區別。mt7601作為station使用還是作為AP使用分別有兩套不同的原始碼包。這裡介紹mt7601作為ap的驅動。下載地址:http://download.csdn.net/download/diandianyangyi/7894
exynos4412開發板LED驅動程式
本文將介紹在EXYNOS4412平臺上實現對LED燈開關的控制 首先定義命令在led.h檔案中 #define LED_MAGIC 'L' #define LED_ON _IO(LED_MAGIC,1) #define LED_OFF _IO(LED_M
基於imx25開發板音訊驅動理解
之前在做關於音訊驅動的相關工作,學習到了一些知識,所以簡單的談一談對這方面的理解。 內容主要是基於imx255核心板,它是支援多種音訊處理晶片的。工作是配合音訊晶片SGTL5000進行的。這裡主要介紹該晶片在Linux下的驅動相關內容。我實際
s5pv210開發板 led驅動學習筆記
相應驅動程式如下:#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/types.h> #include <linu
Itop4412開發板emmc驅動移植(裝置樹)
硬體裝置:itop4412開發板 核心版本linux-3.8.1 裝置樹方式減少了裝置的冗餘編碼,同時使移植變得更加高效。eMMC作為開發板的基礎,十分重要。 裝置樹用的是核心自帶的smdk4412.dts vim arch/arm/boot/dts/exynos4412-
arm9+linux fl2440之按鍵驅動 plat_button.c
if( result ) { result = -EBUSY; goto ERROR1; } } return 0; ERROR1: kfree((unsigned char *)pdev
Linux驅動開發之主裝置號找驅動,次裝置號找裝置
一、引言 很久前接觸linux驅動就知道主裝置號找驅動,次裝置號找裝置。這句到底怎麼理解呢,如何在驅動中實現呢,在介紹該實現之前先看下核心中主次裝置號的管理: 二、Linux核心主次裝置號的管理 Linux的裝置管理是和檔案系統緊密結合的,各種裝置都以檔
Linux Arm上的RGB液晶屏驅動開發遇到的問題總結
(基於三星Exynos 4412 / iTop4412精英版開發板) 1. 開發前準備和核心編譯 將Linux核心iTop4412_Kernel_3.0_20180508.tar.gz複製到虛擬機器,解壓。 進入解壓後的資料夾,使用命令cp confi