Hallo,
ich bin gerade dabei, den CY7C68013A USB-Controller (die 56-Pin
Variante) von Cypress zusammen mit einem FPGA in Betrieb zu nehmen. Ich
arbeite im Bulk-Modus und verwende Puffergrößen von 4 mal 512 Byte (also
alle Endpoints (2, 4, 6 und 8) werden benutzt).
Die Datenübertragung vom PC zum FPGA funktioniert auch schon
einwandfrei, nun mache ich allerdings eine äußerst merkwürdige
Beobachtung beim Übertragen von Daten vom FPGA zum PC: Pakete mit einer
Größe bis 63 Byte werden wie erwartet übertragen. Beim Versuch größere
Pakete zu übertragen, wird aber beim Lesen vom PC der Wert 0 für die
Größe des übertragenen Paketes angegeben und die Daten können nicht
korrekt ausgegeben werden.
Ganz gleich, welche Einstellungen ich schon geändert habe (z.B.
Busbreite, Auto-Commit, Puffergrößen...), verändert sich dieses
Verhalten des Controllers nicht und es können nur Pakete mit einer Größe
unter 64 Byte übertragen werden. Ich würde gerne nachvollziehen, woher
dieser markante Wert stammt.
Seit einiger Zeit zerbreche ich mir schon den Kopf, von was dieser 64er
Wert abhängt und wie man ihn ändern (-> 512) könnte. Habt ihr schon
einmal ähnliche Beobachtungen gemacht oder vielleicht sogar einen
Verdacht, woran es liegen könnte?
Es wird übrigens noch viel merkwürdiger: Wenn man am Anfang die gleiche
Konfiguration (siehe unten) lädt, die aber statt EP6 den EP8 neu
konfiguriert (vgl. „###“-Markierung im Quelltext), dann einmal ein Paket
(< 64 Bytes) überträgt, anschließend ganz kurz Reset aktiviert, danach
die eigentliche Konfiguration lädt und schließlich noch mal ein Paket (<
64 Bytes) überträgt, so funktioniert auch die Übertragung von größeren
Paketen (z.B. 512 Bytes) tadellos. Sobald man aber irgendetwas an diesem
Verfahren verändert, gibt es wieder den bekannten Fehler.
Ich verfolge schon seit längerer Zeit die anderen Beiträge zum Thema
USB-Übertragung im Forum und hoffe, dass jemand von den erfahreneren
Experten meine Beobachtung zu deuten weiß. Ich erwarte keinesfalls, dass
hier jemand die Arbeit für mich macht ;-) Über jeden kleinen Hinweis
würde ich mich sehr freuen, vielleicht kommt euch das ja bekannt vor.
Vielen Dank für eure Mühe,
Julius
Hier ist ein Ausschnitt (nur der Initialisierungs-Teil, sonst wird
außerhalb von „fw.c“ nichts mehr gemacht) des Quelltextes:
______________________________________________________________
// set the CPU clock to 48MHz
CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1) ;
// set the slave FIFO interface to 48MHz
IFCONFIG |= 0x40;
//IFCONFIG = 0xc3;
SYNCDELAY;
// default: all endpoints have their VALID bit set
// default: TYPE1 = 1 and TYPE0 = 0 --> BULK
// default: EP2 and EP4 DIR bits are 0 (OUT direction)
// default: EP6 and EP8 DIR bits are 1 (IN direction)
// default: EP2, EP4, EP6, and EP8 are double buffered
// we are just using the default values, yes this is not necessary...
EP1OUTCFG = 0xA0;
EP1INCFG = 0xA0;
SYNCDELAY; // see TRM section 15.14
EP2CFG = 0xA2;
SYNCDELAY;
EP4CFG = 0xA0;
SYNCDELAY;
EP6CFG = 0xE2;
SYNCDELAY;
EP8CFG = 0xE0;
// out endpoints do not come up armed
// since the defaults are double buffered we must write dummy byte
counts twice
SYNCDELAY;
EP2BCL = 0x80; // arm EP2OUT by writing byte count
w/skip.
SYNCDELAY;
EP2BCL = 0x80;
SYNCDELAY;
EP4BCL = 0x80; // arm EP4OUT by writing byte count
w/skip.
SYNCDELAY;
EP4BCL = 0x80;
// enable dual autopointer feature
AUTOPTRSETUP |= 0x01;
PINFLAGSAB = 0xE4;SYNCDELAY; // 10.07.08 send flags to pins, FLAGA=EP2PF
!
PINFLAGSCD = 0xF5; SYNCDELAY;// 10.07.08 send flags to pins, FLAGC=EP4PF
!
EP2FIFOPFH = 0x00;SYNCDELAY; // Configure programmable flags A/C
EP2FIFOPFL = 0x01;SYNCDELAY;
EP4FIFOPFH = 0x00;SYNCDELAY;
EP4FIFOPFL = 0x01;SYNCDELAY;
Rwuen = TRUE; // Enable remote-wakeup
IFCONFIG = 0xc3; SYNCDELAY; // internal clock set 48MHz, fifo slave +
external master
REVCTL=0x03; SYNCDELAY;
// auto in
REVCTL = 0x03; // REVCTL.0 and REVCTL.1 set to 1
SYNCDELAY;
//##########################
//########################## !!! In anderem (erstem) Hexfile bezieht
sich dieser markierte Teil statt auf EP6 auf EP8.
EP6CFG = 0xE0; // EP8 is DIR=IN, TYPE=BULK
SYNCDELAY;
FIFORESET = 0x80; // Reset the FIFO
SYNCDELAY;
FIFORESET = 0x08;
SYNCDELAY;
FIFORESET = 0x00;
SYNCDELAY;
EP6FIFOCFG = 0x0C; // EP8 is AUTOOUT=0, AUTOIN=1, ZEROLEN=1, WORDWIDE=0
SYNCDELAY;
EP6AUTOINLENH = 0x02; // Auto-commit 512-byte packets
SYNCDELAY;
EP6AUTOINLENL = 0x00;
//########################## !!!
//##########################
// auto out
REVCTL = 0x03; // REVCTL.0 and REVCTL.1 to set to 1
SYNCDELAY;
EP2CFG = 0xA2; // EP2 is DIR=OUT, TYPE=BULK, SIZE=512, BUF=2x
SYNCDELAY;
FIFORESET = 0x80; // Reset the FIFO
SYNCDELAY;
FIFORESET = 0x02;
SYNCDELAY;
FIFORESET = 0x00;
SYNCDELAY;
OUTPKTEND = 0x82; // Arm both EP2 buffers to “prime the pump”
SYNCDELAY;
OUTPKTEND = 0x82;
SYNCDELAY;
EP2FIFOCFG = 0x10; // EP2 is AUTOOUT=1, AUTOIN=0, ZEROLEN=0, WORDWIDE=0
EP2FIFOCFG = 0x19; //0x1D; //0xFF; // Auf diese 4 Zeilen reagiert
SLWR-Funktion sensibel: Als ob PKTEND aktiv wäre, falls nicht bestimmtes
Bit 0 oder default...??..??
EP4FIFOCFG = 0x19; //0x1D; //0xFF;
EP6FIFOCFG = 0x19; //0x1D; //0xFF;
EP8FIFOCFG = 0x19; //0x1D; //0xFF;
Das klingt ganz stark, als würde sich entweder der FX2 nur als FullSpeed
Device melden, oder aber der Host-Controller bzw. Hub kann nur
Full-Speed. Dann ist die Paketgröße nämlich maximal 64 Byte.
Du kannst übrigens auch einen einzigen EP 4-fach puffern, da sparst du
dir das Umschalten zwischen den Adressen. So machen wir das hier.
Was sagt denn die CyConsole? Hat der wirklich 512 Byte Paketgröße?
Hast du in den EP-Deskriptoren auch die 512 Byte eingetragen?
Irgendwo hier hatte ich mal einen getesteten Quellcode für den FX2 am
FPGA hochgeladen, musst du dir mal anschauen.
Edit: Lass mal das REVCTL Register so wie es ist, das hat bei mir
Probleme gemacht.
Hallo,
könntest du deinen Descriptor posten, der wäre noch interessant.
Im Fullspeedmodus (12Mbit/s) dürfen laut Spec nur 64Byte übertragen
werden, nur im Highspeedmodus 512Byte bzw. die FIFO-Größe darf so groß
sein.
Benjamin
Willst du eigentlich alle EP an das Slave FIFO Interface führen? Wenn
ja, wieso schreibst du dann eine Bytelänge in EP2BCL und EP4BCL? UNd
wieso überhaupt bei den OUT Endpints? Die Länge gibts du doch am Host
vor. Wenn dann bräuchte man diese BCL und BCH Register, wenn man von der
8051CPU aus Pakete in den IN Endpoint stellen will. Aber bei Slave FIFO
hast du an den Registern gar nix rum zu murksen, das läuft völlig
autonom am 8051 vorbei.
Du wolltest das TRM nochmal genauer studieren.
Hallo,
ihr habt Recht, die Puffer kann man hier sicher noch sinnvoller
aufteilen. CyConsole sagt auch, es sind im Moment noch 512 Byte.
Wahrscheinlich werde ich 2x1024 Byte auf jeder Seite verwenden, um
gleichzeitig in einen Endpoint lesen und schreiben zu können.
Danke, Christian und Benjamin! Stimmt tatsächlich, der USB-Controller
war nur auf Full-Speed eingestellt. Habe ihn nun gleich nach der
Initialisierung auf High-Speed gesetzt und die Übertragung von größeren
Paketen funktioniert jetzt!
Für alle mit einem ähnlichen Problem, die das zu einem späteren
Zeitpunkt lesen: Seite 56 im Manual hat genauere Informationen und
dieser Teil hilft beim Umschalten:
pConfigDscr = pHighSpeedConfigDscr;
((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR;
pOtherConfigDscr = pHighSpeedConfigDscr;
((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR;
EZUSB_IRQ_CLEAR();
USBIRQ = bmURES; // Clear URES IRQ
Aber zur Sicherheit nicht den USB-Reset-Teil auf High-Speed einstellen,
das kann zu noch viel größeren Problemen führen.
Nein, für das Interface brauche ich nicht alle Endpoints, nur EP2 und
EP6... das habe ich bei dieser Version noch nicht übernommen.
OK, BCL und BHC sind dann wohl völlig überflüssig. Da lässt sich ja
ohnehin noch sehr viel kürzen, weil vieles davon default-Werte sind.
Vielen lieben Dank für eure Hilfe! Das hätte ich selbst nicht so schnell
herausgefunden ;-)
Julius
1024 Byte bei BULK transfer klappt aber nicht. Man kann es zwar
einstellen, aber es funktioniert dann nicht gescheit. Außerdem ist dann
irgendwann der RAM alle, ich glaub 4x 512 und 2x 512 Byte klappt gerade
noch so. Wir haben hier auch für den OUT Endpoint doppelt-gepuffert und
für den IN-Endpoint 4-fach gepuffert. Der Upstream ist bei uns
wesentlich mehr.
Hier hatte ich mal den komplett getesteten Code gepostet, kannst du
verwenden: Beitrag "Re: USB-Port auf Spartan 3E für Anwendung nutzen"
Die fw.c sollte man tunlichst nur ändern, wenn man ganz genau weiß, was
man macht. Um diese FullSpeed/HighSpeed Geschichte kümmert der sich bei
den Code-Beispielen von alleine.