mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik FTD2XX als "Bremsklotz"?


Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo miteinander

Momentan arbeite ich gerade an einer USB-Kommunikation. Das ganze ist in 
ein Frame verpackt und wird über den FTD2xx Treiber angesprochen

Jetzt habe ich das Problem, dass in einer while-Schlaufe das Frame 
gesendet wird (Kommunkikation läuft in einem BackgroundWorker). 5kBytes 
als Nutzdaten werden innerhalb von ~20 Milisekunden beim MCU empfangen, 
ausgewertet und verarbeitet. Das ganze Protokoll, welches aus ENQ, SOH, 
Command, NUM + PAR, ACK, ACK EOT besteht, benötigt aber > 50ms?!
6 zusätzliche Bytes benötigen solange wie 7kByte?

Hat jemand schon mal etwas ähnliches Erlebt, und weiss, wie ich es 
beheben kann?

Besten Dank für die Hilfe
MFG
Patrick

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Könnte an der niedrigen Priorisierung von USB Trabnsfers im OS liegen. 
Wir haben hier auch USB 2.0 HighSpeed Geräte, da macht Windows selbst 
bei kontinuierlichem Streaming immer mal Pausen von bis zu 50ms zwischen 
Transfers. Ist zwar relativ selten, tritt aber sporadisch auf. Auch 
manchmal, wenn gar nix anderes läuft und die Prozessorlast gegen 0 geht.

Autor: ein_unwissender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schon mal an die ganzen Puffer im Windows-Treiber gedacht?
Wenn du nur 1 Byte verschickst wartet der Treiber sicherlich mit dem 
verschicken bis noch mehr Daten kommen bzw. bis ein Timer abgelaufen 
ist...

Vielleicht kannst du Padding hinzufügen, damit schneller gesendet wird? 
Musst du halt am Mikrocontroller ausfiltern...

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ein_unwissender schrieb:
> bzw. bis ein Timer abgelaufen
> ist...

In etwa so ist das auch mit dem Timeout gedacht. Dieses habe ich aber 
auf 0 zurückgedreht. Jetzt erreiche ich immerhin schon konstant eine 
Übertragungsgeschwindigkeit, die etwa 1/7 der Entgeschwindigkeit ist.

Wie könnte man die Priorität eines Programmes respektive des USB 
erhöhen, damit diese Operationen Zeitlich gesehen "genau" dann ablaufen, 
wann ich es will, und nicht, wann windows es möchte (Ich weiss, dass das 
jetzt nicht zusammenpasst, aber ich denke auch im MCU styl).

Besten Dank für die Hilfe
MFG
Patrick

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wie könnte man die Priorität eines Programmes respektive des USB
>erhöhen, damit diese Operationen Zeitlich gesehen "genau" dann ablaufen,
>wann ich es will, und nicht, wann windows es möchte (Ich weiss, dass das
>jetzt nicht zusammenpasst, aber ich denke auch im MCU styl).

Das kannst du nicht. USB ist nicht Echtzeit tauglich.

Autor: madler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ENQ, SOH, Command, NUM + PAR, ACK, ACK EOT

Ich versteh nicht ganz wann da jetzt wer was sendet und Ack't, aber 
generell gelten zwei Sachen:

- die Treiber der seriellen Schnittstelle, sowie insbesondere der USB 
sind darauf optimiert mit hoher Datenrate relativ grosse Pakete zu 
uebertragen (Serielle Schnittstelle fuer Modems)
- die Latenzen sind dagegen ziemlich hoch. Ein einzelner Transfer bspw 
an die serielle Schnittstelle macht ne ganze Menge mit Events zum 
Treiber. Dh da muessen Threads vom Scheduler aufgeweckt werden usw. 
Allein die zeitliche Stueckelung mit der der Scheduler arbeitet liegt in 
der Groessenordnung von 10ms. Und alles das fuer ein Byte Acknowledge 
ist halt sehr ineffizient.

Also am Besten:
- moeglichst grosse Pakete uebertragen
- dein Protokoll auf moeglichst wenig "Hin- und Her" (zB Acks) 
optimieren

So die grobe Aussage ;)

Autor: Strubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Trick bei USB heisst: Queueing

Also, wenn Du ein Protokoll auf der anderen Seite laufen hast, welches 
viel Pingpong oder sogar (quasi-) vollduplex arbeitet, kriegst du mit 
folgender Strategie hohe Durchsaetze:
Alles was zunaechst zu schreiben ist, schreiben, dann einen grossen 
Block lesen, und alle ACKs, etc. verarbeiten. Der FTDI-Chip puffert ja 
ein paar Byte in seinem FIFO ab, solange du das nicht volllaufen laesst, 
ist gut.
Wenn das Protokoll allerdings so gestrickt wird, dass erst nach einer 
gewisen Zeit nach dem ACK wieder Daten geschickt werden duerfen, gehts 
so nicht, und du solltest dir ein besseres Protokoll ueberlegen.


Gruesse,

- Strubi

Autor: Johann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich habe heute gerade mit dem FT2232H von FTDI 32MByte pro Sekunde 
erreicht. Das ist schon ganz ok. Ich habe mit 65k Byte großen Blöcken 
gearbeitet, damit der Overhead möglichst klein ist. Jedoch verwendet 
FTDI nur 512 Bytes große Endpoints und dann auch nur 2 davon obwohl die 
4kByte im Chip besitzen.

Zu Christian R.

Ich habe auch mal die TXE Leitung untersucht. Bei mir sind bis jetzt 
noch keine längeren Pausen als 600µS vorgekommen. Ich habe den FTDI Chip 
an einem Notebook und einen Deshtop PC angeschlossen. Beide haben keinen 
Unterschied angezeigt.

Zudem teste ich es gerade unter Vista 64 Bit.

Autor: Johann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier habe ich meine vorgehensweise etwas besser dokumentiert

Beitrag "FTDI USB erzeugt Blue Screen"

Autor: Mars (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Jedoch verwendet FTDI nur 512 Bytes große Endpoints und dann auch nur 2 >davon 
obwohl die 4kByte im Chip besitzen.

Im HS-Modus kann ein Bulk EP nur maximal 512 Bytes haben, da kann FTDI 
nichts dafür ;-)
Zwei EPs (einer IN einer OUT) reichen vollkommen aus um aktuelle 
Host-Controller auszulasten. Wichtig ist hierbei möglichst große Puffer 
zu verwenden (64KB sind eher schon das Minimum) und immer mehrere 
I/O-Operationen ausführen um den Host-Controller zu beschäftigen.
Leider ist die FTD2XX-API was das betrifft sehr eingeschränkt und noch 
eher auf die FS-Devices ausgerichtet.

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Strubi schrieb:
> Wenn das Protokoll allerdings so gestrickt wird, dass erst nach einer
> gewisen Zeit nach dem ACK wieder Daten geschickt werden duerfen, gehts
> so nicht, und du solltest dir ein besseres Protokoll ueberlegen.

Hmmm...
OK, bei einem Streaming MUSS zwingend eine Anfrage kommen, und dann die 
Daten. Ich habe auch schon an grössere Datenmengen gedacht, aber da 
steht mir der MCU (dsPIC30F6012A mit 8k RAM) im Weg. Momentan läuft es 
so, dass ich sobald beim Ring-Buffer die Hälfte der Werte abgearbeitet 
sind, ein ENQ and den PC schicke, damit dieser mir wieder neu 2.4kByte 
schickt, um die "verbrauchte" Hälfte zu erneuern. Dazu kommt, dass ich 
nicht das ganze RAM nutzen kann: Fette Arrays mit 800 Plätzen (2 mal 
16Bit und 3 mal 8Bit) ist das Maximum was ich erreiche, befor der 
Compiler meckert, dass er den restlichen Speicher nicht allocieren kann. 
So gehen mir ~25% verloren, da ich diesen nicht Nutzen kann.

Ich könnte es so anpassen, dass ich vom MCU ein ENQ erhalte, und dann 
ohne weitere Steuerbytes leich die 2.4kByte schende.

Strubi schrieb:
> Alles was zunaechst zu schreiben ist, schreiben, dann einen grossen
> Block lesen, und alle ACKs, etc. verarbeiten.

Und was würde passieren, falls eine der Parteien plötzlich ein Fehler 
registriert oder sonst irgend etwas hat? Das geschrieben wäre weg....

Johann schrieb:
> Ich habe auch mal die TXE Leitung untersucht. Bei mir sind bis jetzt
> noch keine längeren Pausen als 600µS vorgekommen.

TXE kommt bei mir nicht vor, da ich einen FT245 verwende. Das Auswerten 
übernimmt ein 16Bit MCU mit 128MHz... zudem wird die entsprechende 
Funktion in einer for-Schleife gleich ein paar mal abgearbeitet, damit 
dieses möglichst flott geht.

Mit dem KO habe ich mal versucht, ein wenig die Zeiten zu messen:
der PC erhält ein ENQ, danach startet er das Frame mit einem ENQ für den 
MCU. dieser bestätigt die Empfangsbereitschaft mit einem ACK. Danach 
werden 2.4kBytes vom PC versendet.
Zwischen dem 2. ENQ und dem grossen Block, vergehen zwischen 380us bis 
4ms. Duchrschnittlich wären es etwa 1.1ms.


Durch diese Verzögerung kann ich auch nicht die Stream-Menge verdoppeln 
auf die ganze Puffer-Grösse, da ich dann eine Verzögerung der Daten von 
bis zu 4ms erhalte. Dies darf aber nicht sein. der MCU muss 
kontinuierlich Daten zur Verfügung haben.

Besten Dank für die Hilfe.
MFG
Patrick

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Strubi schrieb:
> Alles was zunaechst zu schreiben ist, schreiben, dann einen grossen
> Block lesen, und alle ACKs, etc. verarbeiten.

Diesen Rat habe ich beherzigt und jetzt die Frame-Zeit so auf ca 8ms 
verkleinert. Dies reicht locker da der MCU dies Datenmenge in etwa 14ms 
verarbeitet hat. Somit hat der USB Treiber eine kleine Pause von ~5-6ms.

MFG
Patrick

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.