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
1 | void sendbulk(void) |
2 | {
|
3 | if ((EP2468STAT & bmEP6FULL) != bmEP6FULL) { |
4 | EP6FIFOBUF[0] = buffer6ctr; |
5 | EP6BCH = 0x02; |
6 | EP6BCL = 0x00; |
7 | buffer6ctr++; |
8 | if (buffer6ctr & 0x01) { |
9 | IOA |= 0x02; |
10 | } else { |
11 | IOA &= ~0x02; |
12 | }
|
13 | }
|
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
1 | void init_fx2(void) |
2 | {
|
3 | CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD48MHZ); // & ~(0x18) | (0x10) 48MHz CPU-Clock |
4 | |
5 | // set the slave FIFO interface to 48MHz
|
6 | IFCONFIG |= 0x40; |
7 | |
8 | EP1OUTBC = 0x04; // Writing to EP1OUTBC rearms for an out Transfer |
9 | EP1OUTCS &= (0xff - bmEPSTALL); |
10 | OEB = 0xff; // Port B wird verwendet - auf Ausgabe einstellen |
11 | IOB = 0x00; // Port B of 0 vorbelegen |
12 | OEA = 0xFF; // Port A wird verwendet - auf Ausgabe einstellen |
13 | IOA = 0x10; // Port A of 0 vorbelegen |
14 | |
15 | EP6CFG &= ~0x03;//Quadbuffering |
16 | // EP6ISOINPKTS = 0x03; //3 packets per microframe
|
17 | // EP8CFG &= ~0x03;//Quadbuffering
|
18 | |
19 | |
20 | EP6FIFOBUF[1] = '6'; |
21 | EP6FIFOBUF[2] = 'B'; |
22 | EP6FIFOBUF[3] = 'C'; |
23 | EP6FIFOBUF[509] = 'X'; |
24 | EP6FIFOBUF[510] = 'Y'; |
25 | EP6FIFOBUF[511] = 'Z'; |
26 | |
27 | EP8FIFOBUF[1] = '8'; |
28 | EP8FIFOBUF[2] = 'B'; |
29 | EP8FIFOBUF[3] = 'C'; |
30 | EP8FIFOBUF[509] = 'X'; |
31 | EP8FIFOBUF[510] = 'Y'; |
32 | EP8FIFOBUF[511] = 'Z'; |
33 | |
34 | }
|
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
Sehr komisch. Kannst ja mal das iic File hier anhängen, da schau ich mal nach.
Ok, ist dabei. Sendet im EP6, toggelt Port A Pin 1. VID 04B4, PID 8613 Gruß Ekkehard
Damit komme ich bei mir auf knapp 16MByte/s lesen (ab 4k Blocklänge). Ich hab mal das modifizierte CyAPI Programm mit Screenshots angehängt.
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
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.