Datenverlust beim Lesen von serieller USB-Schnittstelle



  • Hi,

    ich habe ein sehr dubioses Problem beim Lesen von Daten von einer seriellen Schnittstelle. Die Gegenstelle ist ein kleines Embedded-Gerät, welches per USB-CDC angebunden ist. Unter Windows taucht das Gerät als COMx auf und lesen/schreiben von Daten ist kein Problem.

    Unter Linux (verschiedene Distris probiert), taucht das Gerät als /dev/ttyACMx auf und sich sehe beim Lesen von diesem Gerät immer mal den Verlust von ein, zwei Bytes an Daten. Beim Senden scheint das nicht zu passieren.

    Man kann mit dem Gerät auch per TCP/IP kommunizieren. Hier kommt das geiche Protokoll zum Einsatz und auf clientseite der gleiche Code. Da hier (wie unter Windows) ebenfalls kein Problem auftritt, würde ich einen Fehler in meiner Implementierung ausschließen.

    Ich habe bisher noch keinerlei Regel erkennen können, wie/wann/wo der Verlust der Daten passiert, deswegen ist mir jeder Hinweis, jede Spekulation und jede Idee willkommen!

    Der Code zum Öffnen der seriellen Schnittstelle sieht übrigens so aus:

    struct termios       options;
    struct serial_struct sStruct;
    
    *fd= open(serialParams->port, O_RDWR|O_NOCTTY);// | O_NDELAY);
    if (*fd == -1) return ERROR_DEVICE;
    fcntl(*fd, F_SETFL,FNDELAY);
    
    tcgetattr(*fd, &options);
    
    //Enable the receiver and set local mode
    options.c_cflag |= (CLOCAL | CREAD);
    
    options.c_cflag &= ~CSIZE; // Mask the character size bits
    options.c_cflag |= CS8;
    
    options.c_cflag &= ~(PARENB|PARODD);
    
    options.c_cflag&=~CSTOPB;
    
    options.c_lflag=0;
    options.c_iflag=0;
    options.c_oflag=0;
    
    options.c_iflag |= (IXON | IXOFF | IXANY);
    options.c_cflag &= ~CRTSCTS;
    
    ioctl(*fd, TIOCGSERIAL, &sStruct);
    sStruct.flags &= ~ASYNC_SPD_MASK;
    ioctl(*fd, TIOCSSERIAL, &sStruct);
    
    speed=1000000;
    
    ioctl(*fd, TIOCGSERIAL, &sStruct);
    sStruct.flags = (sStruct.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
    sStruct.custom_divisor = (sStruct.baud_base + (speed / 2)) / speed;
    ioctl(*fd, TIOCSSERIAL, &sStruct);
    
    cfsetispeed(&options, B38400);
    cfsetospeed(&options, B38400);
    
    if (tcsetattr(*fd, TCSANOW, &options)!=0) return ERROR_DEVICE;
    

  • Mod

    Hi,

    wie du merkst, gibt es auf deinen Beitrag bisher keine Antworten. Ich denke, dies liegt daran, dass dein Problem recht schwer nachvollziehbar ist, nur mit den Informationen, die du uns hier gegeben hast. Was genau tust du? Wie genau stellst du fest, dass etwas fehlt? Am besten für uns wäre ein ausführbares Minimalbeispiel, das den Fehler demonstriert, mit genauer Angabe, was du tust, was passiert, und was du eigentlich erwartet hättest.
    Wie man Probleme nachstellbar und nachvollziehbar macht
    Da wir natürlich nicht das Gerät zur Verfügung haben, mit dem du kommunizierst, wäre es gut, wenn du diesen Teil irgendwie abstrahieren könntest. Oder du wenigstens diesen Teil so genau beschreiben kannst, dass wir nachvollziehen können, was da passiert.



  • Nein, das liegt wohl am Mangel an Linux-Know-How in diesem Forum. Wie ich inzwischen herausgefunden habe, gibt es tatsächlich einen Bug im CDC-Treiber, der dieses Verhalten verursachen kann.



  • Zonk79 schrieb:

    Nein, das liegt wohl am Mangel an Linux-Know-How in diesem Forum. Wie ich inzwischen herausgefunden habe, gibt es tatsächlich einen Bug im CDC-Treiber, der dieses Verhalten verursachen kann.

    Hast du einer Lösung gefunden, oder ist der Bug im Treiber mittlerweile behoben?


Anmelden zum Antworten