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
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.
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".
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.
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.
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.
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.
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 …
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.
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?
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.
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 :-)
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?
Schnapptrude schrieb:> Gibt es dann gab es bei den...
Hast Du vielleicht den Wikipedia-Artikel zum Fernschreiber
zusammengefasst und in Frageform umformuliert?