OS: Debian 5.0
Ich beobachte bei meinem Programm, das häufig eine Situation eintritt wo
ein einzelnes Zeichen, das mit write auf /dev/ttyS0 geschrieben wird,
nicht tatsächlich am Ausgang erscheint. Da auf dieses Zeichen (von einem
uC) eine Antwort erwartet wird, hängt mein Programm, bzw. läuft durch
die Retry-Schleife.
Ich meine nun, mal gehört zu haben das die Ausgabe nicht zwangsweise
sofort während write bzw. kurz danach erfolgt, sondern das sich das
Zeichen noch eine Weile im Output-Buffer aufhalten kann.
Habt Ihr das auch mal beobachtet?
Ich habe hier http://www.easysw.com/~mike/serial/serial.html#3_1_1
gelesen, das es einige ...FLUSH... attribute für die tcs Funktionen gibt
bzw. eine Posix Funktion namens tcflush.
Allerdings steht in der Beschreibung was von "discard", was ich als
"verwerfen" übersetzen würde. Irgendwie habe ich das im Zusammenhang mit
Dateien mal so gelernt das alle noch nicht geschriebenen Änderungen
geschrieben werden aber nicht verworfen. Ist da ein Unterschied zwischen
Dateien und den Devices?
Deute ich "discard" falsch oder muss ich mein serielles Device anders
öffnen?
Hier der Code:
1
intInitControllerSerialInterface(){
2
// fprintf (stderr, "Initialise serial interface to controller\n");
3
fdc=open(UC_INTERFACE,O_RDWR|O_NOCTTY|O_NDELAY);
4
5
if(fdc==-1)
6
{
7
perror("open_port: Unable to open /dev/ttyS0 - ");
8
return-1;
9
}
10
else{
11
fcntl(fdc,F_SETFL,FNDELAY);
12
13
structtermiosoptions;
14
15
tcgetattr(fdc,&options);// Get the current options for the port...
16
17
cfsetispeed(&options,B9600);// set baud rate
18
cfsetospeed(&options,B9600);
19
20
options.c_cflag|=(CLOCAL|CREAD);// Enable the receiver and set local mode...
21
/* 8N1 no parity */
22
options.c_cflag&=~PARENB;
23
options.c_cflag&=~CSTOPB;
24
options.c_cflag&=~CSIZE;
25
options.c_cflag|=CS8;
26
27
// options.c_cflag &= ~(CCTS_OFLOW | CRTS_IFLOW); // no hardware flow control
28
options.c_cflag&=~CRTSCTS;
29
options.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);// raw input
30
options.c_iflag&=~(IXON|IXOFF|IXANY|ICRNL);
31
options.c_oflag&=~OPOST;// raw output
32
tcsetattr(fdc,TCSANOW,&options);// Set the new options for the port
33
34
return0;
35
}
36
}
In diesem Zusammenhang beobachte ich auch, das die glib funktionen zum
logging ab und zu einfach hängen und nach einer Weile bzw. nach einigen
neutralen Manipulationen am Terminal wieder gehen.
Hat das auch schon jemand beobachtet? Irgendwelche Hinweise?
>ggf. tut es ein "fsync(fdc);" nach dem schreiben
Das ist wohl das was ich mal (vor Jahren) als flushen kennengelernt
habe. Laut Doku ist das: "fsync() transfers ("flushes") all modified
in-core data of (i.e., modified buffer cache pages for) the file
referred to by the file descriptor fd to the disk device (or other
permanent storage device) where that file resides. "
Also wohl nicht auf Zeichendevices anwendbar.
Hmm. Verwirrend. Manche sagen, das fsynch nur mit Dateien oder nur mit
Block devices geht. Manche empfehlen es auch für Character devices.
Ich kann es ja mal probieren. Aber eine dedizierte Funktion dafür wäre
mir natürlich lieber.
Fump schrieb:
> Hmm. Verwirrend. Manche sagen, das fsynch nur mit Dateien oder nur mit> Block devices geht. Manche empfehlen es auch für Character devices.> Ich kann es ja mal probieren. Aber eine dedizierte Funktion dafür wäre> mir natürlich lieber.
Dann schau mal nach tcdrain(), vielleicht hilft das ja weiter.
Dein Problem könnte auch damit zusammenhängen, dass Du einen USB zu
RS232 Konverter hast?!
@ Gerry
>Dann schau mal nach tcdrain(), vielleicht hilft das ja weiter.
Hmm. Könntest Du das bitte erläutern? Nach der Doku blockt das mein
Programm bis das Zeichen gesendet ist.
Wie ich nun sehe, habe ich versäumt zu schreiben, das ich ein Timeout
habe, das dann auch zuschlägt. D.h. das Zeichen ist nach 2 bis 5
Sekunden noch nicht draussen.
Ob ich also blocke bis das Zeichen draussen ist oder warte, ist doch vom
Programm aus gesehen, das selbe, oder?
Ich bin der Meinung, das das Problem ist, dass das Zeichen nicht
unmittelbar oder jedenfalls kurzfristig (weniger als 1s) rausgeht.
Hier auch nochmal der Hinweis, dass das nicht grundsätzlich so ist. Es
gibt Zeiten wo etwa eine Viertelstunde lang das Zeichen sofort rausgeht.
Dann wieder geht es einige Zeit lang nicht.
>Dein Problem könnte auch damit zusammenhängen, dass Du einen USB zu>RS232 Konverter hast?!
Nein. Ich benutze keinen USB-RS232-Konverter. Das Gerät hängt direkt an
einer RS232-Schnittstelle auf dem Motherboard.
tcdrain wartet, bis das letzte Zeichen gesendet wurde.
Anhand des Zeichenrahmens und der Baudrate kann man ausrechnen, wie
lange das mindestens dauert. Aber das hilft hier anscheinend nicht
weiter.
Das /dev/ttyS0 oben hatte ich überlesen, sorry.
Was ich mir denken könnte ist dass noch ein zweites Programm die
Schnittstelle geöffnet hat, zb ein getty. Mach mal ein "lsof | grep
ttyS0".
Wenn Du das ausschließen kannst käme noch "setserial" in Frage. Mal die
Einstellungen ausgeben lassen und mit den Settings im BIOS vergleichen.
Mehr fällt mir im Moment nicht ein, vielleicht hat ja sonst noch einer
ne Idee...
Läubi .. schrieb:
> Gerry E. schrieb:>> Mehr fällt mir im Moment nicht ein, vielleicht hat ja sonst noch einer>> ne Idee...> Hardware Handshake mit floatendem CTS/RTS?
Ja, auch möglich, obwohl: Fump (geiler Name) hat ja den Handshake
abgeschaltet.
options.c_cflag &= ~CRTSCTS;
Trotzdem kann es natürlich von Vorteil sein, unbenutzte Eingänge auf ein
festes Potential zu legen.
Gerry E. schrieb:
> options.c_cflag &= ~CRTSCTS;>> Trotzdem kann es natürlich von Vorteil sein, unbenutzte Eingänge auf ein> festes Potential zu legen.
Ja das steht im Quellcode... aber weiß das z.B. auch die Gegenstelle?
Und kriegt es auch der Treiber mit?
Ich hab (unter Windows) auch ab und an das Problem gehabt das er Zeichen
einfach nicht raussendet wenn ich nur einzelne Zeichen absende...
@ Gerry & Läubi
Das noch ein zweites Programm die serielle Schnittstelle öffnet kann ich
ausschliessen. Es könnte höchstens sein, dass ich das fragliche Programm
selbst ab und zu mal mit Ctrl-C abgebrochen habe, so das die
Schnittstelle an sich noch offen war als ich es noch einmal gestartet
habe. Allerdings habe ich trotzdem wieder Zeichen empfangen können. Das
wäre doch dann auch nicht gegangen, oder? Muss direkt mal probieren ob
open dann fehlschlägt.
setserial kann ich mal probieren. Im Bios steht aber doch nur die
I/O-Adresse und der Interrupt. setserial gibt ja wesentlich mehr aus.
Kannst Du bitte kurz erklären, was das bringen kann?
Tatsächlich sind auf PC-Seite die Handshake-Signale nirgendwo
angeschlossen. Habe aber auch noch nie gehört, das floatende
Handshake-Signale bei disabletem CTS/RTS Probleme machen. Selbst wenn,
habe ich ja keine +- 15V am RS232-Stecker um sie auf die
Handshake-Anschlüsse zu legen.? Kann ich ja mal probieren mit externem
Netzteil, aber seltsam irgendwie.
Die Gegenstelle kann die Handshakesignale nicht beeinflussen. Sie ist
nur mit Gnd, TX und RX verbunden und hat selbst keine Handshake-Signale.
Ist ein ATMega mit Max dran.
Du kannst einfach RTS und CTS am Stecker zusammenschalten.
Probier mal aus was passiert wenn du einfach fröhlich weitersendest
(z.B. immer 100 bytes) und dann auf Empfang gehst.
Hmm,
so wie ich das sehen (hab nett ales durchgelesen ;( ) existiert das
Problem noch
also bei mir (Debian-5.0.1 / 2.6.26-2-686) kommt alles sofort am Seriell
raus !
Mit Strg-C brech ich fast immer ab, und der Port bleibt frei !
Ich würde erstmal 'minicom -s' starten den Port einstellen,
und es darüber mal versuchen (zum Fehler ausschließen).
Achso, hast du den Ausgang mal per Oszi oder LED geprüft,
vielleicht liegt es ja an der AVR-Software der Gegenstelle !?!
Hmm, ......
DBD
Olli
PS: Mein init:
1
int fd;
2
if ((fd = open(mdevice, O_RDWR )) >= 0) {
3
4
tcgetattr(fd,&oldtio); /* save current port settings */
@ Läubi
>Du kannst einfach RTS und CTS am Stecker zusammenschalten.
Das kann ich mal probieren.
>Probier mal aus was passiert wenn du einfach fröhlich weitersendest>(z.B. immer 100 bytes) und dann auf Empfang gehst.
Was vielleicht aus meiner Beschreibung nicht klar hervorgeht:
Es ist so, das ich einmal das Programm starte und es funktioniert
klaglos. Einzelne Zeichen werden gesendet. Ich erhalte auch die
passenden Antworten. Das geht so einige Zeit lang, bis ich dann (aus
anderen Gründen, bin gerade dabei die SW im Zusammenhang mit einer
Anlage zu testen) anhalte.
Dann starte ich das Programm nochmal und es geht nicht. Ich probier hin
und her ohne was zu ändern und auf einmal geht es wieder. Ohne das ich
irgendwas an der SW oder HW geändert habe.
Man könnte vermuten, das das System gerade mit irgendwas ganz dringendem
beschäftigt ist und für so Kinkerlitzchen wie einzelne Zeichen keine
Zeit hat.
Ich weiss daher gerade nicht, was die 100 Zeichen bringen sollen. Kannst
Du das bitte erläutern?
Oliver schrieb:
...
> Achso, hast du den Ausgang mal per Oszi oder LED geprüft,> vielleicht liegt es ja an der AVR-Software der Gegenstelle !?!
Auch möglich, hast Recht!
Gerade wo ich obigen Beitrag von Fump sehe.
ZB ist es möglich, dass sich die Software des AVR aus dem Tritt bringen
lässt, wenn die PC-Seite "unterbrochen" wird...
Man kann übrigens solche Fehlersituationen sehr leicht dadurch
herbeiführen, indem man während der laufenden Kommunikation den
RS-232-Stecker zieht! Eine gute Software zeichnet sich dadurch aus, dass
dann eine Fehlermeldung kommt und nach dem Wiederanstöpseln die
Geschichte weiterläuft als wäre nichts gewesen...