Hallo,
ich habe hier nach einiger Zeit eine FX2-Schaltung im Slave-Mode am
Laufen. Der Daten-Transfer funktioniert unter C# auch zum Teil.
Das Problem ist, das die Daten gestreamt werden müssen und ich eine Rate
von ca. 2 MBytes/s im Moment habe. Das ist natürlich zu wenig (so 15 -
25 MB/s brauch ich schon).
Gestreamt heißt in diesem Fall, daß ich die Daten ohne Unterbrechung an
den PC senden muß.
Meine Frage: Wie mach ich das am Besten? Mit C# oder vlt. doch besser
mit C++. Das ist ja 'von Natur aus' schneller.
Wer hat Tipps für mich (möglichst detailiert)?
Danke im Vorraus. Gruß Pit
Wir arbeiten auch mit C# und dem FX2, nehmen den WinUSB Treiber und
erreichen damit ca. 40MB/s. 2MB/s klingt, als würdest du nur ganz kleine
Pakete übertragen? Wenn du hohe Datenraten brauchst, musst du auf der
FPGA Seite viel puffern und auf der PC Seite per BULK rieige Blöcke
anfordern. Und keinesfalls nur 512 Byte nur pro Transfer. Auch mit dem
Packet End sparsam umgehen, denn dann ist ein ganzes MicroFrame
abgeschlossen.
Naja, ich puffer momentan garnicht. Ich jage alles raus wie es kommt.
Ich kann mir nicht vorstellen, dass puffern etwas bringt. Bei 20MBytes/s
brauch ich ja 6 MBytes an Puffer, wenn sich Windows mal 300ms
anderweitig beschäftigt.
Auf der Empfangsseite lese ich mit 64kByte-Paketen aus. Allerdings immer
nur ein Lese-Aufruf. Irgendwo habe ich gelesen, dass mehrere parallele
Aufrufe der Renner sind. Allerdings weiß ich nicht wie ich das am Besten
anstelle.
Naja, wenn du konstante Datenraten brauchst, aber auch Datensicherheit
kannst du nur über BULK gehen und viel puffern. 6MB ist schon heftig,
wir nutzen momenten 64k x 16 Bit in unserer Applikation. Mehrere
Leseanfragen geht über Asynchronne Transfers, aber das bringts nicht so
wirklich. Für 20MB/s wirst du ohne Puffer nicht auskommen, es sei denn,
du nutzt isochrones Streaming, da hast du 24MB/s, aber keine
Datensicherheit. Wenn Daten weg sind, sind die weg, wiederholt wird
nichts.
Pit schrieb:> Ich kann mir nicht vorstellen, dass puffern etwas bringt. Bei 20MBytes/s> brauch ich ja 6 MBytes an Puffer, wenn sich Windows mal 300ms> anderweitig beschäftigt.
Und das soll der Grund sein das puffern nichts bringt???
Wenn du ein Stream hast, denn du ohne Verlust/Fehler an den PC schicken
willst, dann musst du umbedingt auf Device Seite puffern.
>6MB ist schon heftig, wir nutzen momenten 64k x 16 Bit in unserer Applikation.
Das ist reine Theorie: 300ms * 20MBytes/s = 6 MBytes.
>Und das soll der Grund sein das puffern nichts bringt???>Wenn du ein Stream hast, denn du ohne Verlust/Fehler an den PC schicken>willst, dann musst du umbedingt auf Device Seite puffern.
Der Grund steht oben schon. Bei einer Datenrate von 20MB/s fallen
soviele Bytes an, daß ich mangels RAM sowieso einen Datenverlust habe.
Wozu also puffern?
Ich glaube auch nicht, daß der USB das Problem ist. Wenn man keine
Unmengen an USB-Geräten am Bus hat, dann sollte das mit Bulk-Transfers
gehen. Der FT2232H schaft ja auch ca. 10MBytes/s asynchron.
Ich glaube die Wahrheit liegt in der Software auf PC Seite und hatte
gehofft, jemand hat da schon rumgetüftelt.
Moin,
mit Bulk und libusb sollten ansich bis zu 27 MB/s (gemessen) drinliegen,
wenn man schick grosse Blöcke anfragt. Das Problem ist aber der
blockierende Aufruf von usb_bulk_read(), man kriegt die Performance nur
hin, wenn man eben auch fix, grosse Blöcke von der HW bekommt, also
tendentiell was wie einen Paket-Transfer implementiert. In der
Abfrage-Mainloop darf sonst auch nicht viel laufen.
Bei Streaming mit irregulären Blöcken geht die Performance runter, da
muss man es per asynchrone API 'non-blocking' machen. Mit isochron
kriegt man ansich die 48 MB/s mit einer dauernd gefüllten "buffer queue"
hin, wenn man drei Pakete in den Microframe packt, aber wenn man die
nicht vollhalten kann, motzt der Protokoll-Layer. Und am Anfang verliert
man sowieso immer mal Pakete, bis der Acquisitionsprozess sich
warmgelaufen hat (unter nicht realtime-Linux zumindest). Es hängt also
sehr vom eigentlichen logischen (selbst implementierten) Protokoll ab,
wie man am effizientesten Daten einzieht.
Wenn möglich, würde ich in deinem Fall versuchen, es als erstes im
Bulk-Mode und cleverer Paketisierung zu machen.
Viel Erfolg,
- Strubi
P.S. Hilft übrigens sehr, mit einem Oszi/LA die RX full/TX empty flags
zu monitoren
48MB/s? Naja, das wohl eher nicht. Iso macht 24MB/s bei 3 x 1024 Byte
pro Paket, jedenfalls steht das im FX2 Manual.
40MB/s sind durchaus auch synchron möglich, aber nur mit großen Paketen
und Buffern. Das Problem ist, dass die Buffer in einem Rutsch geleert
werden, da passen, wenn im Buffer auf Device Seite verfügbar, 10 bis 11
512 Byte Pakete in einen Microframe, was dann die reichlich 40MB/s
ergibt. Aber die müssen auch verfügbar sein. Wenn die nicht im Puffer
liegen, dann sinkt die Datenrate rapide. 300ms wäre schon worst case,
wir hatten hier max. 50ms Pause im Normalbetrieb gemessen. Wenn keine
Daten verloren gehen sollen, dann musst du entsprechend puffern, da
beißt die Maus keinen Faden ab. Unser System funktioniert aber so, dass
die Messdaten sowieso angefordert werden, Daten dürfen keine verloren
gehen, also sinkt dann die Trigger-Rate...
Probier mal den WinUSB Treiber, kann ich echt nur empfehlen.
Hallo,
eine kurze Rückmeldung:
Ich habe das jetzt mit den Funktionen BeginDataXfer, WaitForXfer und
FinishDataXfer gelöst.
Man muß etwas rumprobieren, um die passende Anzahl an parallelen
Aufrufen und die Puffergröße richtig einzustellen. Dann klappt es aber
ganz gut. Bisher habe ich die Datenpakete noch nicht ausgewertet, aber
die FULL-Flag-LED blitzt jedenfalls nicht mehr auf (bei 15MBytes/s).
Danke für die Hilfen, Gruß Pit
Pit schrieb:> Bisher habe ich die Datenpakete noch nicht ausgewertet, aber> die FULL-Flag-LED blitzt jedenfalls nicht mehr auf (bei 15MBytes/s).
lol...
Werte besser mal deine Datenpakete aus. Wenn du kein blitzen der LED
siehst, heisst das noch lange nicht dass da kein Blitzen ist. Es könnte
so kurz sein, dass du es nicht realisierst. Am Besten du schliesst mal
das Oszi an den FULL Flag Pin.