Forum: PC-Programmierung Linux: serielle Schnittstelle - die drölfte (zeitgleiches lesen und schreiben)


von Kaj (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Forum,

ich bräuchte mal einen Denkanstoß und hoffe das Ihr mir helfen könnt :)

Details zur Umgebung:
- Board ist das UDOO( http://www.udoo.org )
- OS ist Archlinux
- Sprache C oder C++
- Baudrate ist 115k2

Für die, die das UDOO-Board nicht kennen:
Das UDOO ist ein Board mit zwei Controllern - 1x ein Freescale i.MX6
(4x 1GHz) und 1x Atmel SAM3X8E (selber Controller wie beim Arduino Due; 
Cortex-M3 84MHz). Auf der "PC"-Seite (also der i.MX6) kann ein Linux 
betrieben werden. Der i.MX6 und der Atmel-Controller sind direkt über 
UART verbunden.
Soweit erstmal nichts besonderes.

i.MX6 = PC
Atmel-µC = mC

Jetzt zu der Anwendung (siehe Bild):
Der mC bekommt vom PC einen "request": Dieser request kann eine Anfrage 
oder ein Befehl sein, auf die der mC antwortet (response).
mC-Seitig alles kein Problem, dank Interrupts. An dieser Stelle auch 
PC-Seitig noch keine wirkliche Herausforderung:
request senden und auf antwort warten.
Jetzt soll es PC-Seitig aber auch möglich sein einen response zu 
empfangen, ohne das ein request geschickt wurde. (ja ich weiß, diese 
formulierung führt die begriffe "response" und "request" irgendwie ad 
absurdum :) )

Ein request ist relativ kurz (<= 20 Zeichen), ein request kann aber auch 
schon mal mehr als 250 Zeichen lang sein.


Also:
Es soll möglich sein vom PC was zu senden und dann die Antwort zu 
empfangen. Es soll ebenso möglich sein, etwas zu empfangen, ohne das 
etwas gesendet wurde. Das Bedeutet (mehr oder minder) das ein 
"gleichzeitiges" lesen und schreiben möglich sein muss, denn es kann 
(und wird auch) passieren das gerade ein request gesendet wird, und 
gleichzeitig noch ein response empfang wird, für den es keinen request 
gab. Es geht hierbei nur um die PC-Seite(Linux)!

Jetzt mein Problem:
Wie behandel ich das am besten PC-Seitig? :-/
Die ganze Zeit die Schnittstelle pollen und nach x sekunden 
(entsprechend der Baudrate) einen timeout zuschlagen zu lassen finde ich 
sehr unschön.

Eine Idee ist einen Prozess zu starten, dann zwei threads zu erzeugen, 
und ein thread ist nur zum lesen und ein thread nur zum schreiben da. 
(Was irgendwie auch auf polling hinaus läuft :-/ )
Wäre das so überhaupt möglich?

Könnte man statt dem Prozess und den zwei threads auch einfach zwei 
Programme schreiben, eins nur zum lesen, eins nur zum schreiben? Können 
überhaupt mehrere Programme zeitgleich auf ein und dieselbe 
Schnittstelle zugreifen? Wenn ja, wie wird das geregelt?

Weiter Idee: Interrupts
In wie weit stellt mir Linux an der Stelle Interrupts/SIGNALs zur 
verfühgung? Das wäre natürlich die schönste und auch meine bevorzugte 
Lösung. Wenn Daten zum lesen da sind, bekomm ich einen Interrupt und 
kann die Daten abholen, ohne das ich die Schnittstelle die ganze Zeit 
pollen muss, so wie ich es auch auf dem mC mache.

Habt Ihr da vielleicht einen Denkanstoß, wie man das am besten handhabt?
Welche "Libs" sind dafür zu empfehlen?
termios? LibSerial? Irgendwas aus Boost oder Qt?

Ich bin euch für jede Hilfe dankbar!

Gruesse

: Verschoben durch Moderator
von Peter II (Gast)


Lesenswert?

Kaj schrieb:
> Also:
> Es soll möglich sein vom PC was zu senden und dann die Antwort zu
> empfangen. Es soll ebenso möglich sein, etwas zu empfangen, ohne das
> etwas gesendet wurde.

ist schon mal sehr blöd. Dann was ist wenn du etwas sendest und auf eine 
Antwort wartest und der µC gleichzeitig etwas sendet. Dann muss du die 
Antworten richtig auswerten. du machst dir damit das leben selber 
schwer.

> Die ganze Zeit die Schnittstelle pollen und nach x sekunden
> (entsprechend der Baudrate) einen timeout zuschlagen zu lassen finde ich
> sehr unschön.
wieso pollen? Man macht ein Read und gut ist. Das blockiert im 
Normalfall und damit ist das kein pollen.

> Eine Idee ist einen Prozess zu starten, dann zwei threads zu erzeugen,
> und ein thread ist nur zum lesen und ein thread nur zum schreiben da.
> (Was irgendwie auch auf polling hinaus läuft :-/ )
> Wäre das so überhaupt möglich?
ja

> Könnte man statt dem Prozess und den zwei threads auch einfach zwei
> Programme schreiben, eins nur zum lesen, eins nur zum schreiben? Können
> überhaupt mehrere Programme zeitgleich auf ein und dieselbe
> Schnittstelle zugreifen? Wenn ja, wie wird das geregelt?
das ist Unsinn, wie willst du beide Programm synchronisieren, damit du 
Request und Responce zuordnen kannst? Viel zu kompliziert wenn es mit 
Threads einfacher geht.

> In wie weit stellt mir Linux an der Stelle Interrupts/SIGNALs zur
> verfühgung?
dafür nimmt man ein select oder poll und fragt damit die Schnittstelle 
ab, aber das bringt dich nicht wirklich weiter.

von Dr. Sommer (Gast)


Lesenswert?

Den DAteideskriptor auf nonblocking Mode setzen, und select () 
verwenden. Das gibt dir also Bescheid sobald Daten ankommen, oder du 
Daten senden kannst. Die eigentlichen read/write Aufrufe kehren dann 
immer "sofort" zurück, und deren nacheinander-aufrufen ist dadurch 
effektiv "gleichzeitig".

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Der Klassiker hat dafür übrigens zwei Prozesse benutzt (sich selbst
geforkt), dann kann man mit simplem blockierenden Lesen arbeiten. So
war beispielsweise seinerzeit cu(1) aufgebaut.

von auswahl() (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Den DAteideskriptor auf nonblocking Mode setzen, und select ()
> verwenden. Das gibt dir also Bescheid sobald Daten ankommen, oder du
> Daten senden kannst. Die eigentlichen read/write Aufrufe kehren dann
> immer "sofort" zurück, und deren nacheinander-aufrufen ist dadurch
> effektiv "gleichzeitig".

Jedesmal wenn der select() zurückkommt hast du quasi deinen Interrupt.

von auswahl() (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Der Klassiker hat dafür übrigens zwei Prozesse benutzt (sich selbst
> geforkt), dann kann man mit simplem blockierenden Lesen arbeiten. So
> war beispielsweise seinerzeit cu(1) aufgebaut.

Nur hatten die beiden Prozesse bei cu(1) quasi nicht miteinander zu tun.

von Bernd K. (prof7bit)


Lesenswert?

Mach nen separaten Thread der nichts anderes tut als auf Zeichen von der 
Seriellen Schnittstelle zu warten.

Stichwort zum Googeln: select()

Du gibst dem Select Aufruf das (oder die) Datei-Handle(s) das Du auf 
Leseereignisse überwachen willst und einen Timeout in Millisekunden. Der 
select() call wird blocken solange bis entweder ein Ereignis eintritt 
(mindestens ein Byte steht zum Lesen bereit) oder der Timeout erintritt.

* Wenn ein Byte zum Lesen bereitsteht kannst Du read() aufrufen und Dir 
soviele Bytes geben lassen wie da sind, dann die Daten verarbeiten 
(evtl. mit einem Mutex oder dergleichen an geeigneter Stelle verhindern 
daß er dem Main-Thread in die quere kommt wenn gemeinsame 
Datenstrukturen von beiden Threads verwendet werden oder besser noch 
wenn Du ein GUI-Framework verwendest dann einfach mit dessen dafür 
vorgesehener API den main-thread aufwecken (jedes GUI-Framework hat 
dafür eigens vorgesehene Funktionen) und diesen die Daten handlen 
lassen).

* Dann noch kurz prüfen ob der main Thread eventuell möchte daß der 
Receive-Thread sich terminieren möge, wenn ja dann Ende, andernfalls 
wieder nach oben zum select() bis zum nächsten Timeout. Der Timeout muss 
nicht länger als eine Handvoll Millisekunden lang sein, prozentual 
gesehen wird der Thread 99.999% der ganzen Zeit in select() sitzen und 
schlafen.

* wenn das Hauptprogramm den Thread beenden will sollte es ein Flag 
setzen welches der Thread sieht wenn er das nächste Mal aus dem Timeout 
kommt (deshalb ein kurzer Timeout) und dann warten bis der Thread sich 
beendet hat, dann das Dateihandle schließen.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

auswahl() schrieb:

> Nur hatten die beiden Prozesse bei cu(1) quasi nicht miteinander zu tun.

Inwiefern die hier was miteinander zu tun haben müssen, darüber hat
sich der TE gar nicht ausgelassen.  Kann also auf ihn passen oder
auch nicht.

Ist halt eine Lösung, die bereits vor 40 Jahren funktioniert hat …

von Schnapptrude (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Ist halt eine Lösung, die bereits vor 40 Jahren funktioniert hat …

gabs die sereielle Schnittstelle schon vor 40 Jahren?

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Schnapptrude schrieb:
> Jörg Wunsch schrieb:
>> Ist halt eine Lösung, die bereits vor 40 Jahren funktioniert hat …
>
> gabs die sereielle Schnittstelle schon vor 40 Jahren?

Das ist jetzt als Witz gedacht, oder? Die Grundidee mit dem 
Start-Stop-Bits entstand so um 1870. CCITT Standards für serielle 
Übertragung gab es mindestens schon Ende der 20er Jahre. Lange, lange 
bevor es Computer gab. RS232 als Standard stammt vom Anfang der 60er 
Jahre. Um die gleiche Zeit ist das Internationale Alphabet 5 
standardisiert worden. Aus der Nummer kann man ersehen, dass es davor 
bereits vier andere Zeichensätze für serielle Übertragung gab. IA5 ist 
interessant, da es praktisch ASCII ist.

: Bearbeitet durch User
von Schnapptrude (Gast)


Lesenswert?

Hannes Jaeger schrieb:
> Das ist jetzt als Witz gedacht, oder? Die Grundidee mit dem
> Start-Stop-Bits entstand so um 1870.

Nein, die Frage war schon ernst gemeint. Mir war es nicht bewusst, dass 
man sowas schon vor über 100 Jahren gemacht hat. Hat man in den 20er 
Jahren auch schon "Daten" hin- und hergeschickt durch Telefonleitungen?

von Schnapptrude (Gast)


Lesenswert?

Schnapptrude schrieb:
> "Daten"

Ich mein jetzt nicht Morsedaten.

von lex Te (Gast)


Lesenswert?

Schnapptrude schrieb:
> Nein, die Frage war schon ernst gemeint. Mir war es nicht bewusst, dass
> man sowas schon vor über 100 Jahren gemacht hat. Hat man in den 20er
> Jahren auch schon "Daten" hin- und hergeschickt durch Telefonleitungen?

Nennt sich Fernschreiber bzw. Telex. Läuft mit 50 Baud, 5 Bits und 1,5 
Stoppbits.

von Schnapptrude (Gast)


Lesenswert?

lex Te schrieb:
> Nennt sich Fernschreiber bzw. Telex. Läuft mit 50 Baud, 5 Bits und 1,5
> Stoppbits.

50 Baud --> da kann ich ja schneller sprechen am Telefon als so langsam 
einen Text durch das Telefonkabel zu schicken :-)

von Schnapptrude (Gast)


Lesenswert?

Gibt es dann gab es bei den 5 bits auch Umlaute schon wie äößü? Oder 
waren das reine angelsächsiche Fernschreiber? Konnte man auch schon 
damals über diese langen Seekabel von Europa nach Amerika mit 
Fernschreibern Daten hin- und herschreiben?

Wie ging denn dann das mit der Verstöpsellung? Damals gabs doch noch die 
Damen vom Amt, denen man gesagt hat, wo man hin will und sie einen hin- 
und hergestöpselt haben. Musste man das vorher auch mit den 
Fernschreibern machen oder hatten die Fernschreiber feste statische 
Leitungen, die immer mit dem einen oder dem anderen Fernschreiber 
verbunden waren?

Ist das eigentlich richtig, dass die Y-Tour-Gesellschaft ein eigenes 
parallel zum Postnetz verlaufendes Kommunikationsnetz hat - also ein 
Bundeswehrnetz?

von Tom (Gast)


Lesenswert?

Schnapptrude schrieb:
> Gibt es dann gab es bei den...

Hast Du vielleicht den Wikipedia-Artikel zum Fernschreiber 
zusammengefasst und in Frageform umformuliert?

von Schnapptrude (Gast)


Lesenswert?

Tom schrieb:
> Du vielleicht den Wikipedia-Artikel

was ist WikiPedia?

von Thom (Gast)


Lesenswert?

Wikipedia ist eine Joghurtsoße, mit der man Schmand aus Brillengläsern 
verwenden kann.

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
Noch kein Account? Hier anmelden.