打印
[嵌入式linux]

FS2410下的键盘驱动,为什么不能注册中断?

[复制链接]
1265|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wangben85|  楼主 | 2009-2-23 15:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下是网上找到的FS2410下面的键盘驱动,本人稍作修改。可以编译通过,但是下到板子里insmod,发现不能注册中断。即request_irq函数有什么问题么?希望高手帮忙!
  #include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/sched.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/console.h>
#include <linux/parport.h>
#include <linux/lp.h>
#include <asm/io.h>           
#include <linux/ioport.h>  
#include <linux/interrupt.h>
#include <asm/uaccess.h>

#define GPECON (0x56000040)
#define GPFCON (0x56000050)
#define GPGCON (0x56000060)
#define GPEDAT (0x56000044)
#define GPFDAT (0x56000054)
#define GPGDAT (0x56000064)
#define SRCPND (0x4A000000)
#define EINTMASK (0x560000A4)
#define INTMASK (0x4A000008)
static void *gpecon;
static void *gpfcon;
static void *gpgcon;
static void *gpedat;
static void *gpfdat;
static void *gpgdat;
static void *srcpnd;
static void *eintmask;
static void *intmask;
MODULE_LICENSE("GPL"); //2.6内核必须有,否则不能加载
#define keyirq_MAJOR 242
#define NAME "buttons"
#define NOKEY  0xff
static struct semaphore key_sem;
static char key=NOKEY;
/*----------清除中断------------------*/
static void inline clearIrq(void)
{
  //mdelay(100);   //防抖动
  writel(readl(srcpnd)|0x25,srcpnd);//clear srcpnd 0 2 11 19
}
/*---------键盘扫描-----------------*/
static int Key_Scan( void )
{
//mdelay(100);
        writel(readl(gpgdat)&(~((1<<6)|(1<<2))) | (1<<6) | (0<<2) ,gpgdat);  //GPG2 output 0;GP6 output 1
        writel(readl(gpedat)&(~((1<<13)|(1<<11))) | (1<<13) | (1<<11)  ,gpedat);  //GPE13,11 output 1
if(      (readl(gpfdat)&(1<< 0)) == 0 ) return 16 ;
else if( (readl(gpfdat)&(1<< 2)) == 0 )  return 15 ;
else if( (readl(gpgdat)&(1<< 3)) == 0 )  return 14 ;
else if( (readl(gpgdat)&(1<<11)) == 0 )  return 13 ;
        writel(readl(gpgdat)&(~((1<<6)|(1<<2))) | (0<<6) | (1<<2) ,gpgdat);  //GPG6 output 0;GPG2 output 1
        writel(readl(gpedat)&(~((1<<13)|(1<<11))) | (1<<13) | (1<<11)  ,gpedat);  //GPE13,11 output 1
if(      (readl(gpfdat)&(1<< 0)) == 0 ) return 11 ;
else if( (readl(gpfdat)&(1<< 2)) == 0 )  return 8 ;
else if( (readl(gpgdat)&(1<< 3)) == 0 )  return 5 ;
else if( (readl(gpgdat)&(1<<11)) == 0 )  return 2 ;
        writel(readl(gpgdat)&(~((1<<6)|(1<<2))) | (1<<6) | (1<<2) ,gpgdat);  //GPG6,2 output 1
        writel(readl(gpedat)&(~((1<<13)|(1<<11))) | (1<<13) | (0<<11) ,gpedat);  //GPE13 output 1;GPE11 output 0
if(      (readl(gpfdat)&(1<< 0)) == 0 ) return 10 ;
else if( (readl(gpfdat)&(1<< 2)) == 0 )  return 7 ;
else if( (readl(gpgdat)&(1<< 3)) == 0 )  return 4 ;
else if( (readl(gpgdat)&(1<<11)) == 0 )  return 1 ;

        writel(readl(gpgdat)&(~((1<<6)|(1<<2))) | (1<<6) | (1<<2) ,gpgdat);  //GPG6,2 output 1
        writel(readl(gpedat)&(~((1<<13)|(1<<11))) | (0<<13) | (1<<11) ,gpedat);  //GPE11 output 1;GPE13 output 0
if(      (readl(gpfdat)&(1<< 0)) == 0 ) return 12 ;
else if( (readl(gpfdat)&(1<< 2)) == 0 )  return 9 ;
else if( (readl(gpgdat)&(1<< 3)) == 0 )  return 6 ;
else if( (readl(gpgdat)&(1<<11)) == 0 )  return 3 ;
return 0xff ;
}
static irqreturn_t irq_isr(int irq, void *dev_id, struct pt_regs *regs)
{
//GPGCON = GPGCON & (~((3<<22)|(3<<6))) | ((0<<22)|(0<<6)) ;  //GPG11,3 set input
//GPFCON = GPFCON & (~((3<<4)|(3<<0))) | ((0<<4)|(0<<0)) ;  //GPF2,0 set input
        writel(readl(gpgcon)& (~((3<<22)|(3<<6))) | ((0<<22)|(0<<6)),gpgcon);//set gpg11 3 to input
        writel(readl(gpfcon)& (~((3<<4)|(3<<0))) | ((0<<4)|(0<<0)),gpfcon);//set gpf2 0 to input    
//查询按键键值
key = Key_Scan() ;
if( key != 0xff )
  printk("Interrupt occur... K%d is pressed!\n", key ) ;
         //printk("Interrupt " ) ;
//Beep( 2000, 3000 ) ;

//重新初始化IO口
//rGPGCON = rGPGCON & (~((3<<12)|(3<<4))) | ((1<<12)|(1<<4)) ;  //GPG6,2 set output
//rGPGDAT = rGPGDAT & (~((1<<6)|(1<<2)));  //GPG6,2 output 0

//rGPECON = rGPECON & (~((3<<26)|(3<<22))) | ((1<<26)|(1<<22));  //GPE13,11 set output
//rGPEDAT = rGPEDAT & (~((1<<13)|(1<<11)));  //GPE13,11 output 0

//rGPGCON = rGPGCON & (~((3<<22)|(3<<6))) | ((2<<22)|(2<<6)) ;  //GPG11,3 set EINT
//rGPFCON = rGPFCON & (~((3<<4)|(3<<0))) | ((2<<4)|(2<<0)) ;  //GPF2,0 set EINT

               
         writel(readl(gpecon)& (~((3<<26)|(3<<22))) | ((1<<26)|(1<<22)),gpecon);//set gpe11 13 to output        
         writel(readl(gpedat)&(~((1<<13)|(1<<11))) ,gpedat);  //set GPE11 13 to 00
          writel(readl(gpgcon) & (~((3<<12)|(3<<4))) | ((1<<12)|(1<<4)),gpgcon);//set gpe2 6 to output       
          writel(readl(gpgdat)&(~((1<<6)|(1<<2))) ,gpgdat);  //set GPG2 6 to 00 :
   writel(readl(gpgcon)&(~((3<<22)|(3<<6))) | ((2<<22)|(2<<6)),gpgcon);  //set GPG3/EINT11,GPG11/EINT19
          writel(readl(gpfcon)&(~((3<<4)|(3<<0))) | ((2<<4)|(2<<0)),gpfcon);//set GPF0/EINT0,GPF2/EINT2
        up(&key_sem);
        return IRQ_HANDLED;
}

static ssize_t keyirq_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
  if(down_interruptible(&key_sem))
    {
      return -ERESTARTSYS;
    };
    put_user(key, buf);
    key = NOKEY;
    return 1;
}
int keyirq_open(struct inode *inode, struct file *file)
{
    clearIrq();
#if 1
    enable_irq(IRQ_EINT0);
    enable_irq(IRQ_EINT2);
    enable_irq(IRQ_EINT11);
    enable_irq(IRQ_EINT19);
#endif
    sema_init(&key_sem, 0);
    return 0;
}
int keyirq_release(struct inode *inode, struct file *filp)
{
#if 1
    disable_irq(IRQ_EINT0);
    disable_irq(IRQ_EINT2);
    disable_irq(IRQ_EINT11);
    disable_irq(IRQ_EINT19);
#endif
    return 0;
}

static int keyirq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    return 0;
}
struct file_operations keyirq_fops = {
     .owner= THIS_MODULE,
     .read = keyirq_read,
     .open = keyirq_open,
     .release = keyirq_release,
     .ioctl = keyirq_ioctl,
};
int __init keyirq_init(void)
{
    int rc;
           if ((rc = register_chrdev(keyirq_MAJOR, NAME, &keyirq_fops)) < 0)
           {
        printk("keyirq: can't get major %d\n", keyirq_MAJOR);
        return 1;
           }
           else
           {
             printk("buttons.ko register success");
            } 
            
          gpecon=ioremap_nocache(GPECON,0x0000004);
          gpfcon=ioremap_nocache(GPFCON,0x0000004);
          gpgcon=ioremap_nocache(GPGCON,0x0000004);
          srcpnd=ioremap_nocache(SRCPND,0x0000004);
          intmask=ioremap_nocache(INTMASK,0x0000004);
          eintmask=ioremap_nocache(EINTMASK,0x0000004);
          gpedat=ioremap_nocache(GPEDAT,0x0000004);//remap, ready for follow step
   gpfdat=ioremap_nocache(GPFDAT,0x0000004);
          gpgdat=ioremap_nocache(GPGDAT,0x0000004);
     
   writel(readl(gpgcon)&0xffbfffbf,gpgcon);  //set GPG3/EINT11,GPG11/EINT19
          writel(readl(gpgcon)|0x800080,gpgcon);//...
          writel(readl(gpfcon)&0xffffffee,gpfcon);//set GPF0/EINT0,GPF2/EINT2
          writel(readl(gpfcon)|0x22,gpfcon);//...
               
          writel(readl(intmask)&0xffffffda,intmask);//set interr enable
          writel(readl(eintmask)&0xfff7f7ff,eintmask);
         
          writel(readl(gpecon)& (~((3<<26)|(3<<22))) | ((1<<26)|(1<<22)),gpecon);//set gpe11 13 to output        
          writel(readl(gpedat)&(~((1<<13)|(1<<11))) ,gpedat);  //set GPE11 13 to 00
          writel(readl(gpgcon) & (~((3<<12)|(3<<4))) | ((1<<12)|(1<<4)),gpgcon);//set gpe2 6 to output       
          writel(readl(gpgdat)&(~((1<<6)|(1<<2))) ,gpgdat);  //set GPG2 6 to 00 :
   printk(KERN_ERR "have initial interr,ok!\n");
    set_irq_type(IRQ_EINT0, IRQT_FALLING);
    set_irq_type(IRQ_EINT2, IRQT_FALLING);
    set_irq_type(IRQ_EINT11, IRQT_FALLING);
    set_irq_type(IRQ_EINT19, IRQT_FALLING);

    rc = request_irq(IRQ_EINT0, irq_isr, SA_INTERRUPT, NAME, NULL);
    if (rc) {
        printk ("<1>keyirq 1 irq not registered. Error:%d\n", rc);
    }
    rc = request_irq(IRQ_EINT2, irq_isr, SA_INTERRUPT, NAME, NULL);
    if (rc) {
        printk ("<1>keyirq 2 irq not registered. Error:%d\n", rc);
    }
    rc = request_irq(IRQ_EINT11, irq_isr, SA_INTERRUPT, NAME, NULL);
    if (rc) {
        printk ("<1>keyirq 4 irq not registered. Error:%d\n", rc);
    }
rc = request_irq(IRQ_EINT19, irq_isr, SA_INTERRUPT, NAME, NULL);
    if (rc) {
        printk ("<1>keyirq 4 irq not registered. Error:%d\n", rc);
    }
    disable_irq(IRQ_EINT0);
    disable_irq(IRQ_EINT2);
    disable_irq(IRQ_EINT11);
    disable_irq(IRQ_EINT19);
#if 0
    enable_irq(IRQ_EINT0);
    enable_irq(IRQ_EINT2);
    enable_irq(IRQ_EINT11);
    enable_irq(IRQ_EINT19);
#endif
   
  /*  if ((rc = register_chrdev(keyirq_MAJOR, NAME, &keyirq_fops)) < 0){
        printk("keyirq: can't get major %d\n", keyirq_MAJOR);
        return 1;
    }*/
    return 0;
}
void keyirq_exit(void)
{
#if 1
    disable_irq(IRQ_EINT0);
    disable_irq(IRQ_EINT2);
    disable_irq(IRQ_EINT11);
    disable_irq(IRQ_EINT19);
#endif
    free_irq(IRQ_EINT0, NULL);
    free_irq(IRQ_EINT2, NULL);
    free_irq(IRQ_EINT11, NULL);
    free_irq(IRQ_EINT19, NULL);

    unregister_chrdev(keyirq_MAJOR, NAME);
}
module_init(keyirq_init);
module_exit(keyirq_exit);

相关帖子

沙发
wangkj| | 2009-2-24 08:05 | 只看该作者

你至少应该把错误信息贴出来吧

你应该在请求中断的函数中,加上printk,查找原因。错误不是瞎猜出来的。
一种故障,可能有10中原因。

使用特权

评论回复
板凳
tw2835| | 2009-2-27 23:41 | 只看该作者

……

cat /proc/interrupt  这种问题还是不难解决的

使用特权

评论回复
地板
xuwukong| | 2009-3-1 21:08 | 只看该作者

优龙的已经把键盘驱动编译进去了,占用了中断

更换内核
再换驱动吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

30

帖子

0

粉丝