Forum: PC-Programmierung Cypress 68013, cyAPI


von Ekkehard D. (ekkehard)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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.

von Ekkehard D. (ekkehard)


Lesenswert?

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
}

von Christian R. (supachris)


Lesenswert?

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()...

von Christian R. (supachris)


Lesenswert?

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.

von Ekkehard D. (ekkehard)


Lesenswert?

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
}

von Christian R. (supachris)


Lesenswert?

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.

von T. H. (pumpkin) Benutzerseite


Lesenswert?

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?

von Christian R. (supachris)


Lesenswert?

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.

von T. H. (pumpkin) Benutzerseite


Lesenswert?

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!

von Christian R. (supachris)


Lesenswert?

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 ;)

von Ekkehard D. (ekkehard)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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?

von Ekkehard D. (ekkehard)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

Sehr komisch. Kannst ja mal das iic File hier anhängen, da schau ich mal 
nach.

von Ekkehard D. (ekkehard)


Angehängte Dateien:

Lesenswert?

Ok, ist dabei. Sendet im EP6, toggelt Port A Pin 1. VID 04B4, PID 8613
Gruß Ekkehard

von Christian R. (supachris)


Angehängte Dateien:

Lesenswert?

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.

von Ekkehard D. (ekkehard)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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....

von Ekkehard D. (ekkehard)


Lesenswert?

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

von Ekkehard D. (ekkehard)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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.

von Ekkehard D. (ekkehard)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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....

von Ekkehard D. (ekkehard)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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.

von Ekkehard D. (ekkehard)


Lesenswert?

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.

von Christian R. (supachris)


Lesenswert?

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.

von Ekkehard D. (ekkehard)


Lesenswert?

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
Noch kein Account? Hier anmelden.