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.
Wie wärs mit einem Lese-Thread, der die Daten blockweise liest und in einem FIFO speichert?
Martin W. schrieb: > Wie macht man das am geschicktesten? du kannst mit select warten bis daten kommen wenn du eine hauptschleife hast die ständig durlaufen wird. Oder die startest einen Thread und man einfach ein blockierendes Read.
select oder poll, google mal danach. Das ist an sich schon so bewährt, dass du da praktisch nur noch abschreiben musst.
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.
> 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.
Wie jiffies oben schon sagte ist select() da der Weg zum Glück. Schau mal da http://www.zotteljedi.de/socket-tipps/index.html da ist das recht gut erklärt. Falls Du nicht klar kommst melde dich noch mal dann kram ich meinen alten Code mal raus, hab das vor jahren mal gemacht.
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.