这是案件程序:#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/cdev.h>
#define DEVICE_NAME "buttons" /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */
#define BUTTON_MAJOR 231 /* 主设备号 */
#define MAX_KEY_BUF 16
#define KEY_NUM 4
#define KEYSTATUS_UP 1
#define KEYSTATUS_DOWN 0
#define KEYSTATUS_DOWNX 2
#define KEY_TIMER_DELAY1 (HZ/50)
#define KEY_TIMER_DELAY (HZ/10)
#define BUF_HEAD (key_dev->buf[key_dev->head])
#define BUF_TAIL (key_dev->buf[key_dev->tail])
#define INCBUF(x,mod) ((++(x))&((mod)-1))
static volatile int *key;
void (*keyEvent)(int);
struct button_irq_desc {
int irq;
unsigned long flags;
char *name;
int pin;
};
/* 用来指定按键所用的外部中断引脚及中断触发方式, 名字 */
static struct button_irq_desc button_irqs [] = {
{IRQ_EINT19, IRQF_TRIGGER_FALLING, "KEY1",S3C2410_GPG11}, /* K1 */
{IRQ_EINT11, IRQF_TRIGGER_FALLING, "KEY2",S3C2410_GPG3}, /* K2 */
{IRQ_EINT2, IRQF_TRIGGER_FALLING, "KEY3",S3C2410_GPF2}, /* K3 */
{IRQ_EINT0, IRQF_TRIGGER_FALLING, "KEY4",S3C2410_GPF0}, /* K4 */
};
typedef unsigned char KEY_RET;
typedef struct
{
unsigned int keyStatus[KEY_NUM];
KEY_RET buf[MAX_KEY_BUF];
unsigned int head,tail;
wait_queue_head_t wq;
struct cdev key_cdev;
}KEY_DEV;
KEY_DEV *key_dev;
static struct timer_list key_timer[KEY_NUM];
static int isKey_down(int key)
{
int key_status;
key_status=!(s3c2410_gpio_getpin(button_irqs[key].pin));
return key_status;
}
static irqreturn_t buttons_interrupt(int irq,void *dev_id)
{
unsigned int key1;
//key=(volatile int *)dev_id;
key1=*key;
printk(KERN_NOTICE "interrupt-wawayu Error key_button_interrupt_handle adding");
disable_irq(button_irqs[2].irq);
printk(KERN_NOTICE "interrupt-wawayu Error key_button_interrupt_timer_add_before adding");
key_dev->keyStatus[2]=KEYSTATUS_DOWNX;
key_timer[2].expires=jiffies+KEY_TIMER_DELAY1;
add_timer(&key_timer[2]);
printk(KERN_NOTICE "interrupt-wawayu Error key_button_interrupt_timer_add_after adding");
return IRQ_RETVAL(IRQ_HANDLED);
}
static void keyEvent_raw(int key)
{
if(key_dev->keyStatus[key]==KEYSTATUS_DOWN)
{
BUF_HEAD=key+1;
}
key_dev->head=INCBUF(key_dev->head,MAX_KEY_BUF);
wake_up_interruptible(&(key_dev->wq));
}
static void keyEventnull(int key)
{
}
static void key_timer_handle(unsigned long data)
{
unsigned int key1;
key1=*key;
if(isKey_down(2))
{
printk(KERN_NOTICE "interrupt-wawayu Error key_timer_handle adding");
if(key_dev->keyStatus[2]==KEYSTATUS_DOWNX)
{
key_dev->keyStatus[2]=KEYSTATUS_DOWN;
key_timer[2].expires=jiffies+KEY_TIMER_DELAY;
(*keyEvent)(2);
add_timer(&key_timer[2]);
}
else
{
key_timer[2].expires=jiffies+KEY_TIMER_DELAY;
add_timer(&key_timer[2]);
}
}
else
{
key_dev->keyStatus[2]=KEYSTATUS_UP;
enable_irq(button_irqs[2].irq);
}
}
/* 应用程序对设备文件/dev/buttons执行open(...)时,
* 就会调用s3c24xx_buttons_open函数
*/
static int s3c24xx_buttons_open(struct inode *inode, struct file *file)
{
key_dev->head=key_dev->tail=0;
keyEvent=keyEvent_raw;
printk(KERN_NOTICE "interrupt-wawayu Error open_function_adding");
return 0;
}
/* 应用程序对设备文件/dev/buttons执行close(...)时,
* 就会调用s3c24xx_buttons_close函数
*/
static int s3c24xx_buttons_close(struct inode *inode, struct file *file)
{
keyEvent=keyEventnull;
return 0;
}
/* 应用程序对设备文件/dev/buttons执行read(...)时,
* 就会调用s3c24xx_buttons_read函数
*/
static KEY_RET read_key()
{
KEY_RET key_ret;
key_ret=BUF_TAIL;
key_dev->tail=INCBUF(key_dev->tail,MAX_KEY_BUF);
return key_ret;
}
static int s3c24xx_buttons_read(struct file *filp, char __user *buff,
size_t count, loff_t *offp)
{
KEY_RET key_ret;
unsigned long error;
retry:
if(key_dev->head !=key_dev->tail)
{
key_ret=read_key();
error=copy_to_user(buff,(char *)&key_ret,sizeof(key_ret));
}
else
{
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN;
interruptible_sleep_on(&(key_dev->wq));
goto retry;
}
return 0;
}
/* 这个结构是字符设备驱动程序的核心
* 当应用程序操作设备文件时所调用的open、read、write等函数,
* 最终会调用这个结构中的对应函数
*/
static struct file_operations s3c24xx_buttons_fops = {
.owner = THIS_MODULE, /* 这是一个宏,指向编译模块时自动创建的__this_module变量 */
.open = s3c24xx_buttons_open,
.release = s3c24xx_buttons_close,
.read = s3c24xx_buttons_read,
};
static int request_irqs(void)
{
int i;
for(i=0;i<KEY_NUM;i++)
{
if(request_irq(button_irqs.irq, buttons_interrupt,button_irqs.flags,button_irqs.name,(void *)&i))
{
printk(KERN_NOTICE "interrupt-wawayu Error %d adding",i);
return -1;
}
}
return 0;
}
static int free_irqs(void)
{
int i;
for(i=0;i<KEY_NUM;i++)
{
free_irq(button_irqs.irq,buttons_interrupt);
}
return 0;
}
static void buttons_setup_cdev(KEY_DEV *dev, int index)
{
int err, devno = MKDEV(BUTTON_MAJOR, index);
cdev_init(&dev->key_cdev, &s3c24xx_buttons_fops);
dev->key_cdev.owner = THIS_MODULE;
dev->key_cdev.ops = &s3c24xx_buttons_fops;
err = cdev_add(&dev->key_cdev, devno, 1);
if (err)
printk(KERN_NOTICE "Error %d adding LED%d", err, index);
}
/*
* 执行“insmod s3c24xx_buttons.ko”命令时就会调用这个函数
*/
static int __init s3c24xx_buttons_init(void)
{
int ret,i;
dev_t devno=MKDEV(BUTTON_MAJOR,0);
if(BUTTON_MAJOR)
ret=register_chrdev_region(devno,1,DEVICE_NAME);
else
{
ret=alloc_chrdev_region(&devno,0,1,DEVICE_NAME);
//BUTTON_MAJOR=MAJOR(devno);
}
if(ret<0)
return ret;
key_dev=kmalloc(sizeof(KEY_DEV),GFP_KERNEL);
if(!key_dev)
{
ret=- ENOMEM;
goto fail_malloc;
}
memset(key_dev, 0, sizeof(KEY_DEV));
buttons_setup_cdev(key_dev,0); //申请设备号,注册设备
request_irqs();
key_dev->head=key_dev->tail=0;
for(i=0;i<KEY_NUM;i++)
key_dev->keyStatus=KEYSTATUS_UP;
init_waitqueue_head(&key_dev->wq);
for(i=0;i<KEY_NUM;i++)
setup_timer(&key_timer,key_timer_handle,i);
return 0;
fail_malloc:unregister_chrdev_region(devno,1);
return 0;
}
/*
* 执行”rmmod s3c24xx_buttons.ko”命令时就会调用这个函数
*/
static void __exit s3c24xx_buttons_exit(void)
{
/* 卸载驱动程序 */
free_irqs();
cdev_del(&key_dev->key_cdev); /*注销cdev*/
kfree(key_dev); /*释放设备结构体内存*/
unregister_chrdev_region(MKDEV(BUTTON_MAJOR, 0), 1); /*释放设备号*/
}
/* 这两行指定驱动程序的初始化函数和卸载函数 */
module_init(s3c24xx_buttons_init);
module_exit(s3c24xx_buttons_exit);
/* 描述驱动程序的一些信息,不是必须的 */
MODULE_AUTHOR("http://www.100ask.net"); // 驱动程序的作者
MODULE_DESCRIPTION("S3C2410/S3C2440 BUTTON Driver"); // 一些描述信息
MODULE_LICENSE("GPL"); // 遵循的协议
这是oops信息:interrupt-wawayu Error open_function_adding<5>interrupt-wawayu Error key_button_interrupt_handle adding<1>Unable to handle kernel paging request at virtual address 7effbd78
pgd = c0004000
[7effbd78] *pgd=00000000
Internal error: Oops: 5 [#1]
Modules linked in: s3c24xx_buttons1
CPU: 0 Not tainted (2.6.22.6 #3)
PC is at buttons_interrupt+0x24/0xb4 [s3c24xx_buttons1]
LR is at release_console_sem+0x1e8/0x204
pc : [<bf0000a0>] lr : [<c0035c38>] psr: 60000013
sp : c0305ec0 ip : 00000000 fp : c0305ed4
r10: 3001e554 r9 : 41129200 r8 : 3001e5bc
r7 : 00000037 r6 : 00000000 r5 : bf001640 r4 : ebfffb9b
r3 : bf0003c8 r2 : c030c594 r1 : 60000093 r0 : 0000003c
Flags: nZCv IRQs on FIQs on Mode SVC_32 Segment kernel
Control: c000717f Table: 33c28000 DAC: 00000017
Process swapper (pid: 0, stack limit = 0xc0304260)
Stack: (0xc0305ec0 to 0xc0306000)
5ec0: c07ceb00 00000000 c0305ef4 c0305ed8 c005cc24 bf00008c c030ecf0 00000037
5ee0: c07ceb00 c030ed1c c0305f14 c0305ef8 c005de08 c005cbf0 00000000 00000015
5f00: 00000000 c036e674 c0305f2c c0305f18 c002f2ac c005dcf4 c030e3e8 00000015
5f20: c0305f4c c0305f30 c0024044 c002f22c ffffffff f0000000 00000020 c036e674
5f40: c0305fa4 c0305f50 c0024a24 c0024010 c0021c80 00000032 f0200000 60000013
5f60: c0025e34 c0304000 c0307e24 c036e674 3001e5bc 41129200 3001e554 c0305fa4
5f80: c0305f98 c0305f98 c0025e94 c0025ea0 60000013 ffffffff c0305fbc c0305fa8
5fa0: c00265b0 c0025e44 c0349b40 c0323bec c0305fcc c0305fc0 c0265b1c c002657c
5fc0: c0305ff4 c0305fd0 c0008b74 c0265ae4 c0008674 00000000 00000000 c002132c
5fe0: c0007175 c0324134 00000000 c0305ff8 30008030 c000891c 00000000 00000000
Backtrace:
[<bf00007c>] (buttons_interrupt+0x0/0xb4 [s3c24xx_buttons1]) from [<c005cc24>] (handle_IRQ_event+0x44/0x80)
r5:00000000 r4:c07ceb00
[<c005cbe0>] (handle_IRQ_event+0x0/0x80) from [<c005de08>] (handle_edge_irq+0x124/0x174)
r7:c030ed1c r6:c07ceb00 r5:00000037 r4:c030ecf0
[<c005dce4>] (handle_edge_irq+0x0/0x174) from [<c002f2ac>] (s3c_irq_demux_extint8+0x90/0xa4)
r7:c036e674 r6:00000000 r5:00000015 r4:00000000
[<c002f21c>] (s3c_irq_demux_extint8+0x0/0xa4) from [<c0024044>] (__exception_text_start+0x44/0x60)
r5:00000015 r4:c030e3e8
[<c0024000>] (__exception_text_start+0x0/0x60) from [<c0024a24>] (__irq_svc+0x24/0xa0)
Exception stack(0xc0305f50 to 0xc0305f98)
5f40: c0021c80 00000032 f0200000 60000013
5f60: c0025e34 c0304000 c0307e24 c036e674 3001e5bc 41129200 3001e554 c0305fa4
5f80: c0305f98 c0305f98 c0025e94 c0025ea0 60000013 ffffffff
r7:c036e674 r6:00000020 r5:f0000000 r4:ffffffff
[<c0025e34>] (default_idle+0x0/0x74) from [<c00265b0>] (cpu_idle+0x44/0x60)
[<c002656c>] (cpu_idle+0x0/0x60) from [<c0265b1c>] (rest_init+0x48/0x58)
r5:c0323bec r4:c0349b40
[<c0265ad4>] (rest_init+0x0/0x58) from [<c0008b74>] (start_kernel+0x268/0x2c0)
[<c000890c>] (start_kernel+0x0/0x2c0) from [<30008030>] (0x30008030)
Code: e5851008 e5914000 eb40d883 e59f3078 (e7930204)
Kernel panic - not syncing: Fatal exception in interrupt
请问错在哪里?????
哪位大大帮帮