C IRQ Storm vom Parallel Port

Freezedevil

Lieutenant
Registriert
Mai 2011
Beiträge
648
Hi,

ich habe eine Parallel Port Express Card an meinem Rechner hängen und versuche nun auf Interrupts an diesem Port zu reagieren. Das System ist Ubuntu 64bit, Kernel 2.6.35-18.
Aktuell sieht mein Code so aus

Code:
/*
 * Code taken from with minor changes:
 * http://www.xenoscope.com/weblog/2008/09/16/how-to-monitor-parallel-port-interrupts-in-user-space-in-linux/
 * 
 * Example code from:
 * http://people.redhat.com/twaugh/parport/html/x916.html
 */
#include <linux/ppdev.h>
#include <linux/parport.h>
#include <stropts.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/select.h>
 
#define PP_DEV_NAME "/dev/parport0"
 
int main()
{
    //Get a file descriptor for the parallel port
    int ppfd;
 
    ppfd = open(PP_DEV_NAME, O_RDWR);
    if(ppfd == -1)
    {
        printf("Unable to open parallel port!\n");
        return 1;
    }
 
    //Have to claim the device
    if(ioctl(ppfd, PPCLAIM))
    {
        printf("Couldn't claim parallel port!\n");
        close(ppfd);
        return 1;
    }
 
    while(1)
    {
        //Set up the control lines for when an interrupt happens
        int int_count;
        int busy = PARPORT_STATUS_ACK | PARPORT_STATUS_ERROR;
        int acking = PARPORT_STATUS_ERROR;
        int ready = PARPORT_STATUS_BUSY | PARPORT_STATUS_ACK | PARPORT_STATUS_ERROR;
        char int_value;
 
        ioctl(ppfd, PPWCTLONIRQ, &busy);
 
        //Let ppdev know we're ready for interrupts
        ioctl(ppfd, PPWCONTROL, &ready);
 
        //Wait for an interrupt
        fd_set rfds;
        FD_ZERO(&rfds);
        FD_SET(ppfd, &rfds);
        if(select(ppfd + 1, &rfds, NULL, NULL, NULL))
        {
            printf("Received interrupt\n");
        }
        else
            continue; //Caught a signal
 
        //Fetch the associated data
        ioctl(ppfd, PPRDATA, &int_value);
 
        //Clear the interrupt
        ioctl(ppfd, PPCLRIRQ, &int_count);
        if(int_count > 1)
            printf("Uh oh, missed %i interrupts!\n", int_count - 1);
 
        //Acknowledge the interrupt
        ioctl(ppfd, PPWCONTROL, &acking);
        usleep(2);
        ioctl(ppfd, PPWCONTROL, &busy);
    }
 
    return 0;
}

An einem Onboard Parallel Port funktioniert das ganze auch ohne Probleme. Mit meiner Express Card habe ich jedoch, wie der Titel schon sagt, das Problem, dass ich nach einem Interrupt unendlich viele weitere bekomme. Ich kann die Interrupts nur stoppen, indem ich die entsprechenden Module entferne (rmmod) und anschließen neu lade (modprobe). Ich hab schon versucht am Treiber zu werkeln, was bisher jedoch leider nicht von Erfolg gekrönt war.

Die Interrupts löse ich momentan manuell aus indem ich Pin 10 kurzschließe.

Wenn jemand eine Idee hat was ich tun kann um nur einen sauberen Interrupt zu bekommen, dann wäre ich sehr dankbar.
 
Kann es sein, dass du beim select irgendetwas übersiehst? Dann würde das select eine Endlosschleife bauen. Einfach mal einen Debugger anwerfen und schauen wo das herkommt :)
 
Die Interrupts werden nicht richtig entfernt, nachdem sie abgearbeitet sind. Das sollte eigentlich dieser Code tun:

Code:
//Clear the interrupt
        ioctl(ppfd, PPCLRIRQ, &int_count);
        if(int_count > 1)
            printf("Uh oh, missed %i interrupts!\n", int_count - 1);

und wie gesagt tut er das bei onboard Ports auch. Wenn man sich /proc/interrupts ansieht, ist festzustellen, dass der Counter in die Höhe schießt und meine Anwendung (die im User Space läuft) so natürlich denkt es wäre ein neuer Interrupt. Oder was meistest du mit "wo das her kommt"?
Ich vermute deshalb, dass das Problem eher im Treiber bzw. in der Hardware selbst liegt.

Danke schonmal, dass sich hier überhaupt jemand mit dem Problem beschäftigt.
 
Zurück
Oben