Hallo Forum, ich benötige mal Hilfe bei eine USB-Host-Implementation. Ich habe hier einen STM32F4xx und damit verbunden einen FTDI FT232. Jetzt habe ich den USB-Host Core aus den Beispielen von ST und den Linux-Treiber vom FTDI zusammengebaut und erfolgreich zum laufen bekommen. Ich kann den FTDI konfigurieren (Baudraten, Handshake, etc.) und erfolgreich Daten abrufen und senden. Zum Senden verwende ich die "USBH_BulkSendData(...)"-, zum Empfangen die "USBH_BulkReceiveData(...)"-Funktionen. Empfangen geht auf diese Weise mit Pollen der Daten, ich rufe zyklisch die Empfangsroutine auf und wenn etwas dinne ist, werden Daten weiter an die nächst höhere Schicht gereicht. Jetzt kommt das Problem, wenn ich versuche dieses Polling alle 10ms zu machen, gibt es ein variable Verzögerung. Also der Interrupt, der den Abschluss der Aktion anzeigt kommt viel zu spät. Polle ich langsam (>20ms) vergeht eine Zeit von 26µs vom Starten bis zum Interrupt (CHH-Interrupt). Polle ich schneller vergehen zwischen 3ms und 16ms bis der Interrupt kommt. Frage: was blockiert denn hier? Ist das bei Bulk-Transfer immer so, dass eine gewisse Wartezeit eingehalten werden muss? Kann mir jemand erklären, was genau hier auf dem Bus passiert dass zu dem o.g. Verhalten führen kann? Danke
Der FT232 hat doch einen variablen FIFO, der könnte die beobachtete Verzögerung erklären. Die Idee dahinter ist die Bytes vom UART zu sammeln und in einer größeren Bulk Transaktion zu verarbeiten anstatt viele kleine Transaktionen zu verwenden - letzteres würde den Host stärker belasten. Im Windows Treiber ist das eintellbar. Schau Dir mal die Linux Source genau an, dort müsste es eigentlich auch einstellbar sein.
Mein FT232 hat 256 bytes Fifo. Mit aktiviertem Hardware-Handshake konnte ich den Buffer füllen und auch sehen, wann er voll war. Dann kann man die Daten auslesen. Bei 115200 Bd sind sie 256 Bytes in etwas mehr als 20ms voll. Ich wollte wenn ich Daten gelesen hatte, gleich nochmal abfragen und schnell auslesen. Erst wenn keine Daten mehr kommen wollte ich auf einen langsamen Takt wechseln. Dabei ist mir dann aufgefallen dass es nicht wirklich schnell gelesen wurde. Durch Messung bin ich dann darauf gekommen, dass der Interrupt sehr lange auf sich warten lässt. Kann der USB Client denn die Kommunikation verzögern?
Rangi J. schrieb: > Kann der USB Client denn die Kommunikation verzögern? Selbstverständlich. Er braucht auf das (Bulk)IN-Token nur ein NAK zu senden. Der FTDI Chip wird das vermutlich solange machen, bis entweder der FIFO voll genug oder ein Timout aufgetreten ist.
So, ich habs kurzerhand einfach mal aufm PC gesnifft. Hier kann man die Polling-Zeit einstellen. Initial stand das auf 16ms und tatsächlich wurde auch alle 16ms ein "URB_BULK in" Transfer ausgelöst. Beim Umstellen auf 5ms eben dann alle 5ms. Und das ganze ohne Verzögerungen oder Wartezeiten. Der FTDI hat artig alle 5ms geantwortet. Das hat bei mir z.B. nicht geklappt. Und jetzt hab ich nochwas gesehen: (Beim diesem Sniff hatte ich Glück, denn die Zeit war genau auf 0 beim Start) Im Bild Zeile 196 sind Daten enthalten. Der folgende Transfer erfolgt nicht 10ms später, sondern 31ms. Danach geht es wieder alle 10ms weiter. Wie kann ich mir das erklären? Und es kann hier nicht daran liegen, das 286 Bytes übertragen wurden. 286 Bytes @ 12MHz dauern ca. 0,5ms
Rangi J. schrieb: > Im Bild Zeile 196 sind Daten enthalten. Der folgende Transfer erfolgt > nicht 10ms später, sondern 31ms. Danach geht es wieder alle 10ms weiter. > Wie kann ich mir das erklären? Und es kann hier nicht daran liegen, das > 286 Bytes übertragen wurden. 286 Bytes @ 12MHz dauern ca. 0,5ms Da hat der FTDI das gleiche gemacht wie vorher schon am STM32: Solange keine Daten in der FIFO sind, sofort "nix da" geantwortet. Die ersten paar Bytes auch gleich mitgeschickt. Und dann den USB-Transfer hingehalten, das soll sich schließlich lohnen. Am PC ist so ein Verhalten oft praktisch, denn es reduziert Interruptlast und Taskwechsel. Vernünftigerweise sollte man das aber konfigurieren können. Vor allem, wann der FTDI damit wieder aufhört, sonst hält er nach dem letzten Byte auf der Leitung den PC noch 30ms hin, während die Gegenseite auf die Antwort wartet.
@Nosnibor: das ist aber unlogisch. Das "warten" auf mehr Daten sollte aber aufhören, wenn der Puffer voll ist. Das passiert aber nicht. Im Gegenteil, dadurch kommt es zum Datenverlust, der Puffer läuft über. Ich hab nochwas komisches gesehen. Beim Transfer mit Windows sind Transferlängen von 270 Byte (vermutlich mehr) möglich (oder werde ich hier vom USBPcap verschaukelt?). Beim STM32 hat mir aber der End-Point-Descriptor gesagt nur 64Bytes maximal möglich sind (in_ep_size=0x40, out_ep_size=0x40). Ich habs mal manuell auf 128 gesetzt, aber das funktioniert nicht, dann kommt ein Timeout in der ISR.
So, jetzt hatte ich mal wieder Zeit diesem Thema zu widmen: Es gibt eine Erkenntnis. Ich muss dem FTDI mit einem Befehl einen Latency-Timer einstellen. Dieser wirkt sehr merkwürdig, denn ich kann den FTDI nicht auslesen, solange dieser Timer nicht abgelaufen ist, auch wenn (und ich betone, selbst wenn) Daten im Puffer sind und sogar wenn der Puffer überläuft. Man muss den Timer dann am besten auf ein Wert stellen, in dem dann alle möglichen Daten reinpassen. Der Wert des Timers ist ein Byte, 1 = 1ms. Bei 0 kann ich immer auslesen, macht aber nur dann sinn, wenn die Applikation das Auslesen künstlich verlangsamt.
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.
