外部中断按键驱动程序编写

来源:互联网 发布:c高级编程 编辑:程序博客网 时间:2024/05/12 09:50

//包含必须的头文件
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/interrupt.h>
//#include <linux/delay.h>  //定义了mdelay() ndelay() msleep()等等延时函数
//#include <asm/uaccess.h>  //定义内核空间和用户空间装换的函数等……
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>


//定义常用的变量
#define device_name  "my_irq"   //定义设备名
#define device_major 231        //定义主设备号
#define irq  IRQ_EINT1          //定义中断号为外部中断1
static int  count =0;           //计数

 

//打开函数 不起什么作用,可以不要
static  int irq_open(struct inode *inode,struct file *file)
{
 printk("Enter irq_open...");
 return 0;
}

 

//关闭函数 不起什么作用
static int irq_close(struct inode *inode, struct file *file)
{
 printk("Enter irq_close");
 return 0;
}

//中断服务子程序
static irqreturn_t irq_interrupt()  //注意这里的函数返回类型
{
 count++;
 printk("Now key interrput occur %d times!!\n",count);
 return IRQ_HANDLED;
}
//之前这里的返回类型用了void,以至于在运行按键中断模块的时候,一直出现

//如下错误:
# insmod myirq.ko
Irq init_module success!!
Now key interrput occur 1 times!!
irq event 17: bogus return value 25
[<c002adac>] (dump_stack+0x0/0x14) from [<c0061220>] (__report_bad_irq+0x38/0x94)
[<c00611e8>] (__report_bad_irq+0x0/0x94) from [<c00612cc>] (note_interrupt+0x50/0x240)
 r4:c02e131c
[<c006127c>] (note_interrupt+0x0/0x240) from [<c006200c>] (handle_edge_irq+0x120/0x144)
[<c0061eec>] (handle_edge_irq+0x0/0x144) from [<c0026048>] (asm_do_IRQ+0x48/0x60)
 r6:c0313350 r5:c02e131c r4:00000011
[<c0026000>] (asm_do_IRQ+0x0/0x60) from [<c0026a64>] (__irq_svc+0x24/0xa0)
Exception stack(0xc39cde2c to 0xc39cde74)
de20:                            00000000 f0000008 00000001 00000000 c02e131c
de40: 40000013 00000011 c3e326e0 00000000 c3df9198 00000000 c39cde94 c39cde50
de60: c39cde74 c0061ab0 c0060fb0 a0000013 ffffffff                           
 r7:c3e326e0 r6:00000002 r5:f0000000 r4:ffffffff
[<c0060e28>] (setup_irq+0x0/0x1cc) from [<c00611cc>] (request_irq+0xb4/0xd0)
 r8:bf000134 r7:00000020 r6:bf000040 r5:00000011 r4:c3e326e0
[<c0061118>] (request_irq+0x0/0xd0) from [<bf00205c>] (irq_init+0x5c/0x78 [myirq])
[<bf002000>] (irq_init+0x0/0x78 [myirq]) from [<c005e2b8>] (sys_init_module+0x1404/0x149c)
 r4:bf0006a0
[<c005ceb4>] (sys_init_module+0x0/0x149c) from [<c0026e60>] (ret_fast_syscall+0x0/0x2c)
handlers:
[<bf000040>] (irq_interrupt+0x0/0x34 [myirq])
/ #
当中断服务函数返回类型改为 irqreturn_t时,在运行模块就一切KO了!如下:

# Now key interrput occur 1 times!!
Now key interrput occur 2 times!!
Now key interrput occur 3 times!!
Now key interrput occur 4 times!!
Now key interrput occur 5 times!!
Now key interrput occur 6 times!!
Now key interrput occur 7 times!!
Now key interrput occur 8 times!!
Now key interrput occur 9 times!!
Now key interrput occur 10 times!!



//文件操作结构的填充
struct file_operations irq_fops=
{
  .open    = irq_open,
  .release = irq_close,
  .owner   = THIS_MODULE,
};


//init.exit等函数
static int __init irq_init(void)
{
 int ret;
 
 ret = register_chrdev(device_major,device_name,&irq_fops);  //注册设备
 if(ret<0)
  
  printk("Irq init_module failed ...\n");
  return ret;
  }
 else
  printk("Irq init_module success!!\n");

 ret = request_irq(irq,&irq_interrupt,IRQF_TRIGGER_FALLING,"IRQ_TEST",NULL);  //申请中断
 
 return ret;
}

static void __exit clean_irq(void)
{
 unregister_chrdev(device_major,device_name);  //注销设备
 free_irq(irq,NULL);                           //释放中断
 printk("Exit irq module...\n");

}

module_init(irq_init);
module_exit(clean_irq);

MODULE_LICENSE("GPL");   //这个最好是加上,不然在运行模块的时候会出现内核污染的信息哦……
MODULE_AUTHOR("ALV");