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

📄 keypad.c

📁 ARM9下的键盘驱动源程序
💻 C
字号:
//#define MYDEBUG#include "khead.h"#include "mx1hw.h"//#define PDEBUG printk#define KEYPAD_IRQ			13	struct keypad_struct{//	wait_queue_head_t gkeypadWait;	int gKeypadFlag;	int gDataFlag; /* flag if the driver buf is full */};static struct keypad_struct keypadmx1;static int gMajor = 0;static int g_keyvalue = 0;static long g_keyjif = 0;static DECLARE_WAIT_QUEUE_HEAD(wait);// functions and interfacestatic int keypad_open(struct inode *inode, struct file *filp);static int keypad_release(struct inode *inode, struct file *filp);static ssize_t keypad_read(struct file *filp, char *buf, size_t size,			   loff_t * l);static ssize_t keypad_write(struct file *filp, const char *buf,			    size_t size, loff_t * l);static int keypad_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg);static void keypad_intr_handler(int irq, void *dev_id, struct pt_regs *regs);static unsigned int keypad_poll(struct file * filp, struct poll_table_struct * wait_t);struct file_operations keypad_fops = {      open:keypad_open,      release:keypad_release,      read:keypad_read,      write:keypad_write,	  poll:keypad_poll,      ioctl:keypad_ioctl,};void WREG(unsigned long reg, unsigned long val){	asm volatile ("str %1, [%0]"::"r" (reg), "r"(val)		      :"memory");}unsigned long REG(unsigned long reg){	unsigned long tmp = 0;	asm volatile ("ldr %0, [%1]"::"r" (tmp), "r"(reg)		      :"memory");	return tmp;}static int keypad_open(struct inode *inode, struct file *filp){	PDEBUG("*** open ***\n");	MOD_INC_USE_COUNT;	return 0;}static int keypad_release(struct inode *inode, struct file *filp){	PDEBUG("*** close ***\n");	MOD_DEC_USE_COUNT;	return 0;}static unsigned int keypad_poll(struct file * filp, struct poll_table_struct * wait_t){	poll_wait(filp, &wait, wait_t);	return ( keypadmx1.gDataFlag==0) ? 0 : (POLLIN | POLLRDNORM);}void delay(int n){	int i, j;	for(i=0;i<10000;i++){		for(j=0;j<n;j++){		}	}}#define usleep(n) delay(n)static int key_vector[5][5]={	{ 0, 0, 0, 0, 0},	{ 0, 1, 2, 3, 4},	{ 0, 5, 6, 7, 8},	{ 0, 9,10,11,12},	{ 0,13,14,15,16}};static int row_value=0,line_value=0;static void convert_key(){	int tmp;	if(row_value==ROW1)			tmp = 1;	else if(row_value==ROW2)			tmp = 2;	else if(row_value==ROW3)		tmp = 3;	else if(row_value==ROW4)		tmp = 4;	else		tmp =0;	g_keyvalue = key_vector[line_value][tmp];}static void line_poll(){	if(!((row_value&ROW1)||		(row_value&ROW2)||		(row_value&ROW3)||		(row_value&ROW4)))	{		g_keyvalue=0;		return;	}//no keydown detected;		row_value &= (row_value&ROW1)|			(row_value&ROW2)|			(row_value&ROW3)|			(row_value&ROW4);//mask other bits	*(volatile U32*)PTC_IMR  &= ~(0xF<<14);//interrupt masked	//line output high,prepare for poll	*(volatile U32*)PTA_DR |= 0x7<<17; 	*(volatile U32*)PTB_DR |= 0x1<<19;	usleep(1);//begin polling	*(volatile U32*)PTA_DR &= ~0x1<<17;//line 1	usleep(1);	if(!(*(volatile U32*)PTC_SSR&row_value))	{		line_value = 1;		goto convert;	}	*(volatile U32*)PTA_DR |= 0x1<<17;//not line 1 	*(volatile U32*)PTB_DR &= ~(0x1<<19);//line 2	usleep(1);        if(!((*(volatile U32*)PTC_SSR)&row_value))	{		line_value = 2;		goto convert;	}        *(volatile U32*)PTB_DR |= (0x1<<19);//not line 2        *(volatile U32*)PTA_DR &= ~0x1<<18;//line 3	usleep(1);        if(!(*(volatile U32*)PTC_SSR&row_value))	{                line_value = 3;        	goto convert;	}	*(volatile U32*)PTA_DR |= 0x1<<18;//not line 3	        *(volatile U32*)PTA_DR &= ~0x1<<19;	usleep(1);        if(!((*(volatile U32*)PTC_SSR)&row_value))        { 		line_value = 4;        	goto convert;	}	*(volatile U32*)PTA_DR |= 0x1<<19;//not line 4		line_value = 0;	row_value =0;convert:	convert_key();      	*(volatile U32*)PTA_DR &= ~(0x7<<17);//output 0        *(volatile U32*)PTB_DR &= ~(0x1<<19);	*(volatile U32*)PTC_IMR  |= 0xF<<14;//interrupt enabled	}static void keypad_intr_handler(int irq, void *dev_id, struct pt_regs *regs){	unsigned long flags;	//printk("jiffies-keyjif:   \t\t\t%ld\n", jiffies-g_keyjif);#if 1	//remove trembling	if(jiffies - g_keyjif <= 19) {		//printk("discarded.\n");		*(volatile U32*)PTC_ISR  |= 0xF<<14;    //clear all 14~17 interrupts(write 1 to clear)		return;	}#endif	row_value=*(volatile U32*)PTC_ISR;		g_keyjif=jiffies;//	PDEBUG("PTC_ISR: 0x%x\n",*(volatile U32*)PTC_ISR);	save_flags_cli(flags);	keypadmx1.gDataFlag = 1;	restore_flags(flags);		line_poll();	//usleep(200);	wake_up_interruptible(&wait);	*(volatile U32*)PTC_ISR  |= 0xF<<14;    //clear all 15~30 interrupts(write 1 to clear)}static ssize_tkeypad_read(struct file *filp, char *buf, size_t size, loff_t * l){	int nonBlocking;	unsigned long flags;	int  ret = 0;		PDEBUG("*** read ***\n");	nonBlocking = filp->f_flags & O_NONBLOCK;	PDEBUG("nonBlocking:%d\n", nonBlocking);	if( keypadmx1.gDataFlag == 1)	{		*(U32*)buf=g_keyvalue;			save_flags_cli(flags);		keypadmx1.gDataFlag = 0;		restore_flags(flags);		ret = 2;	}else{		if(!nonBlocking ){			interruptible_sleep_on(&wait);			*(U32*)buf=g_keyvalue;				save_flags_cli(flags);			keypadmx1.gDataFlag = 0;			restore_flags(flags);			ret = 2;		}else			ret =0;	}	g_keyvalue = 0;	return ret;}	static ssize_tkeypad_write(struct file *filp, const char *buf, size_t size, loff_t * l){	PDEBUG("*** write ***\n");	return 0;}static intkeypad_ioctl(struct inode *inode, struct file *file,		unsigned int cmd, unsigned long arg){	unsigned long tmp;	tmp = arg;	PDEBUG("cmd: 0x%08x, arg: 0x%08x\n", cmd, (int) arg);	return 0;   }static void GPIO_init(void){//row	*(volatile U32*)PTC_GIUS |= 0xF<<14; //GPC 14~17:GPIO function;	*(volatile U32*)PTC_DDIR &= ~(0xF<<14);	//14~17 input	*(volatile U32*)PTC_PUEN |= 0xF<<14; //pull high	*(volatile U32*)PTC_ICR1 |= 0x50000000;	//PC 15,PC14,negtive edge interrupt(01), pin 15	*(volatile U32*)PTC_ICR2 |= 0x00000005; //PC16,PC17,negtive edge interrupt(01), pin 16~30	*(volatile U32*)PTC_IMR  &= ~(0xF<<14);    //all 14~17 interrupts masked	*(volatile U32*)PTC_ISR  |= 0xF<<14;    //clear all 14~17 interrupts(write 1 to clear)//line	*(volatile U32*)PTA_GIUS |= 0x7<<17;//GPA 17~19;GPIO function;	*(volatile U32*)PTA_DDIR |= 0x7<<17;//17~19 output;	*(volatile U32*)PTA_PUEN &= ~(0x7<<17);//tri-state;	*(volatile U32*)PTA_OCR2 |= 0xFC;	*(volatile U32*)PTA_DR &= ~(0x7<<17);//output 0	*(volatile U32*)PTB_GIUS |= 0x1<<19;//GPB 19	*(volatile U32*)PTB_DDIR |= 0x1<<19;//output	*(volatile U32*)PTB_PUEN &= ~(0x1<<19);//tri-state	*(volatile U32*)PTB_OCR2 |= 0xC0;	*(volatile U32*)PTB_DR  &= ~(0x1<<19);//output 0		  //	*(volatile U32*)PTD_GIUS |= 0x7ff8000;		//use PTD 15~26//	*(volatile U32*)PTD_DDIR &= ~0x7ff8000;	//input//	*(volatile U32*)PTD_PUEN |= 0x7ff8000;		//pull high//	*(volatile U32*)PTD_ICR1 |= 0x07000000;		//negtive edge interrupt(01), pin 15//	*(volatile U32*)PTD_ICR1 |= 0x00155555;		//negtive edge interrupt(01), pin 16~30	//*(volatile U32*)PTD_ICR1 |= 0x0;		//positive edge interrupt(00), pin 15	//*(volatile U32*)PTD_ICR1 |= 0x0;		//negtive edge interrupt(00), pin 16~30//	*(volatile U32*)PTD_IMR  &= ~0x7ff8000;    //all 15~30 interrupts masked//	*(volatile U32*)PTD_ISR  |= 0x7ff8000;    //clear all 15~30 interrupts(write 1 to clear)}static devfs_handle_t devfs_handle;int init_module(){	int result;	printk("KEYPAD driver " __DATE__ " / " __TIME__ "\n");	/* register our character device */	result = devfs_register_chrdev(0, "keypad", &keypad_fops);	if (result < 0) {		printk("keypad driver: Unable to register driver\n");		return -ENODEV;	}	devfs_handle = devfs_register(NULL, "keypad", DEVFS_FL_DEFAULT,			result, 0,			S_IFCHR | S_IRUSR | S_IWUSR,			&keypad_fops, NULL);	printk("make node for keypad with 'mknod keypad c %d 0'\n",	       result);	gMajor = result;	if (request_irq	    (KEYPAD_IRQ, keypad_intr_handler, SA_INTERRUPT, "KEYPAD",	     NULL))		printk		    ("*** Cannot register interrupt handler for KEYPAD ! ***\n");	else		printk("KEYPAD interrupt handler registered\n");	printk("Keypad init.\n");	GPIO_init();	*(volatile U32*)PTC_IMR |= 0xF<<14; // enable pin 14~17	//*(volatile U32*)PTD_IMR  = 0x7fff0000;    //enable pin 15~30	//*(volatile U32*)PTD_IMR  = 0x7ff8000;    //enable pin 20~28	return 0;}void cleanup_module(){	if (gMajor > 0) {		devfs_unregister_chrdev(gMajor, "keypad");		devfs_unregister(devfs_handle);	}	free_irq(KEYPAD_IRQ, 0);	printk("Say goodbye to keypad\n");}

⌨️ 快捷键说明

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