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

📄 key.c

📁 该文件是摩托罗拉的嵌入式芯片dragonball MX1的在嵌入式linux下键盘驱动
💻 C
字号:
#define	__KERNEL__

#define	MODULE





/////////////////////////////////////////////////////////////////////////////

#include <linux/module.h>

#include <linux/version.h>

#include <linux/init.h>

#include <linux/fs.h>

#include <linux/delay.h>

#include <linux/poll.h>

#include <asm/uaccess.h>        /* get_user,copy_to_user */



#include <linux/string.h>

#include <linux/kernel.h>

#include <linux/sched.h>

#include <linux/types.h>

#include <linux/fcntl.h>

#include <linux/interrupt.h>

#include <linux/ptrace.h>

#include <linux/ioport.h>

#include <linux/in.h>

//include <linux/malloc.h>

#include <linux/slab.h>

#include <linux/vmalloc.h>

#include <linux/string.h>

#include <linux/init.h>

#include <asm/bitops.h>

#include <asm/io.h>

#include <linux/errno.h>

#include <linux/tqueue.h>

#include <linux/wait.h>

#include <asm/irq.h>

#include <asm/arch/hardware.h>

#include <asm/arch/irqs.h>

#include <linux/devfs_fs_kernel.h>

#include "mx1_def.h"

#include "key.h"





void delay(void);

int key_open(struct inode * inode, struct file * filp);

int key_release(struct inode * inode, struct file * filp);

unsigned int key_poll(struct file * filp, struct poll_table_struct * wait);

int init_key(void);

static void pb_irq_handle(int irq, void *dev_id, struct pt_regs *regs);

void cleanup_key(void);

ssize_t key_read(struct file * filp, char * buf, size_t count, loff_t * l);



char *dev_id="KeyBoardIrq";

#define	V_ADDRESS(x)	(*((volatile unsigned long* )(0xF0000000|x)))



unsigned char  key_val=0xff;

wait_queue_head_t 	ts_wait;



struct file_operations key_fops = {

	open:           key_open,

	release:        key_release,

	read:           key_read,

	poll:           key_poll,

	};





int key_open(struct inode * inode, struct file * filp)

{

	//       enable_irq(12);

	MOD_INC_USE_COUNT;

	return 0;

}



/******************************************************************************

* Function Name: key_release

*

* Input: 		inode	:

* 			filp	:

* Value Returned:	int	: Return status.If no error, return 0.

*

* Description: release resource when close the inode

*

* Modification History:

* 	wang kuo

*****************************************************************************/

int key_release(struct inode * inode,

struct file * filp)

{

	//    disable_irq(12);

	MOD_DEC_USE_COUNT;

	return 0;

}



ssize_t key_read(struct file * filp, char * buf, size_t count, loff_t * l)

{

	copy_to_user(buf, &key_val, 1);

	key_val = 0xff;

	return 0;

}



unsigned int key_poll(struct file * filp, struct poll_table_struct * wait)

{

	poll_wait(filp,&ts_wait,wait);



	if (key_val != 0xff)

	return POLLIN |POLLRDNORM;

	else

	return 0;

}

static void pb_irq_handle(int irq, void *dev_id, struct pt_regs *regs)

{



	unsigned long status_isr=0;

	unsigned long dr_bak=0;

	

	unsigned pta_mask = 0x8000;

	unsigned ptc_mask = 0x10000;

	int i=0;

	unsigned int row=0, col=0;



	if(!((V_ADDRESS(PTA_ISR) & 0x1)||(V_ADDRESS(PTC_ISR) & 0xE000)))	

		return;

	

	// Disable Interruption

	V_ADDRESS(PTA_IMR)  &=~ 0x00000001;	//PA0

	V_ADDRESS(PTC_IMR)  &=~ 0x0000E000;	//PC13, PC14, PC15

	

	// ROW: PC14, PC15, PA0, PC13 

	status_isr |= (V_ADDRESS(PTC_ISR) & 0x2000) >> 13;	                         

	status_isr |= (V_ADDRESS(PTC_ISR) & 0x4000) >> 11;

	status_isr |= (V_ADDRESS(PTC_ISR) & 0x8000) >> 13;

	status_isr |= (V_ADDRESS(PTA_ISR) & 0x1)    <<  1;

	

	V_ADDRESS(PTA_ISR)  |= 0x00000001;

	V_ADDRESS(PTC_ISR)  |= 0x0000E000;

	

	/////////////////////////////////////////////////////////////////////////



	if(status_isr)

	{

		row = (status_isr/2);

		if(row>3)   row =3;



		//PC14、PC15、PA0、PC13

		dr_bak=((V_ADDRESS(PTC_SSR) & 0xE000) | (V_ADDRESS(PTA_SSR) & 0x1));

		

		while(dr_bak == ((V_ADDRESS(PTC_SSR) & 0xE000) | (V_ADDRESS(PTA_SSR) & 0x1)))

		{

			//  PA15、PA16、PC16、PC17

			if(col < 2){

				V_ADDRESS(PTA_DR) &=~0x18000;	

				V_ADDRESS(PTA_DR) |= pta_mask;	

				pta_mask = pta_mask << 1;

			}

			else {

				V_ADDRESS(PTC_DR) &=~0x30000;

				V_ADDRESS(PTC_DR) |= ptc_mask;

				ptc_mask = ptc_mask << 1;

			}

			if(col==4)  break;

			col++;



		}

		col = 4-col;

		if(col<=3 && row<=3)

		{

			printk("Key(%u, %u) pressed!\n",row,col);

			for(;i<2000;i++)

				delay();			

			V_ADDRESS(PTA_DR) &=~0x18000;

			V_ADDRESS(PTC_DR) &=~0x30000;

			key_val = (row << 4) | col;

		}

	}



	///////////////////////////////////////////////////////////////////////////////

	//    restore_flags(flags);



	V_ADDRESS(PTA_IMR)  |= 0x00000001;

	V_ADDRESS(PTC_IMR)  |= 0x0000E000;

	wake_up_interruptible(&ts_wait);

}

void delay(void)

{

	unsigned long i= 1<<12;

	

	for(;i>0;i--){};

}







//////////////////////////////////////////////////////////////////////////////////////////////////

#ifdef MODULE

int init_module(void)

#else

int __init init_key(void)

#endif

{

	unsigned int result = 0;

	init_waitqueue_head(&ts_wait);



	// PA15、PA16、PC16、PC17 OUTPUT

	

	V_ADDRESS(PTA_GIUS) |= 0x18000;		// PA15, PA16

	V_ADDRESS(PTA_OCR1) |= 0xC0000000;	// PA15

	V_ADDRESS(PTA_OCR2) |= 0x3;		// PA16

	V_ADDRESS(PTA_DDIR) |= 0x18000;

	V_ADDRESS(PTA_DR)   &=~0x18000;

	

	V_ADDRESS(PTC_GIUS) |= 0x30000;

	V_ADDRESS(PTC_DDIR) |= 0x30000;

	V_ADDRESS(PTC_OCR2) |= 0xF;		// PC16, PC17

	V_ADDRESS(PTC_DR)   &=~0x30000;

	

	// PC14、PC15、PA0、PC13 INTERRUPT

	V_ADDRESS(PTA_GIUS) |= 0x1;		// PA0

	V_ADDRESS(PTA_DDIR) &=~0x1;

	V_ADDRESS(PTA_ICR1) &=~0x3;

	V_ADDRESS(PTA_ICR1) |= 0x1;

	V_ADDRESS(PTA_ISR)  |= 0x1;



	V_ADDRESS(PTC_GIUS) |= 0xE000;		// PC14, PC15, PC13

	V_ADDRESS(PTC_DDIR) &=~0xE000;

	V_ADDRESS(PTC_ICR1) &=~0xFC000000;

	V_ADDRESS(PTC_ICR1) |= 0x54000000;

	V_ADDRESS(PTC_ISR)  |= 0xE000;



	result = register_chrdev(250, "/tmp/keyBoard", &key_fops);



	if (result < 0) {

		printk("<1>key_dev: can't get major number 250\n");

		unregister_chrdev(250,"keyBoard");

		return result;

	}

	printk("<1>register_chrdev: %d\n", result);

	

	// 

	V_ADDRESS(PTA_IMR)  |= 0x1;	// PA0

	V_ADDRESS(PTC_IMR)  |= 0xE000;	// PC14, PC15, PC13



	result=request_irq(11,pb_irq_handle,SA_SHIRQ,"keyBoard", dev_id);

	result=request_irq(13,pb_irq_handle,SA_SHIRQ,"keyBoard", dev_id);

	

	enable_irq(11);

	enable_irq(13);

	

	printk("<1> request_irq: %d\n", result);

	return 0;

}







#ifdef MODULE

void cleanup_module(void)

#else

void __exit cleanup_key(void)

#endif

{

	disable_irq(11);

	disable_irq(13);

	V_ADDRESS(PTA_IMR)  &=~ 0x00000001;	//PA0

	V_ADDRESS(PTC_IMR)  &=~ 0x0000E000;	//PC13, PC14, PC15

	

	free_irq(11, dev_id);

	free_irq(13, dev_id);

	unregister_chrdev(250,"keyBoard");

}







#ifndef MODULE

module_init(init_key);

module_exit(cleanup_key);

#endif

⌨️ 快捷键说明

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