📄 key.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 + -