Serielle Schnittstelle unter Linux, nicht blockierend lesen?

Gast #2479279
Lesenswert?

Hallo,

ich programmiere meistens den USART auf einem AVR und finde das 
Interrupt-Konzept sehr schön, weil man in der Routine die Daten mit 
einer State-Machine sammeln kann und immer genau weiß, wann ein 
Datensatz komplett da ist.

Ich möchte jetzt auf einem Embedded System unter Linux Daten in einem 
bestimmten Format auslesen, die von einem AVR über die serielle 
Schnittstelle hereinkommen. Interrupt-gesteuert geht ja leider nicht, 
also muss ich wohl in der Hauptschleife die Daten einsammeln.

Ich habe jetzt mal probiert, das Verhalten unter dem AVR nachzubilden, 
indem ich die Schnittstelle mit O_NONBLOCK öffne und den Aufruf von read 
auf jeweils ein Byte begrenze. Das ist aber total langsam.

Mit einem Testprogramm habe ich herausgefunden, dass die Daten da 
blockweise einlaufen, mit größeren Pausen dazwischen. Wobei die Länge 
der Blocks um einen Mittelwert herumschwankt, aber immer mal größer und 
mal kleiner ist. Manchmal kommt auch tatsächlich nur ein Byte.

Wie macht man das am geschicktesten? Den Artikel serielle Schnittstelle 
habe ich natürlich gelesen aber leider nichts gefunden, was mir da 
weiterhelfen würde. Wäre nett, wenn jemand mit einem Beispiel aushelfen 
könnte.
#2479390
Lesenswert?

Martin W. schrieb:
> Ich habe jetzt mal probiert, das Verhalten unter dem AVR nachzubilden,
> indem ich die Schnittstelle mit O_NONBLOCK öffne und den Aufruf von read
> auf jeweils ein Byte begrenze. Das ist aber total langsam.

mit einem non blocking file descriptor kann man auch zügig arbeiten; 
wenn es langsam ist dann aus anderen Gründen.

Du hast in so einem Fall immer folgende Möglichkeiten (schon genannt, 
aber mal als Übersicht):

- für jeden zu lesenden fd einen Thread
- select (wenn man den timeout-Wert entsprechend klein setzt,
  kann man nebenbei etwas sinnvolles tun)
- non blocking fd
- asynchrones Lesen

Nur im ersten Fall nutzt du nebenbei mehrere Prozessoren.
#2479417
Lesenswert?

> Mit einem Testprogramm habe ich herausgefunden, dass die Daten da
> blockweise einlaufen, mit größeren Pausen dazwischen. Wobei die Länge
> der Blocks um einen Mittelwert herumschwankt, aber immer mal größer
> und mal kleiner ist.

Das Verhalten kommt übrigens vom FIFO der PC-UART (16550&Co). Damit das 
FIFO tatsächlich gegen unnötige Interruptlast hilft, aber auch nicht 
ewig verzögert, wenn es noch nicht ganz voll ist, gibt es eine Wartezeit 
bis zur Interruptauslösung. Ist der FIFO-Stand unterhalb einer gewissen 
Marke und kommt währenddessen ein neues Zeichen rein, wird mit dem IRQ 
noch gewartet.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren