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:
1 | struct termios options;
|
2 | struct serial_struct sStruct;
|
3 |
|
4 | *fd= open(serialParams->port, O_RDWR|O_NOCTTY);// | O_NDELAY);
|
5 | if (*fd == -1) return ERROR_DEVICE;
|
6 | fcntl(*fd, F_SETFL,FNDELAY);
|
7 |
|
8 | tcgetattr(*fd, &options);
|
9 |
|
10 | //Enable the receiver and set local mode
|
11 | options.c_cflag |= (CLOCAL | CREAD);
|
12 |
|
13 | options.c_cflag &= ~CSIZE; // Mask the character size bits
|
14 | options.c_cflag |= CS8;
|
15 |
|
16 | options.c_cflag &= ~(PARENB|PARODD);
|
17 |
|
18 | options.c_cflag&=~CSTOPB;
|
19 |
|
20 | options.c_lflag=0;
|
21 | options.c_iflag=0;
|
22 | options.c_oflag=0;
|
23 |
|
24 | options.c_iflag |= (IXON | IXOFF | IXANY);
|
25 | options.c_cflag &= ~CRTSCTS;
|
26 |
|
27 | ioctl(*fd, TIOCGSERIAL, &sStruct);
|
28 | sStruct.flags &= ~ASYNC_SPD_MASK;
|
29 | ioctl(*fd, TIOCSSERIAL, &sStruct);
|
30 |
|
31 | speed=1000000;
|
32 |
|
33 | ioctl(*fd, TIOCGSERIAL, &sStruct);
|
34 | sStruct.flags = (sStruct.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
|
35 | sStruct.custom_divisor = (sStruct.baud_base + (speed / 2)) / speed;
|
36 | ioctl(*fd, TIOCSSERIAL, &sStruct);
|
37 |
|
38 | cfsetispeed(&options, B38400);
|
39 | cfsetospeed(&options, B38400);
|
40 |
|
41 | if (tcsetattr(*fd, TCSANOW, &options)!=0) return ERROR_DEVICE;
|