2426|0

73

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

请帮忙看看 按键驱动的问题!! [复制链接]

最近参考网上资料,为自己的S3C44B0X开发板1X4按键写了驱动程序key1x4.c,以及简单的测试程序key_test.c:
/*********************************************************************/
/*key_test.c*/
#include
#include
#include
#include
#include
#include
int main()
{
        int  fd,count;
        char buf[3];
        printf("key1x4  test  ....\n");
        /*open key  device */
        fd=open("/dev/key1x4",O_RDWR);
         printf("fd = %x\n", fd);
        if(fd == -1)
        {
                printf("Could not open LED driver!\n");
                return -1;
        }
         else printf("key opened\n");

         while(1)
        {
          printf("key control led state :\n");
          read(fd, buf, 3);       
          printf("------------------------------------\n");       
          printf ("LED1=%c ; LED2=%c ; LED1=%c\n",buf[0],buf[1],buf[2]);
          printf("------------------------------------\n");          

        }
  
        /*close led device */
        close(fd);
        
        printf("right end!!!!\n");

        return 0;
}
运行该测试程序后,程序在超级中断里面打印
key1x4  test  ....
fd =3
key opened
key  control led state  :
后,整个系统都死在那了,只能重启系统。
下面是驱动程序:
/*************************************************************************/
/*key1x4.c*/
/*
*******************************
key & led  driver for my S3C44b0X board
*******************************
*/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include
#include
#include
#include
#include

#define key_MAJOR        63
#define key_DEVNAME   "key1x4"
#define BIT_EINT4567   (0x1<<21)

#define key_irq  S3C44B0X_INTERRUPT_EINT4567

static     u32      gnPCONC_backup;
static     int      state;
static     int      INT4567=0;
static     char     key_buf[3];
static     int      flag=0;

DECLARE_WAIT_QUEUE_HEAD(key_wait);

static struct timer_list  key_timer;  

struct led_local {
       
  char *device;
                       
} key[4]={{"key1"}, {"key2"}, {"key3"}, {"key4"}};

void led_manager(int arg, int nr)
{
        if (arg == 0)
        {
                        outb(inb(S3C44B0X_PDATC) | (1 << nr ), S3C44B0X_PDATC);
                key_buf[nr]=1;
               
            }
        else if (arg == 1)
        {
                       outb(inb(S3C44B0X_PDATC) & ~(1 << nr ), S3C44B0X_PDATC);
                key_buf[nr]=0;
            }
              else
               printk (KERN_INFO "Wrong arg\n");
}

static int key_open(struct inode *inode ,struct file *file)
{   
   printk (KERN_INFO "Hey! device opened\n");
   return 0;
       
}

static int key_read(struct file *file ,char * buf,size_t count, loff_t * offset )
{
          
       while (1)
        {
                       //interruptible_sleep_on( &key_wait);
            wait_event_interruptible(key_wait,flag);
       
                  count=3;
          
                  if(copy_to_user(buf,key_buf,count))
            {
                printk("error reading, copy_to_user\n");
                return  -EFAULT;
              }
               
              flag=0;
        }
          
      return count;


}

       
static int key_release(struct inode * inode ,struct file *file)
{       
        int i;
          for(i=0;i<4;i++)
        {      
                 free_irq(key_irq, key.device);

        }
                  
       printk (KERN_INFO "Hmmm! device closed\n");
        return 0;
}

static struct file_operations key_ops={
                open: key_open,
                read: key_read,
                release: key_release,
};

static void key_task(unsigned long irq)/*中断下半部*/
{
        INT4567=inb(S3C44B0X_EXTINPND);

        if (!INT4567)  
                 return;
       
            if (irq == key_irq)
           {   
            switch (INT4567 )
              {
                          case 1:
                           led_manager(++state%2, 1);               
                                    break;
                        case 2:
                           led_manager(++state%2, 2);
                           break;
                        default:
                           led_manager(++state%2, 3);   
                           break;                               
                          }
            }
          
               else
         printk (KERN_WARNING"%d irq  wrong!", key_irq);
                 
        INT4567=0;         
        outb(0x0f,S3C44B0X_EXTINPND);
                        
        flag=1;
        wake_up_interruptible(&key_wait);           
        enable_irq(irq);      
        return ;  
}


static void key_interrupt(int irq, void *dev_id, struct pt_regs *regs)/*中断上半部*/
{
             
        disable_irq(irq);
               
        /*-------------------------*/
        /* setup kernel timer                 */
        /*-------------------------*/
        init_timer(&key_timer);
        key_timer.function = key_task;
        key_timer.data = irq;
        key_timer.expires = 10;
        add_timer(&key_timer);
       
        /*--------------------------*/
        /* return from interrupt   */
        /*--------------------------*/
        return;

         
}

/* device  init*/

int key_init(void)
{            
       int    result,i;
       u32  temp;
       u16  pdatc;
          
        request_region(S3C44B0X_PCONC, 12, "key_DEVNAME");
       
          result = register_chrdev(key_MAJOR,key_DEVNAME,&key_ops);
       
            if (result<0)
        {
                printk (KERN_WARNING "led: can't get major number %d\n", key_MAJOR);
                return result;
            }
               
        gnPCONC_backup = inl(S3C44B0X_PCONC);

        printk("PCONC = %x\n",gnPCONC_backup);

         temp = gnPCONC_backup & 0xFFFFFF03;
        temp |= 0x57;
       
         pdatc=(inl(S3C44B0X_PDATC) & 0x7);
          
         outl(temp, S3C44B0X_PCONC);
         outw(0x0,S3C44B0X_PUPC);
          outw(pdatc, S3C44B0X_PDATC);
               
          printk (KERN_INFO "key_ioctl driver done\n");

         for(i=0;i<4;i++)
        {      
                 result=request_irq(key_irq, key_interrupt,SA_SHIRQ, key.device,key.device);
              
                    if (result)
                         {
                        printk(KERN_INFO "led: can't get assigned irq\n");
                          }
                else
                    {         printk(KERN_INFO "led: get assigned irq \n");
                }
               
        }
                  
        // 将多功能端口G设置为中断功能
            printk(KERN_INFO "S3C44B0X_PCONG=0x%x\n", inw(S3C44B0X_PCONG));
            outw(0xff00, S3C44B0X_PCONG);
        temp=inb(S3C44B0X_PUPG);
        temp|=0xf0;
        outb(temp,S3C44B0X_PUPG);
            printk(KERN_INFO "S3C44B0X_PCONG=0x%x\n", inw(S3C44B0X_PCONG));
               
        //设置外部中断控制寄存器EXINT ,外部中断请求寄存EXTINTPND
        outl(0x22222222,S3C44B0X_EXTINT); //EXINT
         outb(0x0f,S3C44B0X_EXTINPND);      //EXTINTPND

        //设置中断控制器INTCON
            outb(0x5,S3C44B0X_INTCON);  //INTCON
        // outl(~(BIT_GLOBAL|BIT_EINT4567),S3C44B0X_INTMSK);//INTMSK开中断
       
         init_waitqueue_head(&key_wait);
       
         return 0;

}


int key_exit(void)
{        
        int result;

        release_region(S3C44B0X_PCONC, 12);

        if((result = unregister_chrdev(key_MAJOR,key_DEVNAME))<0)
        {
        printk("key_dev. unable to release major %d for read \n",key_MAJOR);
                return result;
        }
            printk (KERN_INFO "key_ioctl cleaned up\n");       
        return 0;
}







点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表