Hi, ich muss die Steuerleitungen der seriellen Schnittstelle recht zeitkritisch abfragen. Da ich das nicht unbedingt per Polling machen will, die Frage: Gibt es für C unter Linux da eine Interrupt-gesteuerte Möglichkeit? LG traffic
Die gibt's im normalen Posix-Modell nur für die DCD-Leitung: im „normalen“ Modembetrieb bekommst du ein SIGHUP (“hangup”), wenn DCD verschwindet. Allerdings muss der zugrhörige Prozess zuvor der process group leader für das entsprechende Terminal geworden sein (via setpgid() und tcsetpgrp()).
:
Bearbeitet durch Moderator
Ich gehe mal davon aus, dass du das auslesen per TTY Syscalls (ioctl) machst. Da gibt es den TIOCMIWAI-Syscall. Siehe die Doku: http://man7.org/linux/man-pages/man4/tty_ioctl.4.html
1 | TIOCMIWAIT int arg |
2 | Wait for any of the 4 modem bits (DCD, RI, DSR, CTS) to |
3 | change. The bits of interest are specified as a bit mask in |
4 | arg, by ORing together any of the bit values, TIOCM_RNG, |
5 | TIOCM_DSR, TIOCM_CD, and TIOCM_CTS. The caller should use |
6 | TIOCGICOUNT to see which bit has changed. |
Logischerweise musst du dann diesen Syscall in einen Child-Prozess auslagern, wenn du nicht willst, dass dein Programm blockiert... Siehe z.B. hier für ein Beispielprogramm: http://linux.mathematik.tu-darmstadt.de/pub/linux/oldstuff/people/bonnes/waitcomm/serial_test.c
:
Bearbeitet durch User
H. K. schrieb: > Logischerweise musst du dann diesen Syscall in einen Child-Prozess > auslagern, wenn du nicht willst, dass dein Programm blockiert... Linux kann doch mittlerweile auch Threads.
Peter II schrieb: > Linux kann doch mittlerweile auch Threads. Stimmt. Habe ich vergessen zu erwähnen!
traffic schrieb: > ich muss die Steuerleitungen der seriellen Schnittstelle recht > zeitkritisch abfragen. Wie kritisch ist denn die Zeit? Linux ist, wie alle andere Desktop und Server OS-en, nicht gerade ausgelegt für zeitkritische (Real-time) Anforderungen.
Danke für die Antworten. Leider bin ich irgendwie zu blöd, folgender Test-Code kommt bei mir nur bis zur Ausgabe "TEST":
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <termios.h> |
4 | #include <sys/ioctl.h> |
5 | #include <sys/types.h> |
6 | #include <sys/stat.h> |
7 | #include <fcntl.h> |
8 | #include <unistd.h> |
9 | #include <string.h> |
10 | |
11 | int main() |
12 | {
|
13 | int fd; |
14 | struct termios options; |
15 | fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY); |
16 | if(fd == 0) |
17 | {
|
18 | printf("Fehler: Device kann nicht geöffnet werden.\n"); |
19 | return 1; |
20 | }
|
21 | |
22 | memset(&options,0,sizeof (struct termios)); |
23 | cfmakeraw(&options); |
24 | cfsetispeed(&options,B9600); |
25 | cfsetospeed(&options,B9600); |
26 | tcsetattr(fd,TCSANOW,&options); |
27 | tcflush(fd,TCIOFLUSH); |
28 | |
29 | int i; |
30 | printf("TEST\n"); |
31 | i = ioctl(fd,TIOCMIWAIT,0); |
32 | if( i < 0 ) |
33 | {
|
34 | printf("clear failed (%d)\n",i); |
35 | return 1; |
36 | }
|
37 | else
|
38 | printf("PASS\n"); |
39 | i = ioctl(fd, TIOCMIWAIT, TIOCM_DSR); |
40 | printf("A=%d", i); |
41 | |
42 | close(fd); |
43 | return 0; |
44 | }
|
LG traffic
traffic schrieb: > ioctl(fd,TIOCMIWAIT,0); Nun, wenn du auf nichts wartest (0), dann ist das wohl wenig sinnvoll. Die Funktion kann daraus zwei Entscheidungen treffen: sofort zurückkehren („nichts“ ist ja bereits eingetreten), oder unendlich warten („nichts“ kann nie eintreten). Offenbar tut sie letzteres.
Naja, dem verlinkten Beispiel nach müsste es gehen:
1 | /* clear the wait flags */
|
2 | r = ioctl(fd,TIOCMIWAIT,0); |
3 | if( r < 0 ) |
4 | {
|
5 | fprintf(stderr,"clear failed (%d)\n",r); |
6 | return 1; |
7 | }
|
traffic schrieb: > zeitkritisch traffic schrieb: > "/dev/ttyUSB0" Bist du dir mit den zeitkritisch sicher? So recht passt das nicht zusammen. Wie viel Zeit kannst du dir denn gönnen?
nicht“Gast“ schrieb: > So recht passt das nicht zusammen. Die Zeiten, die für die Meldung über den USB benötigt werden, dürften im Bereich 10 ms liegen (hängt natürlich vom konkreten Device ab, das er uns nicht genannt hat). So schnell muss man es erstmal auf der Ebene des Programms schaffen in einem nicht-realtime-OS.
:
Bearbeitet durch Moderator
Die Zeit zum Erkennen einer Pegeländerung beträgt 30-40 ms. USB ist hier nur zum Test drin.
Wenn eine Handshake Funktion zeitkritisch ist, sollte sie bereits im Treiber implementiert sein, und nicht im Benutzerprogramm. Db das Buffer Full, im RTS/CTS. Sonst kann man im UART Fall von einem PC wenig erwarten. Versuch mal eine zunehmend laengere Blochnachricht zu uebertragen. Die kommt dann ploetzlich in einzelne Bloecke zerhackt. Mit einem eigenen Timing. Ich hab die Details dazu leider vergessen. Und der USB treiber macht auch noch seine Spielchen. Fazit. Man sollte von einem PC keine Echtzeitleistungen erwarten.
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.