Hallo,
bin auch gearde mit dem Slave FIFO Interface des FX2 beschäftigt. Leider
komme ich momentan nur auf eine Datenrate von 4MB/s.
Ich steure es mit einem Zustandsautomaten aus einem FPGA an. FULL flag
berücksichtige ich usw.
Nun takte ich die FSM einmal mit 12.5 MHz und einmal 25MHz. Beide Male
sind die Datenraten gleich.
Der Falschenhals liegt also bei Software mit der ich die Daten auslese.
Seitens des FX2 verwende ich Bulk-Übertragung, 4x buffered, Auto IN, ext
clocked.
Ich verwende libusb, synchron. Dort hohle ich in einer Schleife mit
usb_bulk_read() Datenblöcke mit je 1024Bytes ab.
Im Thread stand, dass man größere Datenblöcke anfordern soll, dann wird
die Übertragung schneller.
Warum das?
1024Byte pro Transfer ist zu wenig. Da kommst du nur auf so niedrige
Raten. Wir erreichen die 40MB/s knapp, wenn wir richtig große Blöcke
abholen....128kiByte beispielsweise.
Achso, die Rechung: Bei 1024 Byte pro Transfer ist ein Microframe nur
mit 1024 Byte gefüllt. Bei USB 2.0 HighSpeed wird alle 125µs ein
Microframe generiert. Ist der nur mit 1024 Byte gefüllt, kommst du auf
ziemlich genau 8MB/s maximal.
Christian R. schrieb:> 1024Byte pro Transfer ist zu wenig. Da kommst du nur auf so niedrige>> Raten. Wir erreichen die 40MB/s knapp, wenn wir richtig große Blöcke>> abholen....128kiByte beispielsweise.>
Aha..
>>> Achso, die Rechung: Bei 1024 Byte pro Transfer ist ein Microframe nur>> mit 1024 Byte gefüllt. Bei USB 2.0 HighSpeed wird alle 125µs ein>> Microframe generiert. Ist der nur mit 1024 Byte gefüllt, kommst du auf>> ziemlich genau 8MB/s maximal.
Ok.., und das unter der Vorraussetzung, dass alle 125us usb_bulk_read()
ausgeführt wird. Denn der Host ist ja der "master".
Wenn die externe Logik in der Lage ist 6656 Bytes alle 125us (pro
Microframe) zu liefern, kommt mal also auf eine Datenrate von ca
50MB/s..
Vorrausgesetzt, dass usb_bulk_read() alle 125us aufgerufen werden kann,
reicht dann doch also, immer 6656 Bytes mit dieser Funktion anzufordern?
Wenn es nun aber nicht nicht möglich ist, alle 125 us die Funktion
aufzurufen, muss man größere Blöcke anfordern, sodass mehrere Microframe
aufeinander folgend empfangen werden.
Also wäre es grundsätzliche ratsam größere Blöcke anzufordern, wie bei
euch 128kByte.
Dann muss die externe Logik allerdings auch schnell genug nachliefern,
sonst gibt es einen timeout.
Gibt es da nicht auch eine obere Grenze bei libusb bezüglich der
Einlesemenge?
Also die 125µs sind fest. Und darum kümmert sich der Hostcontroller. Das
API sollte die Blöcke so groß wie möglich abfragen. Außerdem sind bei
HighSpeed die Pakete maximal 512 Byte groß. Pro MicroFrame passen 10 bis
11 512 Byte rein. Man kommt also nur auf etwa 40MB/s. Musst du das
TimeOut entsprechend hochsetzen. Wir lesen immer so riesen Brocken. Die
Hardware setzt das Packetend an der entsprechenden Stelle, dann kommt
der Treiber zurück, auch wenn die Anzahl noch nicht erreicht ist. Und da
wir im Voraus exakt wissen, wieviel Daten anliegen, klappt das.
Ok, danke für den Tipp! Sehr gut..Bin jetzt bei meinen erwarteten
15-16Byte/s. Meine FPGA Logik kann theoretisch auch nur 16,66MByte/s
Daten produzieren. Soweit so gut.
Zum PKTEND: Lasse den FX2 mit AUTOIN=1 laufen. Mit meiner FPGA Logik
frage ich das Full Flag ab, sodass wenn das FULL-Flag high ist, keine
Daten in das Slave FIFO geschrieben werden. In der Simulation
funktioniert der Mechanismus. Ob das FULL Flag aber überhaupt mal high
wird, habe ich noch gar nicht geprüft. - Die Daten, die ich empfange
sind jedenfalls korrekt, ganz ohne PKTEND. Naja habe ja auch einen
kontinuierliche Datenstrom. Der PKTEND Pin ist ja nur für Anwendungen
gedacht, wenn keine Daten mehr von der externen Logik mehr generiert
werden und der FIFO-Füllstand des Autoin noch nicht erreicht ist.
Naja, wenn der Rechner mal zu tun hat, wirst du schon merken, wie
wichtig das Full Flag ist. Das PacketEnd ist schon sehr nützlich, eben
weil man dann fast beliebig große Transfers machen kann, die keine
ganzzahligen Vielfachen von 512 Byte sind. Und weil man damit einen noch
größeren Datenstrom segmentieren kann. Wir nutzen das wie gesagt
intensiv.
Hallo
Ich habe gerade auch mit dem Chip zu tun.
Wie sind eure Erfharungen, in wie weit wirkt sich die MaxPacketSize auf
die Transferrate aus? Bei kelienren Paketen wird der prozentuale Anteil
des Overheads größer. Kommt sonst noch etwas dazu?
Viele Grüße, Tilo
Tilo schrieb:> Wie sind eure Erfharungen, in wie weit wirkt sich die MaxPacketSize auf>> die Transferrate aus? Bei kelienren Paketen wird der prozentuale Anteil>> des Overheads größer. Kommt sonst noch etwas dazu?
Naja, es gilt ja die Microframes möglichst voll zu bekommen. Es passen
ja zehn bis elf Pakete je 512 Bytes(maximal) in einen Microframe(bei
bulk Transfer). Wenn die Pakete nicht voll werden, schafft man eben
nicht die volle Bandbreite. Die Anzahl der Pakete ist glaube ich fix.
Wie schnell taktet Ihr den FX2? Und taktet ihr ihn extern oder intern?
Guten morgen
Leider intern, weil es das Design so vorgibt. Ich bin gerade dabei von
Iso auf Bulk umzustellen. Das Problem ist, dass das Datenvolumen nicht
fix ist und man den Iso. Transfer auf Worst case auslegen muss. Mit dem
CyUSB Treiber scheint dies den PC dann ordentlich zu beschäftigen.
Da von libusb die rede ist, verwendet ihr Linux oder Windows?
Also wir nutzen den CyUSB Treiber unter Windows und arbeiten ohne das
beknackte API direkt auf den IOCONTROLS. Das API kann parallele
asynchrone Transfers nicht korrekt handhaben. Die sind aber nötig, um
konstant die volle Datenrate auszuschöpfen. Eine sonderlich hohe
Prozessorlast gibts dabei aber nicht (<3% bei 40MB/s auf einen C2D mit
3GHz). Auch da schlagen die möglichst großen Blöcke wieder rein. Je
weniger Anfragen gestellt werden müssen, desto weniger Prozessorlast.
Wenn man ständig kleine Pakete abholt, steigt die Last rapide an.
Kann ich dir nicht genau sagen. Ich bin der Hardware-Entwicker. Der
zuständige SW-Entwickler hat nach 2 Tagen das Handtuch geworfen und den
Treiber direkt angesprochen. Das geht super.
Mist, ich bin auch "nur" der Hardwareentwickler.
Bei uns die CyAPI eigentlich recht gut. Problematisch war allerdings
bisher, dass es gerne zu PacketLoss kommt.
Momentan arbeite ich auch mit den synchronen Interface von libusb. Die
Datenrate, die ich zur Zeit habe, reicht mir zunächst. Allerdings möchte
ich schon noch das asynchrone Interface als Alternative habe.
Ja, ich habe schon einen Versuch gemacht. Leider hat es nicht geklappt.
Bis zu dieser ..reap..() Funktion läuft alles super, doch bei dieser
Funktion bekomme ich -5 zurück. "Can't find entity" bedeutet das glaube
ich. Habe auch schon im Forum nachgefragt, aber da konnte mir auch
keiner helfen. Falls du weiter bist, kannst du das hier gerne zum Besten
geben:)
PacketLoss haben wir nicht, aber wir haben noch ein kleines Problem bei
extreme Datenraten. Wenn wir zusätzlich zum massiven upstream noch
einiges an Downstream erzeugen, verhaspelt sich der Chip und/oder der
Treiber. Das haben wir noch nicht gänzlich klären können. An der
Firmware scheints nicht zu liegen, das tritt erst bei vielen parallelen
asynchronen Anfragen an den Treiber auf. Wenn wir mal Zeit haben,
stellen wir das mal auf den WinUSB aus dem KMDF um, und schauen, wie das
dann aussieht.
Welche Chiprevision verwendet ihr? Ich hab in einem Errate was gelesen,
dass Daten zerwürfelt, wenn mehrere OUT-Endpoints verwendet werden.
Ihr habt mir mit der CyAPI Angst gemacht. Wir haben nur in eine Richtung
etwas größere Datenmengen, glück gehabt.
Beim Testen ist mir etwas anderes aufgefallen:
An manchen PCs renumeriert sich der FX2 nach upload der Firmware nicht
richtig. Dies kann daran erkannt werden, dass in CyConsole zwar das
Gerät angezeigt wird, dem Gerät aber alle Endpoints fehlen. Drücke ich
in CyConsole auf "Reset" tauchen die EPs auf.
Kommt einem von euch das Problem bekannt vor?
Was macht ihr in der Firmware zu erst: EPs konfigurieren oder
Renumerierung? Hat einer schon mal versucht die EPs anderst zu
konfigurieren, muss das Device dann reconnected werden?
Viele Grüße,
Tilo
Also wir haben nur einen OUT EP und einen IN EP. Die Firmware ist quasi
die BulkLoop Beispiel Firmware, halt auf Slave FIFO umgeschaltet. Ich
hatte hier auch mal eine ähnliche Firmware gepostet, die auf jeden Fall
funktioniert, da sieht man auch die Reihenfolge. Einfach mal suchen.
Diese Renum Geschichten haben wir nicht. Wir halten die Firmware
komplett im EEPROM und das Laden und enumerieren klappt immer
zuverlässig. Mit synchronen Zugriffen funktioniert die CyAPI auch
problemlos, nur mehrere parallele asynchrone Anfragen kann die schlecht
handhaben. Wahrscheinlich der Treiber an sich auch, das müssen wir wie
gesagt, bei viel Zeit mal herausfinden. Prinzipiell ist der WinUSB
Treiber bzw. der hier Beitrag "Generischer USB Treiber für Windows mit C++ API"
der auch WinUSB nutzt, eine gute Sache.
Hallo
Die Beispiele habe ich soweit surch. Prinzipiell halte ich mich auch an
die Beispiele. Leider passen die nicht immer.
Ich will z.B. folgendes:
EP2 soll OUT-EP mit 64Byte Bulk sein
EP6 soll:
Wenn HS-Mode: IN-EP mit Quad-512Byte Bulk
Wenn FS-Mode: IN-EP mit Quad-64Byte Bulk sein
Optional ist für Testzwecke nochmal beides als isochron drin.
EP6 wird von einem DSP gefüttert. Autocommit soll an sein, so dass der
FX2 volle Pakete selbstständig wegschickt. Der DSP schickt immer 64Byte
Blöcke. PF soll daher low werden, so bald 64Byte nicht mehr in die
Puffer des FX2 passen, damit der DSP weiß, dass er warten muss.
Das verrückte ist, an vielen PCs tut alles einwandfrei aber an einzelnen
PCs funktioniert das Device reproduzierbar nicht. Ich bin noch nicht
dahinter gekommen, warum.
Fällt dir eventuell etwas auf?
Im ersten Codeteil passe ich die Descriptortable dynamisch an. Diese
beginnt bei 0x0500. Danach will ich die EPs für den DSP einstellen.
Verwendest du auch Autocommit? Kann es sein, dass ein Paket, das
commitet wurde aber noch nicht vom Host abgeholt wurde nicht mehr mit
INPKTEND gelöscht werden kann?
Vielen Dank,
Tilo
Ich hab das Problem gefunden.
Ich habe die USB Spec so verstanden, dass im FullSpeed Mode 8,16,32,64
und im HighSpeed Mode dazu zusätzlich 512 Byte Pakete zugelassen sind.
Tatsächlich sind es nut 512Byte im HS Mode. Die meisten USB-Hosts machen
das mit aber nicht alle.
Wenn ich das PROGLEVEL Flag des FX2 benutze, um zu sagen, dass das FIFO
fast voll ist.
Muss ich dann auch zwangsweise den PKTEND Pin setzen, damit sich das
FIFO wieder leert (Ich arbeite im AUTOIN Modus)? Oder leert es sich
automatisch, da ich im AUTOIN Modus bin. Ich mache quad buffering. der
letzte Buffer wird dann also nicht ganz voll. Die anderen Buffer werden
aufgrund des AUTOIN Modus doch aber geleert, dass sich das FIFO
automatisch leert, oder?
Im AUTOIN-Mode werden volle Pakete automatisch commited.
Sagen wir, du hast einen Quad buffer. Die ersten drei Buffer sind voll,
der 4. zur Hälfte. Wenn der PC nun Daten abholt, werden die drei vollen
Puffer abgeholt und freigegeben, der 4. jedoch nicht, da er noch nicht
voll ist. Werden nun weiterhin Daten in den FIFO geschoben, wird der
angefangene Puffer voll gemacht und dann an den PC geschickt.
Mit dem PKTEND kann ein Paket abgeschickt werden, dass noch nicht voll
ist.
Beispiel 1: Kontinuierlicher Messdatenfluss
PKTEND muss nie gezogen werden, da kontinuierlich Daten in den FIFO
geschrieben werden und somit die Pakete immer voll werden. Die vollen
Pakete werden voll automatisch vom PC abgeholt.
Beispiel 2: ACK auf ein Steuerkommando
PKTEND muss gezogen werden, da in den meisten Fällen nach dem ACK keine
weiteren Daten in den FIFO geschrieben werden. Da das Paket nicht voll
ist, würde das Paket ohne PKTEND nie an den PC geschickt. Durch das
PKTEND wird alles was im FIFO ist an den PC geschickt.
Das Proglevel-Flag hat einen anderen Zweck. Ich verwende einen DSP mit
DMA, um die Daten in den FIFO zu kopieren. die DMA kopiert immer 64Byte
Blöcke in den FIFO. Mit dem Proglevel Flag kann ich sicherstellen, dass
ein Block mit 64Bytes auch in den FIFO passt. Ohne das Flag musste jedes
Byte einzeln in den FIFO kopiert werden und dann einzeln das FIFO-Full
Flag ausgewertet werden. Das ganze ist ein Performance-Booster.
Ich hoffe ich habe alle Klarheiten beseitigt?
Viele Grüße,