linxu下244X的按键驱动,测试程序

/********************************************************************
 EINT0 -----( GPF0  )----INPUT               EINT2 -----( GPF2  )----INPUT      
 
*********************************************************************/ 
#include <linux/config.h>   
#include <linux/module.h>   
#include <linux/version.h>   
#include <linux/kernel.h>   
#include <linux/init.h>   
#include <linux/fs.h>   
#include <linux/interrupt.h>   
#include <linux/time.h>   
#include <linux/spinlock.h>  
  
#include <asm/hardware.h>   
#include <asm/delay.h>   
#include <asm/uaccess.h>   
#include <asm-arm/arch-s3c2410/regs-gpio.h>   
  
#include <asm/io.h>   
#include <asm/uaccess.h>   
#include <asm-arm/arch-s3c2410/irqs.h>   
#include <asm-arm/irq.h>   
  
#define DEVICE_NAME "button"   
#define MAX_KEY_COUNT  32                                       
  
typedef struct  
{  
    unsigned long jiffy[MAX_KEY_COUNT];         
    unsigned char buf[MAX_KEY_COUNT];           
    unsigned int head,tail;                    
}KEY_BUFFER;  
  
static KEY_BUFFER g_keyBuffer;     

static spinlock_t buffer_lock;      
static int major = 231;             //Define device major   
/*
static void *gpfcon; 
static void *gpfdat;  
  */
#define gpf_con  (volatile unsigned long)ioremap(0x56000050,4)
#define gpf_dat  (volatile unsigned long)ioremap(0x56000054,4)

 

static unsigned long GetTickCount(void) 

    struct timeval currTick;  
    unsigned long ulRet;  
  
    do_gettimeofday(&currTick);  
    ulRet = currTick.tv_sec;  
    ulRet *= 1000;  
    ulRet += (currTick.tv_usec + 500) / 1000;  
    return ulRet;  
}   

static void init_keybuffer(void) 

    int i; 
    spin_lock_irq(&buffer_lock); 
    g_keyBuffer.head = 0; 
    g_keyBuffer.tail = 0; 
    for(i = 0; i < MAX_KEY_COUNT; i++) 
    { 
        g_keyBuffer.buf[i] = 0; 
        g_keyBuffer.jiffy[i] = 0; 
    } 
    spin_unlock_irq(&buffer_lock); 
}  
  
static void remove_timeoutkey(void) 

    unsigned long ulTick; 
 
    spin_lock_irq(&buffer_lock); 
    while(g_keyBuffer.head != g_keyBuffer.tail) 
    { 
        ulTick = GetTickCount() - g_keyBuffer.jiffy[g_keyBuffer.head]; 
        if (ulTick  < 5000)  

            break; 
        g_keyBuffer.buf[g_keyBuffer.head] = 0; 
        g_keyBuffer.jiffy[g_keyBuffer.head] = 0; 
        g_keyBuffer.head ++; 
        g_keyBuffer.head &= (MAX_KEY_COUNT -1); 
    } 
    spin_unlock_irq(&buffer_lock); 
}  
  
static void init_gpio(void) 
{  

 //  writel((readl(gpf_con)) | ((3<<0)|(3<<4))) &(~((1<<0) | (1<<4))),gpf_con );
writel((readl(gpf_con) |0x33)&0xffffffee,gpf_con);

    set_irq_type(IRQ_EINT0, IRQT_FALLING);  
    set_irq_type(IRQ_EINT2, IRQT_FALLING);  



static __inline void enable_irqs(void) 

    enable_irq(IRQ_EINT0); 
    enable_irq(IRQ_EINT2); 

static __inline void disable_irqs(void) 

    disable_irq(IRQ_EINT0); 
    disable_irq(IRQ_EINT2); 
}  
    
static __inline unsigned char button_scan(int irq)  

    long lGPF;
    lGPF = readl(gpf_dat);  
    if ((lGPF & (1<<0)) == 0)     return 1;   //eint0
    else if((lGPF & (1<<2)) == 0) return 2;   //eint2

    return 0xff ;  
}  


static irqreturn_t button_irq(int irq, void *dev_id, struct pt_regs *regs)  
{  
    unsigned char ucKey; 
 int i,j;
    disable_irqs();  
for(i =0 ;i<3000;i++)
 for(j=0;j<2000;j++);
    ucKey = button_scan(irq);  
    if ((ucKey >= 1) && (ucKey <= 16))  
    { 
 printk("0x%2x /n",ucKey);
        if (((g_keyBuffer.head + 1) & (MAX_KEY_COUNT - 1)) != g_keyBuffer.tail)  
        {  
            spin_lock_irq(&buffer_lock); 
            g_keyBuffer.buf[g_keyBuffer.tail] = ucKey;  
            g_keyBuffer.jiffy[g_keyBuffer.tail] = GetTickCount();  
            g_keyBuffer.tail ++;  
            g_keyBuffer.tail &= (MAX_KEY_COUNT -1);  
            spin_unlock_irq(&buffer_lock); 
        }  

    }  
    init_gpio();  
    enable_irqs();  
    return 0;  
}  
static __inline int request_irqs() 

    int ret; 
    ret = request_irq(IRQ_EINT0, button_irq, SA_INTERRUPT, DEVICE_NAME, NULL);  
    if (ret < 0)  
        return ret;  
    ret = request_irq(IRQ_EINT2, button_irq, SA_INTERRUPT, DEVICE_NAME, NULL);  
    if (ret >= 0)  
    {   
        free_irq(IRQ_EINT2, button_irq); 
    }  
    free_irq(IRQ_EINT0, button_irq); 
    return ret; 
}  
 
static __inline void free_irqs() 

    free_irq(IRQ_EINT0, button_irq); 
    free_irq(IRQ_EINT2, button_irq); 
}  
 
static int button_open(struct inode *inode,struct file *filp)   
{  
    int ret = nonseekable_open(inode, filp); 
    if (ret >= 0) 
    { 
        init_keybuffer();  
        enable_irqs();  
    }  
    return ret;  
}   
    
static int button_release(struct inode *inode,struct file *filp)  
{  
    disable_irqs();  
    return 0;  
}   
   
static ssize_t button_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)  
{  
    ssize_t ret = 0;  
  
    remove_timeoutkey();  
    spin_lock_irq(&buffer_lock); 
    while((g_keyBuffer.head != g_keyBuffer.tail) && (((size_t)ret) < count) ) 
    { 
        buffer[ret] = (char)(g_keyBuffer.buf[g_keyBuffer.head]); 
        g_keyBuffer.buf[g_keyBuffer.head] = 0; 
        g_keyBuffer.jiffy[g_keyBuffer.head] = 0; 
        g_keyBuffer.head ++; 
        g_keyBuffer.head &= (MAX_KEY_COUNT -1); 
        ret ++; 
    } 
    spin_unlock_irq(&buffer_lock); 
    return ret;  
}   
   
static int button_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 

    init_keybuffer(); 
    return 1; 

  
static struct file_operations button_fops =  
{  
    .owner = THIS_MODULE,  
    .ioctl = button_ioctl, 
    .open = button_open,  
    .read = button_read,  
    .release = button_release,  
};   
  
static int __init button_init(void)  
{  
    int ret;  
  
 /*     
    gpfcon = ioremap(0x56000050, 0x04); 
    gpfdat = ioremap(0x56000054, 0x04);  
  */
    init_gpio(); 
    ret = request_irqs();  
    if (ret < 0) return ret;  
  
    ret = register_chrdev(major, DEVICE_NAME, &button_fops);  
    if (ret < 0)  
    {  
        free_irqs();  
        return ret;   
    }  
    devfs_mk_cdev(MKDEV(major, 0), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, DEVICE_NAME);  
  
    disable_irqs();  
    printk("button initialized./n");  
    return 0;  
}   

static void __exit button_exit(void)  
{  
    disable_irqs();  
    free_irqs();  
    devfs_remove(DEVICE_NAME);  
    unregister_chrdev(major, DEVICE_NAME);  
}  
  
module_init(button_init);  
module_exit(button_exit);  
 
MODULE_AUTHOR("ranruoyu1003@yahoo.com.cn ( 421083868)");  
MODULE_DESCRIPTION("button Driver");  
MODULE_LICENSE("RAN");  

/**************************start***********************/  
#include <sys/stat.h>   
#include <fcntl.h>   
#include <stdio.h>   
#include <sys/time.h>   
#include <sys/types.h>   
#include <unistd.h>   
#include <asm/delay.h>   
  
main()  
{  
    int fd;  
    char key = 0;  
    fd = open("/dev/button", O_RDWR);  
    if (fd == -1)  
    {  
        printf("open device button errr!/n");  
        return 0;  
    }  
  
    ioctl(fd, 0, 0);  

    while(key != 16)  
    {  
        if (read(fd, &key, 1) > 0)  
        {  
            printf("*********************Key Value = %d*****************************/n", key);  
        }  
    }  
    close(fd);  
    return 0;  
}  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值