Hallo,
ich habe den Cypress 68013 auf dem braintechnology board zum laufen
bekommen.
Mein C Programm benutzt die cyAPI.lib und empfängt Daten per
Bulk-Transfer von einem Endpunkt.
Die Daten werden vom 8051 generiert, ich habe eine kleine Firmware
gebastelt, die immer wenn der Endpunkt leer ist, das erste Byte ändert
und dann die 512 Bytes auf die Reise schickt.
Funktioniert alles, es gehen auch keine Pakete verloren, aber...
Die Datenübertragung liegt nur so um die 10MB/s (in Abhängigkeit von der
gewählten Blockgröße mal mehr mal weniger).
Ich hätte so um die 20MB/s mit einem Endpunkt und so um die 40MB/s mit
zwei Endpunkten erwartet, da in der Cypress Application Note etwas von
21MB/s für Bulk-Transfer und 24MB/s für Isochron stand.
Ideen was da schief gegangen ist?
Gruß Ekkehard
Nunja, da hab ich auch eine Weile dran gesessen. Habe die gleiche
Konstellation. Wenn ich den IN-EP 4-fach buffere und mit der Firmware
einfach immer wieder neu scharf mache, wenn das Full-Flag weggeht,
schaffe ich es, ihn mit 38MByte/s auszulesen. Man muss allerdings riesen
Blöcke anfordern, mit 32 bis 64k Blocklänge war ich dann bei den
38MByte/s. Kann man auch auf dem oszi beobachten, dass dann die
Microframes mit 10 bis 11 Paketen gefüllt sind. mehr geht dann nicht.
11*512Byte/125µs = 42,96875MB/s Brutto ergibt dann ungefähr 38,5MB/s
netto.
Jetzt arbeiten wir gerade dran, das Slave-FIFO Interface auch so zu
füttern, dass man diesen Wert auch mit echten Daten erreicht. Müsste
aber auch klappen, Quad-Buffer und 16-Bit Transfer mit den 48MHz
internen Clock vorausgesetzt.
Danke für die rasche Antwort. Also ich habe nochmal alles durch den Wolf
gedreht, es ändert sich aber nichts wesentliches.
Um etwas Licht ins Dunkle zu bringen habe ich den 8051 so programmiert,
dass er in der einen Portpin toggelt wenn er neue Daten scharf macht.
Ergebnis: innerhalb von 125us wird 8 mal der Puffer scharf gemacht, dann
aber eine Pause von 200us eingelegt. Das spiegelt dann ziemlich exakt
meine 10MB/s und Deine 38,5MB/s wieder.
Hast Du noch einen Tipp?
Gruß Ekkehard
Hier der 8051 code, wird permanent aufgerufen
Wieviel-fach ist denn der Endpoint gepuffert? Das Pin-Setzen und die
Auswerterei vorher brauchen außerdem auch einige Takte....
Ich teste das mal bei mir mit deinem TD_POLL()...
Also ich komme mit deiner Software auch auf etwas über 38MB/s aus dem
EP6.
Du hast das SYNCDELAY(); vergessen, das muss da hin, wenn man die
EPBuffer wieder scharf macht.
Probier mal das Stück Code:
1
if(!(EP2468STAT&bmEP6FULL))
2
{
3
EP6FIFOBUF[0]=buffer6ctr;
4
buffer6ctr++;
5
if(buffer6ctr&0x01)
6
{
7
IOA|=0x02;
8
}
9
else
10
{
11
IOA&=~0x02;
12
}
13
EP6BCH=0x02;
14
SYNCDELAY;
15
EP6BCL=0x00;// arm EP6IN
16
SYNCDELAY;
17
}
Hab´s jetzt mit der LibUSB Win32 getestet, die CyAPI ist mir zu
verworren....und statische lib, alles Murks ;) Geschwindigkeit ist aber
die gleiche. Rechner ist ein HP mit Core 2 Duo, 1GB RAM, VS 2005, ohne
weitere Berechnungen im Lese-Thread....Programm läuft mit der MFC.
Danke erstmal für Deine schnelle Reaktion.
Das SYNCDELAY habe ich nicht "vergessen" sondern "verdrängt" ;-)
Ich wollte das ganze Zeug mit dem SDCC compiler statt Keil machen und
hatte Schwierigkeiten mit den diversen *.h Files.
Ich habe das jetzt entsprechend nach geflickt. Der Compiler fügt jetzt
ein NOP (gekapselt in einer Funktion) für jedes Syncdelay ein
Ich verwende nicht das fw.c von Cypress, sondern halte allen Code in
meinem kleinen Stückchen C.
Kann das die Quelle des Übels sein? Das irgendwelche notwendigen
Initialisierungen schlichtweg fehlen?
Unten habe ich mal alle Initialisierungen hinkopiert.
Der Endpoint sollte 4fach gepuffert sein (hat auch eine kleine
Verbesserung gebracht).
Ich lasse auch in der Hauptschleife des Programms einen Port zappeln.
Ergebnis: Alle 4us wird die Sendefunktion aufgerufen. das sollte
eigendlich reichen.
Gruß Ekkehard
Ich weiß nicht, ob statt dem Syncdelay ein nop ausreicht, vor allem bei
48MHz CPU-Takt. Schau mal lieber in das Framework, da steht die
Berechnung drin, wie lange das Syncdelay sein muss, damit das alles
klappt. Vielleicht verhaspelt der sich schlichtweg.
Mit dem SDCC hatte ich auch mal probiert, das war mir aber zu sehr
Gefrickel....bisher reichen die 4k vom Keil.
Hey Leute! Hatte auch mal probiert im Bulk 512 eine ordentliche
Datenrate zu fahren (habe hierzu eine Beispielkonsole von Cypress incl.
entsprechender Firmware benutzt). Der 8051 schaufelte mit den
Autopointern einfach EP OUT zu EP IN...die Rate war weit unter dem was
ich erwartet hatte.
Ein NOP reicht AFAIR nicht aus, da musst du nochmal im Datenblatt lesen
wie das Timing zustande kommt.
Christian R.:
Du meintest, dass du selbst Probleme mit dem Slave FIFO hast aufgrund
des "kranken Timings". Habe heute begonnen einen CPLD anzuflanschen und
das Timing beaugapfelt - mir sind keine Besonderheiten aufgefallen. Was
meintest du genau? Mit was ließt du deine FIFO's aus? Deine Datenrate
war im Slavemode auch eher niedrig, wenn ich mich recht entsinne im
Bulk. Hast du mal Isochron probiert?
Also wir haben einen Virtex IV FPGA dran, das Programm da drauf macht
ein Kollege. Das worüber er sich am meisten beschwert hat, ist das
Timing zwischen WCLK und WE. Da hat man nur knapp 3ns nach der
Taktflanke Zeit, wenn man das alles ordentlich synchron macht.
Desweiteren war wohl im Datenlatt etwas undurchsichtig beschrieben, dass
man WE und die FIFOARRD nicht gleichzeitig anlegen darf. Aber da ist
noch Optimierungspotenzial. Da wir keine dauerhafte Übertragung haben,
ist die Geschwindigkeit schwer auszurechnen, werd mir aber mal
anschauen, wieviele Pakete der in einen Microframe packt, kann man sehr
gut mit dem Oszi beobachten.
Außerdem hatten wir nur 2-fach Buffer.
Isochron und Interrupt kommt nicht in Frage, es darf nix verloren gehen.
Moin Christian,
ach so ist das. Hab nochmal die 3ns beäugt - unkritsch, das macht man ja
nur einmal pro Übertragung am Anfang, da darfs auch ein Takt mehr
brauchen. ;^)
Die zweite Sache ist wirklich etwas schwammig dargestellt, danke für den
Tip!
Najaaaa...so unkritisch ist das nicht. Mit unserem Virtex war das halt
recht knapp hinzubekommen und dann hat der cypress ab und zu mal ein
Wort verschluckt....aber die Leute beim GNURadio kriegen auch 33MB/s in
den PC, das sollte mit Quad-Buffer und sauberem timing zu schaffen sein
(Steht ja auch in der Streaming-Appnote)....müssen wir mal Modelsim
anwerfen ;)
Hallo,
ich habe jetzt mal mit dem Keil-Compiler das bulkloop example angepasst
und kompiliert. (d.h. ich habe in dscr.a51 die VID/PID auf original
Cypress umgestellt, und in TD_Poll den o.a. Puffer lostreter eingebaut).
Das Ergebnis ist aber ernüchternd, d.h. mehr al 11MB/s kommt aus dem
Endpunkt nicht raus.
@Christian: Wenn ich richtig gelesen habe benutzt du LibUSB Win32. Das
scheint mir jetzt der einzige Unterschied zu sein. Wie kriege ich denn
da mein HEX file in den cypress geladen?
Gruß Ekkehard
Mit der CyAPI ist es bei mir genauso 38MB/s. Hab dazu das BulkLoop
Programm bissl angepasst. Ich nutze die nur, weil die übersichtlicher
ist als die verwurstete CyAPI.
Da muss an deinem USB Controller was sein, oder am OS oder
sonstwo....keine Ahnung. Was macht denn dein Programm noch mit den
daten? Vielleicht kann es gar nicht so schnell neue Daten anfordern? Ich
hab die 38MB/s momentan ohne jegliche Datenbehandlung im Thread.
Wie groß sind denn die Blöcke die du im Thread ausliest?
Ich mache mit den Daten fast nichts. Ich prüfe ob der Einbytezähler
artig von alle 512 Bytes eins rauf geht.
Wenn ich die Blockgröße auf z.B. 20MB setze, kehrt die Lesefunktion erst
nach 2 Sekunden zurück. Es passiert -in diesem Fall- also gar nichts mit
den Daten.
Ich habe das Programm auf verschiedenen Rechnern, laufen lassen, es
kommt im wesentlichen überall das Selbe raus.
Gruß Ekkehard
Danke, konnte kompilieren und komme auf ähnliche Ergebnisse (so knapp
15MB/s). (Bei den o.a. 10MB/s hatte ich noch den USB-Hub unterm Tisch
dazwischen :-() Wenn ich zwei Endpunkte nehme komme ich auf 2*11MB/s.
Aber wie geht das mit Deinen 38MB/s?
Gruß Ekkehard
Einfach, indem ich den Endpunkt nur scharf mache, keine Daten
reinkopiere. Das kann der 8051 da drauf doch eh nicht so schnell. Der
hat ja nur 48MHz, wie soll der da so schnell neue Daten kopieren?
Wenn, dann müssen die schon von außen angeliefert werden, durch FPGA
oder ähnliches.
Ich weiß ja nicht, was in deiner TD_Poll() jetzt noch alles drin ist,
aber mit dem, was ich gestern 14.41 gepostet hab, kam ich ja auch auf
die 38MB/s. Wahrscheinlich is dein EP doch noch bissl anders
konfiguriert....
Ich habe nochmal ein bischen im Firmwarecode gefeilt. Wenn ich die
Endpunkte 2, 4, 6 und 8 gleichzeitig verwende komme ich so auf
32-34MB/s.
Ich habe alle Einstellungen für die Endpunkte überprüft, also was
richtig Falsches habe ich nicht entdecken können.
Da ich als absolutes Minimum 32MB/s benötige, wiege ich mich jetzt mal
in Sicherheit - bis meine Platine mit der Logik da ist :-)
Wie Du aus einem Endpunkt die 38MB/s rausbringst ist mir ein echtes
Rätsel.
Ich würde gerne - als Alternative - das mal mal mit isochronem Transfer
vergleichen. Da habe ich aber so auf die Schnelle nichts zum laufen
bekommen.
Im Prinzip muss ich doch nur die Endpunkte im Descriptor ändern und die
Register für den Enpunkt konfigurieren. Der Rest - Puffer "armieren" und
in der PC software auslesen sollte doch das Gleiche bleiben. Oder habe
ich noch was vergessen?
Schönen dritten Advent!
Gruß Ekkehard
Letzte Meldung ;-)
CCyUSBEndPoint->SetXferSize(65536) ist der Turbo-Knopf den man drücken
muss!
Damit werden aus den 15-16MB/s aus einem einzelnen Endpunkt mal eben
30MB/s. Wenn ich zwei Endpunkte verwende, komme ich so auf 39MB/s. Das
ist mit entsprechender Reserve das was ich brauche.
Lieber Christian, nochmals vielen Dank für Deine Hilfe!!
Gruß Ekkehard
Achso? Ich bekomm das zwar auch so hin, aber gut. Sehr interessant.
Naja, man muss dem Treiber bloß verklickern, dass der die Microframes
vollpackt, dann geht das. Wahrscheinlich macht das die LibUSB von
alleine entsprechend. Wichtig ist halt die mehrfache Bufferung, wenn du
von außen Daten in den Chip schaufeln willst. Leider können wir das erst
nächstes Jahr richtig optimieren bei uns, weil der Kollege schon Urlaub
macht jetzt. Ich bin aber guter Dinge, dass wir min 32MB/s schaffen
werden. Das würde reichen für uns.
Hallo,
ist ja wieder ein wenig Zeit vergangen...
Hier noch ein Update.
Ich habe jetzt endlich eine laufende Hardware, die mir Daten extern in
das FIFO reinschaufelt. Die IFCLK läuft mit ca. 20MHz, und in 3 von 4
Zyklen schreibe ich jeweils ein 16Bit Wort in das FIFO (im 4. Zyklus
gehen gelegendlich Daten in einen anderen Endpunkt). Konfiguration: EP2
(3*1024), EP8 (2*512).
Unabhängig von der Datenrate interessiert mich z.Zt. wie ich einen
großen Block zusammenhängender Daten eintakten kann (d.h. ohne das das
FIFO Full Flag kommt).
Ich habe einen kurzen Versuch mit LibUSB (Win32) gemacht, aber nur
einige ms hinbekommen. Mit cyUSB/cyAPI komme ich jetzt so auf 100ms wenn
ich die o.a. SetXferSize auf 3MByte (!) setze.
Leider kann keinen größeren Wert eintragen, dann legt sich der Treiber
auf die Nase (z.T. mit Blue-Screen).
Gruß Ekkehard
3*1024 hört sich irgendwie nach isochron an.....also direkt
zusammenhängende Blöcke gehn mit USB überhaupt nicht. Man kann nur
versuchen, das zeug schnell genug abzuholen, dann kann man den FIFO bei
4xBuffer schnell vollballern. Aber zwischendurch muss der ja auch mal
abliefern. So ganz haben wir´s auch noch nicht raus, wie man das am
effektivsten macht. Am sinnvollsten scheint mir aber Bulk, 4x Buffer und
48MHz IFCLOCK aus den FX2 nach außen, den über einen DCIM im FPGA
verdoppeln, dann lässt sich das Timing leichter einhalten. Ist aber
immer nocht nicht fertig bei uns....viel zu viel wichtigeres....
Hallo Christian,
ich hole die Daten mit Bulk-Transfer, d.h. ich rufe die Lesefunktion mit
20MB zu lesenden Daten auf (dauert so 750ms) und schaue mir dann den
Inhalt an.
Ich habe mir das Fifo-Voll-Flag mit dem Oszilloskop angesehen, und sehe
eben das dass Fifo gelegendlich überläuft.
Da ich zwei Datenquellen habe muss ich zwei Endpunkte benutzen. Das
beste Ergebnis erhalte ich halt mit dem 3*1024 EP2.
Ich erzeuge mir meinen Takt selber und habe im FPGA einen Zähler der
alle Zustände auskodiert. Das mit dem Timing war eigendlich kein Problem
(hat so zimlich aus Anhieb geklappt).
Gruß Ekkehard
na und wo ist da das Problem? Du musst halt das Full-Flag in deiner
State-Machine berücksichtigen, die darf natürlich erst neue Daten
reinschreiben, wenn das FF nicht gesetzt ist. Und dann kann auch nix
passieren.
BULK Endpunkte haben aber 512Byte Paketgröße und können max.4 -fach
gepuffert werden. Wo deine 3*1024 herkommen, weiß ich nicht.
Na das ist ja sehr merkwürdig. Stimmt es steht da irgendwo mit den
512Bytes für Bulktransfer. Ich habe allerdings die Konfiguration aus dem
FX2_TRM.pdf genommen die in "Figure 1-15. FX2 Endpoint Buffers" zweites
Bild von rechts angegeben ist. EP2 = 3*1024, EP8 = 2*512. Ich habe die
maximale Puffer-Größe in die DescriptorTable eingetragen und alles
spielt. Es kommen auch 3072 Bytes aus dem EP2 im Bulk mode raus, und ich
hätte mich gewundert wenn es nur 1536 gewesen wären.
FIFO Voll ist bei mir "Höchststrafe" weil ich möglichst viele Daten "am
Stück" lesen muss (AD-Wandler), es gibt da keine weiteren Puffer, die
Daten sind dann einfach weg.
Wenn das FIFO wieder "nicht Voll" ist schreibe ich einige
Synchronisationsdaten und beginne mit einer neuen Sequenz.
Mein Problem ist, das ich erwartet habe bei ca. 30MB/s Daten zu lesen
ohne das das FIFO überläuft. Das hängt aber offensichtlich stark vom
Host-Rechner ab. In meinem Fall von dem Parameter der Funktion
SetXferSize, die sich nicht über 3MB erhöhen lässt.
Jo klar, USB ist ja auch derart niedrig priorisiert, das ist vom
Host-Rechner und dessen Belastung abhängig. Ich hab hier zwischen 17
Mbyte/s und 40MByte/s alles schon gehabt, gleiche Konfig jeweils. Ist
natürlich klar, dass du dann Daten verlierst, wenn du eine solche Konfig
aufbaust, über die Sinnlosigkeit eines derartigen Samplig hab ich mich
ja schon paar Mal ausgelassen. Das klappt nur sinnvoll, wenn die
Sampling-Rate ziemlich weit unter der USB Geschwindigkeit liegt. Da kann
man den USB-FIFO benutzen. Der ist ja im Bulk-Modus maximal 2 kByte
groß.
Für deine Anwendung solltest du isochrones Streaming oder
Interrupt-Transfer benutzen. Da kannst du garantiert alle 125µs einen
Datenblock abholen. Bei isochron kommst du maximal auf 24MB/s, das ist
aber dann garantierte Bandbreite. Ist sicher sinnvoller für solche
Sachen....ist ja auch für Audio und Video gedacht, wo die Bandbreite
stimmen muss, aber eben mal ein paar Frames fehlen dürfen.
Sinnlosigkeit hin oder her, es funktioniert sehr gut :-)
Nach längerer Suche bei Microsoft hat sich herausgestellt, dass im
Bulk-Modus dieser Transfer Puffer auf maximal 3344KByte gesetzt werden
kann (4GB im IsoC). Im Bulk-Modus kann demnach maximal 3344KByte am
Stück übertragen werden. Dann gibts ein "Päuschen" und das FIFO läuft
über.
Isochron ist mir die Datenrate zu klein, zwei Endpunkte zu kombinieren
z.Zt. der Aufwand zu groß.
Gruß Ekkehard