Servus,
ich konfiguriere ein FPGA über eine USB/JTAG-Verbindung mit einem
FT2232H. Dazu verwende ich den ftd2xx-Treiber und die entsprechende
lib/API. Meine Software ist so implementiert, dass ich die
Schreibzugriffe puffere und als 4K-Blöcke an die FT_WRITE()-Funktion
weiter gebe. Dabei kam es sporadisch immer wieder mal vor, dass dass der
Update-Vorgang fehlschlägt, also das FPGA nicht zum Leben erwacht. Diese
lässt sich verhindern, wenn ich nach jedem FT_WRITE()-Aufruf ein
Sleep(1) einfüge, was mich zu der Vermutung führt, dass da irgendein
Buffer überläuft.
Eigentlich würde ich aber erwarten, dass wenn ich schon vom Hersteller
eine Lib bekomme, diese sich selbst um das Timing kümmert. Und im
User-Manual von FTDI finde ich auch nirgendwo die Vorgabe irgendwelcher
Wartezeiten. Auf eine entsprechende Anfrage an den Support kam keine
Antwort.
Weiß jemand mehr über das Thema?
Hallo,
passt ja gerade noch so :D
Was passiert wenn du in 1K Blöcken schreibst?
Evt. könnte es auch ein Timingproblem des FPGA's sein, das irgendwo
nicht mitkommt. Kannst du irgendwo eine Frequenz oder Bitabstand
angeben?
Vill. gibt es irgendwo versteckte Defines mit der Buffergröße?
4K ist eben genau die Größe des Sendepuffers auf dem Chip. Wenn ich die
JTAG-Frequenz runterdrehe, tritt der Fehler tendenziell häufiger auf,
deshalb auch meine Vermutung mit dem Overflow.
Das mit den 1K Blöcken müsste ich mal ausprobieren...
Ich glaube auch, dass du für das FPGA zu schnell bist. Die ftd2xx
schickt im Normalfall die komplette "Wurscht", also die kompletten 4k
Daten raus, sobald du das FT_Write abgefeuert hast. Auch kehrt sie erst
zurück, wenn alles gesendet ist, so hab ich das zumindest in
Errinnerung.
Somit gibt dein Sleep dem FPGA mehr Zeit und nicht nur der FTDI Lib.
Aber iM DB des FPGA sollte hier schon was zu finden sein...
Das glaube ich eben nicht. Gerade wenn ich den JTAG-Takt kleiner mache,
die Daten also langsamer ins FPGA schiebe, tritt der Fehler ja häufiger
auf.
Die FT_Write mag ja erst zurückkehren, wenn die Daten per USB
abgeschickt sind, die Frage ist vielmehr ob sie auch sicherstellt, dass
im Sendebuffer des Chips auch Platz dafür ist.
Mein Buffer is 4096 Byte groß und beinhaltet sowohl meine Daten als auch
die FT-MPSSE-Kommandos.
Das FPGA ist mal ganz sicher nicht zu langsam, denn die können meist
33MHz und mehr als JTAG Takt. UNd wenn es bei neidrigerem JTAG Takt
öfter auftritt, deutet das stark auf einen Pufferüberlauf und
fehlerhaftes Handshake hin.
Welches Kommando verwendest du denn? Irgendwie kommt mir 4096 gesamt
komisch vor, wenn da die MPSSE auch mit dabei sind. Ich würde eher auf
4099 kommen, Kommando, LengthL, LengthH, Daten (4096).
Evtl. hilft es dir auch, wenn du ein 0x87 Kommando ans Ende stellst.
Ich hab mal eine Boundary Scan Lib auf Basis der ftd2xx geschrieben und
da hab ich tausende Bytes in kürzester Zeit geschrieben und gelesen und
konnte solche Probleme nicht feststellen. Ich behaupte sogar dass die
FT_Write erst zurück kehrt, wenn die Daten tatsächlich raus gegangen
sind.
Alternativ könntest du natürlich auch ein Schreib/Lese Kommando nehmen,
dann kehrt er 100% erst zurück, sobald die Daten durch geschoben sind...
Gruß MB
Günter R. schrieb:> Welches Kommando verwendest du denn? Irgendwie kommt mir 4096> gesamt> komisch vor, wenn da die MPSSE auch mit dabei sind. Ich würde eher auf> 4099 kommen, Kommando, LengthL, LengthH, Daten (4096).
Versteh ich nicht. Ich kopiere halt die Daten in den Puffer, und sobald
er voll ist oder ich explizit ein flush() aufrufe, wird der Inhalt
abgeschickt. Was hat das mit den verwendeten Kommandos zu tun?
> Ich behaupte sogar dass die> FT_Write erst zurück kehrt, wenn die Daten tatsächlich raus gegangen> sind.
Du meinst auf dem JTAG raus gegangen? Das kann ich mir nicht vorstellen.
Damit würde mann u.U. ja Geschwindigkeit verschenken.
> Alternativ könntest du natürlich auch ein Schreib/Lese Kommando nehmen,> dann kehrt er 100% erst zurück, sobald die Daten durch geschoben sind...
Das dürfte den ganzen Vorgang aber auch deutlich bremsen.
Mit Kommandos meinte ich z.B. CMD_DATABYTES2TDI. Somit hat dein Buffer
(der der wirklich im flushBuffer() gesendet wird) immer mehr als 4096
Bytes. Du schickst das Zeug aber schon sobald Gesamt > 4096 ist und das
ist der Bock, weil dir immer einige Daten fehlen.
Schau mal in die shiftTdiData() Methode und dann siehst du sofort, dass
immer 3 Bytes pro Aufruf dazu kommen. Den Wert CMD_DATABYTES2TDI kannst
du in der MPSSE Doku mal nachschlagen und dann siehst du schon was ich
meine...
Ich würde die Daten extern auf 4096Byte Päckchen umbauen und dann in
einem Rutsch absenden, dann ist die Performance bestimmt am besten.
Alterntaiv könnte auch ein Umbau was bringen, in etwa so (ungetetstet):
EDIT: trBuffer muss natürlich groß genug sein!
Ich hab das Gefühl wir reden aneinander vorbei :-)
Günter R. schrieb:> Mit Kommandos meinte ich z.B. CMD_DATABYTES2TDI. Somit hat dein Buffer> (der der wirklich im flushBuffer() gesendet wird) immer mehr als 4096> Bytes. Du schickst das Zeug aber schon sobald Gesamt > 4096 ist und das> ist der Bock, weil dir immer einige Daten fehlen.> Schau mal in die shiftTdiData() Methode und dann siehst du sofort, dass> immer 3 Bytes pro Aufruf dazu kommen. Den Wert CMD_DATABYTES2TDI kannst> du in der MPSSE Doku mal nachschlagen und dann siehst du schon was ich> meine...
Dass da Kommandos hinzugefügt werden, ist mir schon klar. Aber aus Sicht
der writeBuffer()-Methode ist das doch völlig egal. Die bekommt einen
beliebig großen anonymen Datenblock übergeben und kopiert diesen
byteweise in den 4K-Transmit puffer. Immer wenn dieser voll ist, wird
ein flush aufgerufen, der den puffer leert. Anschließend wird er wieder
befüllt usw. Das geht so lange, bis alle Daten kopiert sind.
Was in meinem codeschnipsel nicht zu sehen ist - sollte der
Gesamttransfer (Daten+Kommandos) nicht 4K aligned sein, werden die am
Ende verbleibenden Daten (plus die nachfolgenden TMS-shift Kommandos)
beim nächsten RUNTEST-Kommando abgeschickt.
Wo da jetzt Daten fehlen sollen, sehe ich nicht. Wenn das so wäre,
dürfte das Ganze ja, unabhängig vom Sleep(), gar nicht funktionieren.
Kann schon sein, dass es aneinander vorbei geht gg
ABER ich sehe das nicht so. Nehmen wir deinen Code und spielen mal
durch.
Buffer hat 4090 Bytes. Nun schiebst du zB nochmal 8Byte nach.
Der Buffer kriegt 1 Byte Kommand, 2 Byte Länge und 8 Byte Daten, doch
nach dem 3. Byte wird die FT_Write aufgerufen und die Daten geschickt
(ich denke auch auf der HW) Jetzt sind noch 5 Byte übrig die wieder in
den Buffer kommen und ob der Treiber jetzt noch weiß, dass es Daten aus
dem Kommando von vorhin sind, wage ich zu bezweifeln. Irgendwo her
müssen ja deine Probleme kommen und das wääre für mich eine Erklärung.
Bei meiner JTAG Lib hab ich das alles immer intern vorbereitet und erst
danach sauber an die FT Lib übergeben und das hat dann auch geklappt.
Ich behaupte wenn du die Daten selber bufferst bis du 4k beisammen hast
und in einem Rutsch übergibst, rennt die Geschichte. So viel Aufwand ist
das sicher nicht...
Also dann,
Ok, jetzt habe ich zumindest verstanden was Du mir sagen willst :-)
ABER ich sehe das wiederum anders. Der Treiber weiß doch überhaupt
nichts von irgendwelchen Kommandos, oder sollte es zumindest nicht.
Seine Aufgabe sollte sein, transparente Daten über USB zum/vom Chip zu
transportieren und dafür zu sorgen, dass alles ankommt. Die
Interpretation der Daten ist Sache der MPSSE. Und ich baue doch eine
Abstraktionsschicht wie obige Klasse FtJagIO doch gerade deshalb, damit
ich mich als Anwender eben nicht um irgendwelche Buffergrößen etc.
kümmern muss.
Ich will gar nicht generell ausschließen, dass Dein Vorschlag Erfolg
haben mag und werde es auch bei Gelegenheit mal ausprobieren. Aber ich
bin der Meinung, dass wenn Du Recht hast dieses Verhalten ein schlechtes
Design, wenn nicht gar einen Bug auf Seiten der FTDI-Entwickler
darstellen würde. Und vor allem sollte es dann irgendwo dokumentiert
sein. Man findet übrigens eine solche Sleep-Anweisung auch im
Beispielcode einer Application-Note von FTDI, ohne dass sie näher
erläutert wäre.
Letztlich wäre es auch noch möglich, dass es sich einfach um einen
Hardware-Bug handelt, da das Problem mit einem anderen Design (anderes
FPGA) nicht auftritt. Leider habe ich momentan keine Möglichkeit ein
anderes Exemplar der gleichen Hardware zu prüfen.
Gruß
Ist Ansichtssache. Meines Erachtens kann es bei deinem Aufbau sein, dass
du unvollständige Befehle schickst und ob das richtig gehandhabt wird
ist fraglich. Ich denke dann mal wohl eher nicht.
Du hast aber mit wenigen "Handgriffen" die Möglichkeit deine FtJagIO
umzubauen, indem du nur die Daten speicherst bis du wirklich 4096Bytes
hast und dann machst du einen neuen Buffer inkl. Kommando und Länge und
schickst das per FT_Write. Beim externen Aufruf von FlushBuffer müsstest
du es natürlich ein wenig anders handhaben, aber Hexerei ist das sicher
keine.
Naja, ich glaub ich hab alles gesagt was mir dazu einfällt ;-)
So denn,
PS: Viele App Notes und auch viele Tools von FTDI sind einfach nur
Schrott und man könnte verzweifeln. FT_PROG zB hab ich noch nie
fehlerfrei erlebt...