⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 key_dev.c

📁 基于ARM(2410)GPIO的嵌入式小键盘驱动程序,提供了6个按键的支持.
💻 C
字号:
/*----------------------------------------------------------- * key_dev.c  * micro keyboard driver with interrupt mode * copyright(C) jilin huafeng *   up_key      : port GPB0 *   down_key    : port GPB1 *   left_key    : port GPB9 *   right_key   : port GPB10 *   confirm_key : port GPF1 *   cancel_key  : port GPF2 *   key_press_interrupt : EINT5 *-----------------------------------------------------------*/#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <asm/irq.h>#include <asm/hardware.h>#include <asm/uaccess.h>#include <asm/arch/irqs.h>#include <asm/io.h>#include <asm/semaphore.h> #include <linux/major.h>#include <linux/vmalloc.h>#include <linux/fs.h>#include <linux/poll.h>static DECLARE_WAIT_QUEUE_HEAD( keys_wait );#define MICRO_KEY_MAJOR 138 //key_dat : x  x  x  x  x  right left x x x x x cancel confirm down up//          15 14 13 12 11 10    9    8 7 6 5 4 3      2       1    0#define NOKEY	     0#define RIGHT_KEY    0x04000#define LEFT_KEY     0x02000#define UP_KEY       0x00001#define DOWN_KEY     0x00002#define CONFIRM_KEY  0x00004#define CANCEL_KEY   0x00008static struct semaphore key_sem;static char key = NOKEY;unsigned long gpfdat, gpfup, gpfcon;unsigned long gpbdat, gpbup, gpbcon;devfs_handle_t devfs_microkey;static void  microkey_clearirq( void ){    /*respond to EINT5*/	SRCPND &= ( ~0x00000010 );  //bit4	INTPND = INTPND;	EINTPEND &= ( ~0x00000020 ); //bit5}void delay(){	int i, j;		for( i = 0; i < 10000; i++ )	{	    for( j = 0; j < 100; j++ );	}}static void microkey_irq_isr( int irq, void *dev_id, struct pt_regs *regs ){    unsigned long f_dat, b_dat, k_dat;    printk( "key pressed\n" );    f_dat = ( *( volatile unsigned long * )gpfdat );    b_dat = ( *( volatile unsigned long * )gpbdat );    k_dat = ( f_dat << 1 ) | b_dat;    k_dat = ~k_dat;    k_dat &= 0x060f;    switch( k_dat )    {        case 0x0400:            key = RIGHT_KEY;printk("right key\n");            break;        case 0x0200:            key = LEFT_KEY;printk("left key\n");            break;        case 0x0008:            key = CANCEL_KEY;printk("cancel key\n");            break;        case 0x0004:            key = CONFIRM_KEY;printk("confirm key\n");            break;        case 0x0002:            key = DOWN_KEY;printk("down key\n");            break;        case 0x0001:            key = UP_KEY;printk("up key\n");            break;        default:            key = NOKEY;            break;    }	microkey_clearirq();	up( &key_sem );}static ssize_t microkey_read( struct inode *inode, char *buf, unsigned long count ){    if( key != NOKEY )    {        down_interruptible( &key_sem );        put_user( key, buf );        key = NOKEY;        return 1;    }    else    {        return 0;    }}int microkey_open( struct inode *inode, struct file *file ){	sema_init( &key_sem, 0 );	return 0;}void microkey_release( struct inode *inode, struct file *filp ){    printk( "release ok!\n" );    return;}static unsigned int microkey_poll( struct file *file, poll_table *wait ){    //always ready	return POLLIN | POLLRDNORM;}struct file_operations microkey_fops ={	read    : microkey_read,	open    : microkey_open,	release : microkey_release,	poll    : microkey_poll,};static int __init microkey_init(void){	static int rc;	set_external_irq( IRQ_EINT5, EXT_FALLING_EDGE, GPIO_PULLUP_DIS );	//map port f config register address    gpfcon = ioremap( 0x56000050, 4 );    //set port f io status: gpf1/2 : input(00), gpf5:10(EINT5)    ( *( volatile unsigned long * )gpfcon ) &= 0xfbc3;  //bit1,2 = 00, bit5 = 10    //map port f data register address    gpfdat = ioremap( 0x56000054, 4 );	//map port b config register address    gpbcon = ioremap( 0x56000010, 4 );    //set port b io status: gpb0/1/9/10 : input(00)    ( *( volatile unsigned long * )gpbcon ) &= 0xffc3fff0;  //bit0/1/9/10 = 00    //map port b data register address    gpbdat = ioremap( 0x56000014, 4 );    	disable_irq( IRQ_EINT5 );	enable_irq( IRQ_EINT5 );	    rc = request_irq( IRQ_EINT5, microkey_irq_isr, SA_INTERRUPT, "microkey", NULL );	if( rc )    {		printk( "<1>microkey irq 5 irq not registered. Error: %d\n", rc );	}	    printk("*********key_dev init ok!***********\n");       	/* Register myirq as character device */    devfs_microkey = devfs_register( NULL, "microkey", DEVFS_FL_DEFAULT, MICRO_KEY_MAJOR, 0,                                  S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,                                  &microkey_fops, NULL );		return 0;}static void __exit microkey_exit(void){	disable_irq( IRQ_EINT5 );    free_irq( IRQ_EINT5, microkey_irq_isr );	devfs_unregister( devfs_microkey );}module_init( microkey_init );module_exit( microkey_exit );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -