免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3203 | 回复: 6
打印 上一主题 下一主题

S3C2440按键驱动错误 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-09-06 13:41 |只看该作者 |倒序浏览
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/interrupt.h>
//#include <asm/memory.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>

#define KEYNUM 5
#define KEY_UP 0
#define KEY_DOWN 1
#define KEY_DOWNX 2
#define MAJOR 255
#define KEY_TIMER_DELAY (HZ/50)
#define GPIOG_REG_ADDR 0x56000064//gpio_g data register phys address

struct b_dev
{
  struct cdev b_cdev;
  char key_state_buf[KEYNUM];//up or down
  unsigned int irq[KEYNUM];
  struct timer_list tl;
};

struct b_dev *pb_dev;
int b_open(struct inode * inodep,struct file * filp)
{
  return 0;
}
int b_release(struct inode * inodep,struct file * filp)
{
  return 0;
}
int b_read(struct file * filp,char * buf,size_t size,loff_t offset)
{
  if(!access_ok(VERIFY_WRITE,buf,size))
  {
    printk(KERN_INFO "buf can't write\n";
    return -EFAULT;
  }
  int key_num,count=0;
  for(key_num=0;key_num!=KEYNUM;key_num++)
  {
    if(pb_dev->key_state_buf[key_num]==KEY_DOWNX && count<size)
    {
      put_user('0'+key_num,buf+count);
      pb_dev->key_state_buf[key_num]=KEY_UP;
      count++;
    }
  }
  return count;
}
struct file_operations f_ops=
{
  .open=b_open,
  .read=b_read,
  .release=b_release,
  .owner=THIS_MODULE,
};

void timer_handler(unsigned long sleep_time)
{
  unsigned int *p_gpiog=__va(GPIOG_REG_ADDR);//phys address to virtual address
  unsigned int gpio_g=*p_gpiog;
  if(gpio_g & 0x0001  && pb_dev->key_state_buf[0] == KEY_DOWN){
    //button 1
    pb_dev->key_state_buf[0]=KEY_DOWNX;
  }
  else if(gpio_g & 0x0008 && pb_dev->key_state_buf[1] == KEY_DOWN){
    //button 2
    pb_dev->key_state_buf[1]=KEY_DOWNX;
  }
  else if(gpio_g & 0x0020 && pb_dev->key_state_buf[2] == KEY_DOWN){
    //button 3
    pb_dev->key_state_buf[2]=KEY_DOWNX;
  }
  else if(gpio_g & 0x0040 && pb_dev->key_state_buf[3] == KEY_DOWN){
    //button 4
    pb_dev->key_state_buf[3]=KEY_DOWNX;
  }
  else if(gpio_g & 0x0080 && pb_dev->key_state_buf[4] == KEY_DOWN){
    //button 5
    pb_dev->key_state_buf[4]=KEY_DOWNX;
  }
  else if(gpio_g & 0x0800 && pb_dev->key_state_buf[5] == KEY_DOWN){
    //button 6
    pb_dev->key_state_buf[5]=KEY_DOWNX;
  }
  printk(KERN_INFO "timer\n";
}
void irq_handler(int irq,void *dev_id,struct pt_regs *regs)
{
  pb_dev->tl.expires=jiffies+KEY_TIMER_DELAY;
  add_timer(&pb_dev->tl);
  switch(irq)
  {
    case 16+36:
      pb_dev->key_state_buf[0]=KEY_DOWN;
      break;
    case 16+39:
      pb_dev->key_state_buf[1]=KEY_DOWN;
      break;
    case 16+41:
      pb_dev->key_state_buf[2]=KEY_DOWN;
      break;
    case 16+42:
      pb_dev->key_state_buf[3]=KEY_DOWN;
      break;
    case 16+43:
      pb_dev->key_state_buf[4]=KEY_DOWN;
      break;
    case 16+47:
      pb_dev->key_state_buf[5]=KEY_DOWN;
      break;
    default:
      break;
  }
  printk(KERN_INFO "IRQ\n";
}

void init_irqs()
{
  pb_dev->irq[0]=16+36;
  pb_dev->irq[1]=16+39;
  pb_dev->irq[2]=16+41;
  pb_dev->irq[3]=16+42;
  pb_dev->irq[4]=16+43;
  pb_dev->irq[5]=16+47;
  int key_num;
  for(key_num=0;key_num<KEYNUM;key_num++)
  {
    request_irq(pb_dev->irq[key_num],irq_handler,SA_SHIRQ,"buttons",pb_dev);
    set_irq_type(pb_dev->irq[key_num],IRQ_TYPE_EDGE_FALLING);
  }
}
static int b_init(void)
{
  pb_dev=kmalloc(sizeof(struct b_dev),GFP_KERNEL);
  memset(pb_dev,0,sizeof(struct b_dev));
  int key_num;
  for(key_num=0;key_num<KEYNUM;key_num++)
  {
    pb_dev->key_state_buf[key_num]=KEY_UP;
  }
  dev_t devno;
  devno=MKDEV(MAJOR,0);
  cdev_init(&pb_dev->b_cdev,&f_ops);
  pb_dev->b_cdev.owner=THIS_MODULE;
  pb_dev->b_cdev.ops=&f_ops;
  int err=cdev_add(&pb_dev->b_cdev,devno,1);
  if(err)
    printk(KERN_NOTICE "Error %d\n",err);
  setup_timer(&pb_dev->tl,timer_handler,20);
  init_irqs();
  printk(KERN_INFO "init over\n";
}

static void b_exit(void)
{
  int key_num;
  for(key_num=0;key_num<KEYNUM;key_num++)
  {
    free_irq(pb_dev->irq[key_num],pb_dev);
  }
  cdev_del(&pb_dev->b_cdev);
  kfree(pb_dev);
  unregister_chrdev_region(MKDEV(MAJOR,0),1);
}

MODULE_AUTHOR("scy";
MODULE_LICENSE("Dual BSD/GPL";

module_init(b_init);
module_exit(b_exit);


当有按键时,系统就会报错
[root@FriendlyARM /]# IRQ
irq event 59: bogus return value 7
[ <c02d37e8>] (dump_stack+0x0/0x14) from [ <c00606ac>] (__report_bad_irq+0x28/0x94
)
[ <c0060684>] (__report_bad_irq+0x0/0x94) from [ <c006088c>] (note_interrupt+0x174
/0x1f0)
r5:c03d5be0 r4:c03d5be0
[ <c0060718>] (note_interrupt+0x0/0x1f0) from [ <c0060fb4>] (handle_edge_irq+0xc0/
0x160)
[ <c0060ef4>] (handle_edge_irq+0x0/0x160) from [ <c0032764>] (s3c_irq_demux_extint
8+0x9c/0xa
r7:c03ff284 r6:00000001 r5:00000000 r4:0000003b
[ <c00326c8>] (s3c_irq_demux_extint8+0x0/0xa from [ <c0028044>] (__exception_tex
t_start+0x44/0x70)
r7:c03ff284 r6:00000000 r5:c0425474 r4:00000015
[ <c0028000>] (__exception_text_start+0x0/0x70) from [ <c0028a44>] (__irq_svc+0x24
/0xa0)
Exception stack(0xc03cdf40 to 0xc03cdf8
df40: f4100000 00000032 f4100000 60000013 c0029edc c03cc000 c0029edc c03ff284
df60: 3001c920 41129200 3001c8ec c03cdf94 c03cdf98 c03cdf88 c002a4f8 c0029f3c
df80: 60000013 ffffffff
r7:c03ff284 r6:00000020 r5:f4000000 r4:ffffffff
[ <c0029edc>] (default_idle+0x0/0xac) from [ <c002a4f8>] (cpu_idle+0x4c/0x6
[ <c002a4ac>] (cpu_idle+0x0/0x6 from [ <c02d2124>] (rest_init+0x5c/0x70)
r7:c03d0440 r6:c001e000 r5:c03ff240 r4:c0423264
[ <c02d20c8>] (rest_init+0x0/0x70) from [ <c0008930>] (start_kernel+0x200/0x26
[ <c0008730>] (start_kernel+0x0/0x26 from [ <30008034>] (0x30008034)
r6:c001ed34 r5:c03ff35c r4:c0007175
handlers:
[ <bf000440>] (irq_handler+0x0/0x130 [my_bdri])
Unable to handle kernel paging request at virtual address e6000064
pgd = c3acc000
[e6000064] *pgd=00000000
Internal error: Oops: 5 [#1]
Modules linked in: my_bdri
CPU: 0    Not tainted  (2.6.29.4-FriendlyARM #2)
PC is at timer_handler+0x10/0x118 [my_bdri]
LR is at run_timer_softirq+0x1b0/0x230
pc : [ <bf0000cc>]    lr : [ <c0044c80>]    psr: 20000013
sp : c03cde80  ip : c03cde90  fp : c03cde8c
r10: c04211c8  r9 : c03d4140  r8 : c03cc000
r7 : bf0000bc  r6 : c03cdea0  r5 : 00000100  r4 : c04209c0
r3 : e6000000  r2 : c03cdea0  r1 : c3a612dc  r0 : 00000014
Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: c000717f  Table: 33acc000  DAC: 00000017
Process swapper (pid: 0, stack limit = 0xc03cc26
Stack: (0xc03cde80 to 0xc03ce000)
de80: c03cded4 c03cde90 c0044c80 bf0000cc c03cdeb4 c04217c8 c04215c8 c04213c8
dea0: c03cdea0 c03cdea0 c03cdecc 00000004 00000001 00000100 c03cc000 c04207e0
dec0: 00000001 0000000a c03cdf0c c03cded8 c0040204 c0044ae0 c03d5514 c03d2c58
dee0: 0000001e 0000001e c0425474 00000000 c03ff284 3001c920 41129200 3001c8ec
df00: c03cdf1c c03cdf10 c00402cc c0040198 c03cdf3c c03cdf20 c0028048 c0040294
df20: ffffffff f4000000 00004000 c03ff284 c03cdf94 c03cdf40 c0028a44 c0028010
df40: f4100000 00000032 f4100000 60000013 c0029edc c03cc000 c0029edc c03ff284
df60: 3001c920 41129200 3001c8ec c03cdf94 c03cdf98 c03cdf88 c002a4f8 c0029f3c
df80: 60000013 ffffffff c03cdfb4 c03cdf98 c002a4f8 c0029eec c0423264 c03ff240
dfa0: c001e000 c03d0440 c03cdfc4 c03cdfb8 c02d2124 c002a4bc c03cdff4 c03cdfc8
dfc0: c0008930 c02d20d8 c0008470 00000000 00000000 c001ed38 00000000 c0007175
dfe0: c03ff35c c001ed34 00000000 c03cdff8 30008034 c0008740 00000000 00000000
Backtrace:
[ <bf0000bc>] (timer_handler+0x0/0x118 [my_bdri]) from [ <c0044c80>] (run_timer_so
ftirq+0x1b0/0x230)
[ <c0044ad0>] (run_timer_softirq+0x0/0x230) from [ <c0040204>] (__do_softirq+0x7c/
0xfc)
[ <c0040188>] (__do_softirq+0x0/0xfc) from [ <c00402cc>] (irq_exit+0x48/0x50)
[ <c0040284>] (irq_exit+0x0/0x50) from [ <c0028048>] (__exception_text_start+0x48/
0x70)
[ <c0028000>] (__exception_text_start+0x0/0x70) from [ <c0028a44>] (__irq_svc+0x24
/0xa0)
Exception stack(0xc03cdf40 to 0xc03cdf8
df40: f4100000 00000032 f4100000 60000013 c0029edc c03cc000 c0029edc c03ff284
df60: 3001c920 41129200 3001c8ec c03cdf94 c03cdf98 c03cdf88 c002a4f8 c0029f3c
df80: 60000013 ffffffff
r7:c03ff284 r6:00004000 r5:f4000000 r4:ffffffff
[ <c0029edc>] (default_idle+0x0/0xac) from [ <c002a4f8>] (cpu_idle+0x4c/0x6
[ <c002a4ac>] (cpu_idle+0x0/0x68) from [ <c02d2124>] (rest_init+0x5c/0x70)
r7:c03d0440 r6:c001e000 r5:c03ff240 r4:c0423264
[ <c02d20c8>] (rest_init+0x0/0x70) from [ <c0008930>] (start_kernel+0x200/0x268)
[ <c0008730>] (start_kernel+0x0/0x268) from [ <30008034>] (0x30008034)
r6:c001ed34 r5:c03ff35c r4:c0007175
Code: e1a0c00d e92dd800 e24cb004 e3a034e6 (e5931064)
Kernel panic - not syncing: Fatal exception in interrupt
==================================================================================
求高手帮助解决。。

论坛徽章:
0
2 [报告]
发表于 2009-09-06 19:51 |只看该作者
unsigned int *p_gpiog=__va(GPIOG_REG_ADDR);//phys address to virtual address
这个p_gpiog 是不是得改成volatile

add_timer(&pb_dev->tl);
改成mod_timer


在irq_handle中添加printk看看是否中断调用到了

论坛徽章:
0
3 [报告]
发表于 2009-09-06 23:07 |只看该作者
中断调用到了,我在/proc/inter...那个文件里也看到中断确实被注册了

论坛徽章:
0
4 [报告]
发表于 2009-09-06 23:09 |只看该作者
能看出错误就在timer_handler里。。。

论坛徽章:
0
5 [报告]
发表于 2009-09-06 23:11 |只看该作者
unsigned int *p_gpiog=__va(GPIOG_REG_ADDR);//
对于GPIO寄存器的物理地址,我这么将它转换成虚拟地址对么???(然后指针获取GPIO寄存器中的数据)

论坛徽章:
0
6 [报告]
发表于 2009-09-09 22:59 |只看该作者

回复 #5 shuchuanyu 的帖子

从“Unable to handle kernel paging request at virtual address e6000064“可以看出,应该是
”__va(GPIOG_REG_ADDR)”转换出来的虚拟地址不对,我的内核里面2440的GPIO寄存器的地址是这样定义的:
#ifndef __ASSEMBLY__
#define S3C2410_ADDR(x)   ((void __iomem *)0xF0000000 + (x))
#else
#define S3C2410_ADDR(x)   (0xF0000000 + (x))
#endif
#define S3C24XX_VA_GPIO    S3C2410_ADDR(0x00E00000)
#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
可见,GPIO寄存器的虚拟地址应该从0xF00E****。
你可以尝试先用上面的方法得到GPIOG的虚拟地址,然后使用内核里面的__raw_readl()函数来读取该寄存器的值。

[ 本帖最后由 gqwang2005 于 2009-9-9 23:09 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2014-06-26 18:34 |只看该作者
仔细检查timer_handler里面的每一个指针变量,尤其是全局变量。还有就是函数timer_handler的第一次执行,有可能在中断之前,因为定时到了(中断还没到)它自然就执行了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP