Forum: Mikrocontroller und Digitale Elektronik Unerklärliches Verhalten von CY7C68013A (USB-Controller)?!


von John K. (juliusk)


Lesenswert?

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;

von Christian R. (supachris)


Lesenswert?

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.

von Benjamin S. (recycler)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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.

von John K. (juliusk)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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.

von Benjamin S. (recycler)


Lesenswert?

Ja, die Puffer sind bei Highspeed und Bulk 512 Byte groß,
bei Isochron max 3x1024 Byte.
Hoffe du kommst weiter
Benjamin

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.