求助 linux按键驱动程序调试,请各位大侠指点一下
#include <linux/sched.h>#include <linux/init.h>
#include <asm/hardware.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/time.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <linux/ioctl.h>
#include <asm/ioctl.h>
#include <linux/cdev.h>
#include <asm-arm/arch-s3c2410/regs-gpio.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <linux/device.h>
#define BUTTON_IRQ1 IRQ_EINT8
#define BUTTON_IRQ2 IRQ_EINT9
#define BUTTON_IRQ3 IRQ_EINT10
#define BUTTON_IRQ4 IRQ_EINT11
#define BUTTON_IRQ5 IRQ_EINT13
#define DEVICE_NAME "button"
static int buttonMajor=0;
static int button_minor=0;
#define BUTTONMINOR 0
#define MAX_BUTTON_BUF16
#define BUTTONSTATUS_1 8
#define BUTTONSTATUS_2 9
#define BUTTONSTATUS_3 10
#define BUTTONSTATUS_4 11
#define BUTTONSTATUS_5 13
static unsigned char buttonRead(void);
static int flag=0;
typedef struct {
// struct cdev *cdev;
unsigned int buttonStatus; //....
unsigned char buf; //.....
unsigned int head,tail; //........
wait_queue_head_t wq; //....
} BUTTON_DEV;
static BUTTON_DEV buttondev;
#define BUF_HEAD (buttondev.buf) //....
#define BUF_TAIL (buttondev.buf) //....
#define INCBUF(x,mod) ((++(x)) & ((mod)-1)) //.......
static void (*buttonEvent)(void);
static void buttonEvent_dummy(void) {}
static void buttonEvent_1(void)
{
if(buttondev.buttonStatus==BUTTONSTATUS_5) {
BUF_HEAD=BUTTONSTATUS_5;
}
if(buttondev.buttonStatus==BUTTONSTATUS_4) {
BUF_HEAD=BUTTONSTATUS_4;
}
if(buttondev.buttonStatus==BUTTONSTATUS_3) {
BUF_HEAD=BUTTONSTATUS_3;
}
if(buttondev.buttonStatus==BUTTONSTATUS_2) {
BUF_HEAD=BUTTONSTATUS_2;
}
if(buttondev.buttonStatus==BUTTONSTATUS_1) {
BUF_HEAD=BUTTONSTATUS_1;
}
buttondev.head=INCBUF(buttondev.head,MAX_BUTTON_BUF);
flag=1;
wake_up_interruptible(&(buttondev.wq));
}
static irqreturn_t isr_button(int irq,void *dev_id,struct pt_regs *regs)
{
switch (irq) {
case BUTTON_IRQ1:buttondev.buttonStatus=BUTTONSTATUS_1;
break;
case BUTTON_IRQ2:buttondev.buttonStatus=BUTTONSTATUS_2;
break;
case BUTTON_IRQ3:buttondev.buttonStatus=BUTTONSTATUS_3;
break;
case BUTTON_IRQ4:buttondev.buttonStatus=BUTTONSTATUS_4;
break;
case BUTTON_IRQ5:buttondev.buttonStatus=BUTTONSTATUS_5;
break;
default:break;
}
buttonEvent();
return 0;
}
static int button_open(struct inode *inode,struct file *filp)
{
int ret;
buttondev.head=buttondev.tail=0;
buttonEvent=buttonEvent_1;
ret=request_irq(BUTTON_IRQ1,isr_button,IRQF_DISABLED,DEVICE_NAME,NULL);
if(ret) {
printk("BUTTON_IRQ1: could not register interrupt\n");
return ret;
}
ret=request_irq(BUTTON_IRQ2,isr_button,IRQF_DISABLED,DEVICE_NAME,NULL);
if(ret) {
printk("BUTTON_IRQ2: could not register interrupt\n");
return ret;
}
ret=request_irq(BUTTON_IRQ3,isr_button,IRQF_DISABLED,DEVICE_NAME,NULL);
if(ret) {
printk("BUTTON_IRQ3: could not register interrupt\n");
return ret;
}
ret=request_irq(BUTTON_IRQ4,isr_button,IRQF_DISABLED,DEVICE_NAME,NULL);
if(ret) {
printk("BUTTON_IRQ4: could not register interrupt\n");
return ret;
}
ret=request_irq(BUTTON_IRQ5,isr_button,IRQF_DISABLED,DEVICE_NAME,NULL);
if(ret) {
printk("BUTTON_IRQ5: could not register interrupt\n");
return ret;
}
return 0;
}
static int button_release(struct inode *inode,struct file *filp)
{
buttonEvent=buttonEvent_dummy;
free_irq(BUTTON_IRQ1,NULL);
free_irq(BUTTON_IRQ2,NULL);
free_irq(BUTTON_IRQ3,NULL);
free_irq(BUTTON_IRQ4,NULL);
free_irq(BUTTON_IRQ5,NULL);
return 0;
}
static ssize_t button_read(struct file *filp,char __user*buffer,size_t count,loff_t *ppos)
{
int button_ret=0;
retry:
if(buttondev.head!=buttondev.tail) {
button_ret=buttonRead();
copy_to_user(buffer,&button_ret,sizeof(int));
return sizeof(int);
}
else {
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN;
wait_event_interruptible(buttondev.wq,flag);
flag=0;
if(signal_pending(current))
{
printk("rturn -ERESTARTSYS\n");
return -ERESTARTSYS;
}
goto retry;
}
return sizeof(int);
}
static struct file_operations button_fops= {
.owner= THIS_MODULE,
.open = button_open,
.read = button_read,
.release = button_release,
};
structcdev *button_dev;
structclass *button_class;
static int __init s3c2410_button_init(void)
{
int ret,err;
dev_t dev,devno;
s3c2410_gpio_pullup(S3C2410_GPG0,1);
s3c2410_gpio_pullup(S3C2410_GPG1,1);
s3c2410_gpio_pullup(S3C2410_GPG2, 1);
s3c2410_gpio_pullup(S3C2410_GPG3,1);
s3c2410_gpio_pullup(S3C2410_GPG5,1);
s3c2410_gpio_cfgpin(S3C2410_GPG0, S3C2410_GPG0_EINT8);
s3c2410_gpio_cfgpin(S3C2410_GPG1, S3C2410_GPG1_EINT9);
s3c2410_gpio_cfgpin(S3C2410_GPG2, S3C2410_GPG2_EINT10);
s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_EINT11);
s3c2410_gpio_cfgpin(S3C2410_GPG5, S3C2410_GPG5_EINT13);
set_irq_type(BUTTON_IRQ1,IRQT_FALLING);
set_irq_type(BUTTON_IRQ2,IRQT_FALLING);
set_irq_type(BUTTON_IRQ3,IRQT_FALLING);
set_irq_type(BUTTON_IRQ4,IRQT_FALLING);
set_irq_type(BUTTON_IRQ5,IRQT_FALLING);
buttonEvent=buttonEvent_dummy;
if(buttonMajor){
dev = MKDEV(buttonMajor,button_minor);
ret = register_chrdev_region(dev,1,"button");
}else{
ret = alloc_chrdev_region(&dev,buttonMajor,1,"button");
buttonMajor=MAJOR(dev);
}
if(ret < 0){
printk(KERN_WARNING"button:can't get mjor %d\n",buttonMajor);
return ret;
}
devno = MKDEV(buttonMajor,0);
button_dev=cdev_alloc();
cdev_init(button_dev,&button_fops);
button_dev->owner=THIS_MODULE;
button_dev->ops=&button_fops;
err=cdev_add(button_dev,devno,1);
if(err){
printk("Error %d adding button",err);
//return -1;
}
button_class=class_create(THIS_MODULE,"button_class");
if(IS_ERR(button_class)){
printk("Err: failed in creating class.\n");
return-1;
}
device_create(button_class, NULL, MKDEV(buttonMajor,button_minor), DEVICE_NAME "%d",button_minor);
buttonMajor=ret;
buttondev.head=buttondev.tail=0;
//buttondev.buttonStatus=0;
buttondev.buttonStatus=BUTTONSTATUS_1;
init_waitqueue_head(&(buttondev.wq));
return 0;
}
static unsigned char buttonRead(void)
{
unsigned long flags;
unsigned char button_ret;
local_irq_save(flags);
button_ret=BUF_TAIL;
buttondev.tail=INCBUF(buttondev.tail,MAX_BUTTON_BUF);
local_irq_restore(flags);
return button_ret;
}
static void __exit s3c2410_button_eixt(void)
{
cdev_del(button_dev);
device_destroy(button_class, MKDEV(buttonMajor,button_minor));
class_destroy(button_class);
unregister_chrdev_region(MKDEV (buttonMajor,button_minor), button_dev);
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("llg");
module_init(s3c2410_button_init);
module_exit(s3c2410_button_eixt);
在测试中没有按按键时,驱动程序不停地中断,怎么回事?
没有
页:
[1]