0vk0 发表于 2011-03-04 19:46

今天小心奕奕的把代码拷出来,是个按键驱动,大家帮忙看一下

本帖最后由 0vk0 于 2011-03-04 19:50 编辑

是个按键驱动,大家帮忙看一下,现在按键抬起可以检测到,但再按别的



我测试时老是出现:
   
      当换一个按键时,会出现前一个按键,比如我按1时,按下会打印1,抬起会打印1,当我换按2时,第一遍按下会打印1,抬起会打印2,再第二遍的时候就不会了


      当我换按5时,第一遍按下会打印2,抬起会打印5,再第二遍的时候也不会了,请帮帮忙看下程序,谢谢了,第二个是应该层的测试程序#include <asm/gpio.h>
#include <asm/jzsoc.h>
……

#define DEVICE_NAME "keypad"
#define    MAX_KEY_COUNT32                                    

#define HC164_CP       89   //kb2
#define HC164_DS       88   //kb1
#define INT_KEY1       93   //kb3
#define INT_KEY2       91   //kb4

#define KEY1_IRQ       (IRQ_GPIO_0 + INT_KEY1)
#define KEY2_IRQ       (IRQ_GPIO_0 + INT_KEY2)
typedef struct
{
    unsigned long jiffy;
    unsigned char buf;   
    unsigned int head,tail;               
}KEY_BUFFER;

static KEY_BUFFER g_keyBuffer;   
static spinlock_t buffer_lock;

static int   Keypad_major = 255;

int a=200,b=201;

/*
*/
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 = 0;
      g_keyBuffer.jiffy = 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;
      if (ulTick< 5000)   
            break;
      g_keyBuffer.buf = 0;
      g_keyBuffer.jiffy = 0;
      g_keyBuffer.head ++;
      g_keyBuffer.head &= (MAX_KEY_COUNT -1);
    }
    spin_unlock_irq(&buffer_lock);
}
/*
*/
void _74HC164Send(unsigned char d)
{
      int j;

      for(j=0;j<8;j++)
      {
                if (d&1)
                        __gpio_set_pin(HC164_DS);
                else
                        __gpio_clear_pin(HC164_DS);

                mdelay(1);
                __gpio_set_pin(HC164_CP);
                mdelay(1);
                __gpio_clear_pin(HC164_CP);

               d >>= 1;
      }
}

/*
*/
static void init_gpio(void)
{
          __gpio_as_input(INT_KEY1);
      __gpio_as_input(INT_KEY2);

      __gpio_as_output(HC164_CP);
      __gpio_as_output(HC164_DS);
   
      __gpio_clear_pin(HC164_CP);
      __gpio_clear_pin(HC164_DS);

         _74HC164Send(0);
}

/*
*/
static __inline void enable_irqs(void)
{
      unsigned long flags;

      spin_lock_irqsave(buffer_lock, flags);
      __gpio_unmask_irq(INT_KEY1);
      __gpio_unmask_irq(INT_KEY2);
      spin_unlock_irqrestore(buffer_lock, flags);

}

/*
*/
static __inline void disable_irqs(void)
{
      unsigned long flags;

      spin_lock_irqsave(buffer_lock, flags);
      __gpio_mask_irq(INT_KEY1);
      __gpio_mask_irq(INT_KEY2);
      spin_unlock_irqrestore(buffer_lock, flags);
}

/*
*/
static unsigned char num = 0;
static __inline unsigned char button_scan(int irq)
{
   unsigned char ret=0xff;
   unsigned char i;

    if(!(__gpio_get_pin(INT_KEY1)))
    {
   for(i=1;i<9;i++)
   {
         printk("i=%d\n",i);
         __gpio_set_pin(HC164_DS);
         mdelay(1);
         __gpio_set_pin(HC164_CP);
         mdelay(1);
         __gpio_clear_pin(HC164_CP);
         if(__gpio_get_pin(INT_KEY1))
         {
                        num=i;            //此处改动过
                        return i;
         }
   }
    }
    else
    {
       if(!(__gpio_get_pin(INT_KEY2)))
       {
          for(i=1;i<9;i++)
          {
         printk("key2 i=%d\n",i);
            __gpio_set_pin(HC164_DS);
            mdelay(1);
            __gpio_set_pin(HC164_CP);
            mdelay(1);
            __gpio_clear_pin(HC164_CP);
            if(__gpio_get_pin(INT_KEY2))
            {
               num=i+8;             //此处改动
               return i;            
            }
          }
       }
    }
    return ret ;
}

/*
*
*/
static irqreturn_t button_down_irq(int irq, void *dev_id)
{
    unsigned char ucKey;
disable_irqs();
udelay(1000);
    ucKey = button_scan(irq);      
   
    if ((ucKey >= 1) && (ucKey <= 16))
    {
      if (((g_keyBuffer.head + 1) & (MAX_KEY_COUNT - 1)) != g_keyBuffer.tail)
      {
            spin_lock_irq(&buffer_lock);
            g_keyBuffer.buf = ucKey;
            g_keyBuffer.jiffy = GetTickCount();
            g_keyBuffer.tail ++;
            g_keyBuffer.tail &= (MAX_KEY_COUNT - 1);
            spin_unlock_irq(&buffer_lock);
      }
    }
   
    _74HC164Send(0);
    __gpio_ack_irq(INT_KEY1); // clear status
    __gpio_ack_irq(INT_KEY2); // clear status
    enable_irqs();

    return IRQ_HANDLED;
}

static irqreturn_t button_rise_irq(int irq, void *dev_id)
{
    unsigned char ucKey;
    disable_irqs();
    udelay(1000);
    ucKey = num;
    // *****************************
    buttonup_scan();
   
    if ((ucKey >= 1) && (ucKey <= 16))
    {
      if (((g_keyBuffer.head + 1) & (MAX_KEY_COUNT - 1)) != g_keyBuffer.tail)
      {
            spin_lock_irq(&buffer_lock);
            g_keyBuffer.buf = ucKey;
            g_keyBuffer.jiffy = GetTickCount();
            g_keyBuffer.tail ++;
            g_keyBuffer.tail &= (MAX_KEY_COUNT - 1);
            spin_unlock_irq(&buffer_lock);
      }
    }
   
    _74HC164Send(0);
    __gpio_ack_irq(INT_KEY1); // clear status
    __gpio_ack_irq(INT_KEY2); // clear status
    enable_irqs();

    return IRQ_HANDLED;
}

/*
*
*/
static int request_irqs(void)
{
   __gpio_as_irq_fall_edge(INT_KEY1);         //下降沿发生中断
   __gpio_as_irq_fall_edge(INT_KEY2);

   __gpio_as_irq_rise_edge(INT_KEY1);         //上升沿发生中断
   __gpio_as_irq_rise_edge(INT_KEY2);

            if(request_irq(KEY1_IRQ, button_rise_irq, IRQF_DISABLED | IRQF_SHARED, DEVICE_NAME, &a)){
                printk("Could not allocate key1 IRQ:%d\n",KEY1_IRQ);
                return -EINVAL;
   }
   if(request_irq(KEY2_IRQ, button_rise_irq,IRQF_DISABLED | IRQF_SHARED, DEVICE_NAME, &a)){
                free_irq(KEY1_IRQ, &a);
                printk("Could not allocate key2 IRQ:%d\n",KEY2_IRQ);
                return -EINVAL;
                }
               
                   if(request_irq(KEY1_IRQ, button_down_irq,IRQF_DISABLED | IRQF_SHARED, DEVICE_NAME, &b)){
                printk("Could not allocate key1 IRQ:%d\n",KEY1_IRQ);
                return -EINVAL;
   }
   if(request_irq(KEY2_IRQ, button_down_irq,IRQF_DISABLED | IRQF_SHARED, DEVICE_NAME, &b)){
                free_irq(KEY1_IRQ, &b);
                printk("Could not allocate key2 IRQ:%d\n",KEY2_IRQ);
                return -EINVAL;
                }
                        
   __gpio_ack_irq(INT_KEY1); // clear status
   __gpio_ack_irq(INT_KEY2); // clear status
    return 0;
}

/*
*
*/
static __inline void free_irqs(void)
{
    free_irq(KEY1_IRQ, &a);
    free_irq(KEY1_IRQ, &b);
    free_irq(KEY2_IRQ, &a);
    free_irq(KEY2_IRQ, &b);
}
/*
*
*/
static int keypad_open(struct inode *inode,struct file *filp)
{
    int ret = nonseekable_open(inode, filp);
    if (ret >= 0)
    {
    printk("keypad opened ret>0.\n");
      init_keybuffer();
      enable_irqs();
    }
    printk("keypad opened.\n");
    return ret;
}

/*
*
*/
static int keypad_release(struct inode *inode,struct file *filp)
{
    disable_irqs();
    printk("keypad release.\n");
    return 0;
}

/*
*
*/
static ssize_t keypad_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 = (char)(g_keyBuffer.buf);
      g_keyBuffer.buf = 0;
      g_keyBuffer.jiffy = 0;
      g_keyBuffer.head ++;
      g_keyBuffer.head &= (MAX_KEY_COUNT - 1);
      ret ++;
    }
    spin_unlock_irq(&buffer_lock);
    return ret;
}

/*
*
*/
static int keypad_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    init_keybuffer();
    return 1;
}

/*
*/
static void led_setup_cdev(struct cdev *dev,int minor,struct file_operations *fops)
{
    int err;
    int devno=MKDEV(Keypad_major,minor);
    cdev_init(dev,fops);
    dev->owner=THIS_MODULE;
    dev->ops=fops;
    err=cdev_add(dev,devno,1);
    if(err)
    printk(KERN_INFO"Error %d adding button %d\n",err,minor);
}
/*
*/
static struct file_operations keypad_fops =
{
    .owner = THIS_MODULE,
    .ioctl = keypad_ioctl,
    .open = keypad_open,
    .read = keypad_read,
    .release = keypad_release,
};

static struct cdev SimpleDevs;

/*
*
*/

static intKeyPad_Init(void)
{
    int ret;
    int result;
    dev_t dev;

    dev=MKDEV(Keypad_major,0);
    if(Keypad_major)
   result=register_chrdev_region(dev,1,DEVICE_NAME);
    else
   {
      result=alloc_chrdev_region(&dev,0,1,DEVICE_NAME);
      Keypad_major=MAJOR(dev);
   }
    if(result<0)
   {
      printk(KERN_WARNING"Keypad:unable to get major %d\n",Keypad_major);      
      return result;
   }
    if(Keypad_major==0)
    Keypad_major=result;
    led_setup_cdev(&SimpleDevs,0,&keypad_fops);
    init_gpio();
    ret = request_irqs();
    if (ret < 0)
    {
      cdev_del(&SimpleDevs);
      unregister_chrdev_region(MKDEV(Keypad_major,0),1);
      return ret;
    }
    printk(KERN_INFO"keypad register ok!!!!!!!!!!\n");
    return 0;
}

/*
*
*/
static void __exit KeyPad_Exit(void)
{
    disable_irqs();
    free_irqs();
    cdev_del(&SimpleDevs);
    unregister_chrdev_region(MKDEV(Keypad_major,0),1);
    printk("button device uninstalled\n");

}

module_init(KeyPad_Init);
module_exit(KeyPad_Exit);

MODULE_AUTHOR("zhyh");
MODULE_DESCRIPTION("keypad driver");
MODULE_LICENSE("GPL");

dreamice 发表于 2011-03-05 11:35

你这个很难说出什么问题,程序本身估计没什么问题,与处理逻辑可能关系很大

0vk0 发表于 2011-03-07 19:49

你这个很难说出什么问题,程序本身估计没什么问题,与处理逻辑可能关系很大
dreamice 发表于 2011-03-05 11:35 http://linux.chinaunix.net/bbs/images/common/back.gifif(request_irq(KEY1_IRQ, button_rise_irq, IRQF_DISABLED | IRQF_SHARED, DEVICE_NAME, &a)){

                printk("Could not allocate key1 IRQ:%d\n",KEY1_IRQ);

                return -EINVAL;

   }

这里是否正确 ,我这里IRQF_DISABLED | IRQF_SHARED换成IRQF_TRIGGER_FALLING | IRQF_DISABLED |和IRQF_TRIGGER_FALLING |IRQF_DISABLED ,就会出现insmod: cannot insert 'key.ko': invalid parameter ,我知道是dev_id这里错误,但是我应该怎么改,请大虾赐教

jn200002 发表于 2011-03-09 16:35

首先

struct button_irq_desc {
    int irq;
    int gpio;
};


static struct button_irq_desc button_irqs [] = {
    {IRQ_EINTx, GPx0(x)}, /* K1 */
    {xxxxxxxxxxxxxxxxx} , /*K2*/
    ...
};

然后把你的申请写成个循环

其次,参数写成IRQF_SHARED | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,

处理所谓按下抬起,在一个中断处理里做就可以了。

最后,你去看看gpio_keys.c   

内核是最好的老师,抄吧。不是非得写的跟内核不一样才能彰显代码的个性……
页: [1]
查看完整版本: 今天小心奕奕的把代码拷出来,是个按键驱动,大家帮忙看一下