主题 : 在pc自行寫一個中斷的driver for lpt ,執行時發生錯誤!! 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 6392
精华: 0
发帖: 45
金钱: 395 两
威望: 351 点
综合积分: 90 分
注册时间: 2009-05-31
最后登录: 2015-12-18
楼主  发表于: 2009-06-23 23:38

 在pc自行寫一個中斷的driver for lpt ,執行時發生錯誤!!

在pc自行寫一個中斷的driver for lpt ,執行時發生錯誤!!
以下是dmesg 的訊息, 請問我要如何除錯??
謝謝

IRQ handler type mismatch for IRQ 7
[<c044d9fd>] setup_irq+0x168/0x17c
[<e0a590b6>] int_interrupt+0x0/0x30 [int_dev]
[<c044da8d>] request_irq+0x7c/0x98
[<e0a59101>] int_open+0x1b/0x3c [int_dev]
[<c0477536>] chrdev_open+0x117/0x132
[<c047741f>] chrdev_open+0x0/0x132
[<c046e787>] __dentry_open+0xc7/0x1ab
[<c046e8cf>] nameidata_to_filp+0x19/0x28
[<c046e909>] do_filp_open+0x2b/0x31
[<c0470b72>] __fput+0x13f/0x167
[<c046e94d>] do_sys_open+0x3e/0xae
[<c046e9ea>] sys_open+0x16/0x18
[<c0404eff>] syscall_call+0x7/0xb
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
1楼  发表于: 2009-06-24 13:27
你可以:
1. 自己从内核源代码里找"IRQ handler type mismatch for IRQ 7"是什么意思;
或者
2. 把驱动源代码和所用的内核版本以及lpt硬件信息贴出来,让论坛上的兄弟们讨论
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 6392
精华: 0
发帖: 45
金钱: 395 两
威望: 351 点
综合积分: 90 分
注册时间: 2009-05-31
最后登录: 2015-12-18
2楼  发表于: 2009-06-24 21:25
驱动源代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/interrupt.h>

#define INT_DEV_NAME "intdev"
#define INT_DEV_MAJOR 240

#define INT_WRITE_ADDR 0x0378
#define INT_READ_ADDR 0x0379
#define INT_CTRL_ADDR 0x037A

#define PRINT_IRQ 7
#define PRINT_IRQ_ENABLE_MASK 0x10

#define INT_BUFF_MAX 64

typedef struct
{
unsigned long time;
} __attribute__((packed)) R_INT_INFO;

R_INT_INFO intbuffer[INT_BUFF_MAX];
int intcount = 0;

void int_clear(void)
{
int lp;

for(lp = 0; lp < INT_BUFF_MAX; lp++)
{
intbuffer[lp].time = 0;
}

intcount = 0;
}

irqreturn_t int_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
if(intcount < INT_BUFF_MAX)
{
intbuffer[intcount].time = get_jiffies_64( );
intcount++;
}
printk("int_init interrupt\n");
return IRQ_HANDLED;
}

int int_open (struct inode *inode, struct file *filp)
{
if(!request_irq(PRINT_IRQ , int_interrupt, SA_INTERRUPT, INT_DEV_NAME,
NULL))
printk("int_init open\n");
{
outb(PRINT_IRQ_ENABLE_MASK, INT_CTRL_ADDR);
}

int_clear( );

return 0;
}

ssize_t int_read(struct file *filp, char *buf, size_t count, loff_t
*f_pos)
{
int readcount;
char *ptrdata;
int loop;

readcount = count / sizeof(R_INT_INFO);
if(readcount > intcount) readcount = intcount;

ptrdata = (char *) &intbuffer[0];

for(loop = 0; loop < readcount * sizeof(R_INT_INFO); loop++)
{
put_user(ptrdata[loop], (char *) &buf[loop]);
}

return readcount * sizeof(R_INT_INFO);
}

ssize_t int_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
unsigned char status;
int loop;

int_clear( );

for(loop = 0; loop < count; loop++)
{
get_user(status, (char *) buf);
outb(status , INT_WRITE_ADDR);
}

return count;
}

int int_release (struct inode *inode, struct file *filp)
{
outb(0x00, INT_CTRL_ADDR);
free_irq(PRINT_IRQ , NULL);
printk("int_init release\n");
return 0;
}

struct file_operations int_fops =
{
.owner = THIS_MODULE,
.read = int_read,
.write = int_write,
.open = int_open,
.release = int_release,
};

int int_init(void)
{
int result;

result = register_chrdev(INT_DEV_MAJOR, INT_DEV_NAME, &int_fops);
if (result < 0) return result;
printk("int_init init\n");
return 0;
}

void int_exit(void)
{
unregister_chrdev(INT_DEV_MAJOR, INT_DEV_NAME);
printk("int_init exit\n");
}

module_init(int_init);
module_exit(int_exit);

MODULE_LICENSE("Dual BSD/GPL");

應用程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define DEVICE_FILENAME "/dev/intdev"

typedef struct
{
unsigned long time;
} __attribute__((packed)) R_INT_INFO;

#define INT_BUFF_MAX 64

int main( )
{
int dev;
R_INT_INFO intbuffer[INT_BUFF_MAX];
int intcount;
char buff[128];
int loop;
dev = open(DEVICE_FILENAME, O_RDWR | O_NDELAY);
if(dev >= 0)
{
printf("start...\n");
buff[0] = 0xFF;
write(dev,buff,1);
printf("wait... input\n");
while(1)
  {
   memset(intbuffer, 0, sizeof(intbuffer));
   intcount = read(dev,(char *) &intbuffer[0],sizeof(R_INT_INFO))/sizeof(R_INT_INFO) ;
   if(intcount) break;
  }

  printf("input ok...\n");
  sleep(1);
  memset(intbuffer, 0, sizeof(intbuffer));

  printf("read interrupt times\n");
  intcount = read(dev,(char *) intbuffer,sizeof(intbuffer)) / sizeof(R_INT_INFO) ;
  for(loop =0; loop < intcount; loop++)
  {
   printf("index = %d time = %ld\n", loop, intbuffer[loop].time);
   }

   printf("led flashing...\n");
   for(loop=0; loop<5; loop++)
   {
    buff[0] = 0xFF;
    write(dev,buff,1);
    sleep(1);
    buff[0] = 0x00;
    write(dev,buff,1);
    sleep(1);
    }
   close(dev);
  }

return 0;
}

内核版本
Linux version 2.6.18-53.el5 (mockbuild@builder6.centos.org) (gcc version 4.1.2 20070626 (Red Hat 4.1.2-14)) #1 SMP Mon Nov 12 02:22:48 EST 2007



[root@localhost chap12]# cat /proc/interrupts
           CPU0      
  0:   54553037    IO-APIC-edge  timer
  1:      19605    IO-APIC-edge  i8042
  6:          5    IO-APIC-edge  floppy
  7:          0    IO-APIC-edge  parport0
  8:          1    IO-APIC-edge  rtc
  9:          0   IO-APIC-level  acpi
12:      85275    IO-APIC-edge  i8042
15:     190577    IO-APIC-edge  ide1
169:      43736   IO-APIC-level  vmxnet ether
177:          0   IO-APIC-level  uhci_hcd:usb1, Ensoniq AudioPCI
185:          0   IO-APIC-level  ehci_hcd:usb2
193:      71539   IO-APIC-level  ioc0
NMI:          0
LOC:   54557867
ERR:          0
MIS:          0
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
3楼  发表于: 2009-06-24 22:33
在内核源代码kernel/irq/manage.c 里有
复制代码
  1. 250        if (old) {
  2. 251                /*
  3. 252                 * Can't share interrupts unless both agree to and are
  4. 253                 * the same type (level, edge, polarity). So both flag
  5. 254                 * fields must have IRQF_SHARED set and the bits which
  6. 255                 * set the trigger type must match.
  7. 256                 */
  8. 257                if (!((old->flags & new->flags) & IRQF_SHARED) ||
  9. 258                    ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK))
  10. 259                        goto mismatch;
  11. ...
  12. 324mismatch:
  13. 325        spin_unlock_irqrestore(&desc->lock, flags);
  14. 326        if (!(new->flags & IRQF_PROBE_SHARED)) {
  15. 327                printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
  16. 328                dump_stack();
  17. 329        }
  18. 330        return -EBUSY;

很明显,在你的驱动程序调用request_irq()之前,IRQ 7已经被别的驱动(parport0的驱动)申请了,而且申请时并没有指定IRQF_SHARED,因此无法满足驱动的再次申请。
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."