Hi,
ich habe hier ein USB-Gerät, welches als CDC-Device arbeitet (d.h. es
taucht im System als COMx bzw. /dev/ttyACMx auf).
Dieses Gerät erwartet Datenpakete, welche immer nur aus ein paar Bytes
bestehen.
Wenn solche Daten per Ethernet übertragen werden, dann ist es sinnvoll,
diese zu sammeln und erst ab einer bestimmten Paketgröße zu senden.
Wie ist das jetzt bei so einem USB-CDC-Device? Ist es da - wie bei einer
echten seriellen Schnittstellenhardware - egal ob ich die Daten jeweils
einzeln absende oder ist es wie bei Ethernet schneller, den Krempel zu
sammeln und immer größere Pakete auf einen Rutsch durchzuschicken?
Ich kann es leider nicht mal eben so ausprobieren, da die entsprechenden
Änderungen in der Software doch etwas größer sind, deswegen die Frage.
Danke!
Hallo,
USB überträgt die Daten in Pakete.
"Im Vergleich zu den früheren Lösungen bietet USB deutlich höhere
Datenübertragungsraten. Die Daten werden jedoch in Paketen übertragen,
für manche zeitkritische Anwendungen ist es deshalb weniger geeignet –
etwa bei mit nur wenigen Bytes belegten Paketen, die die
Übertragungsrate senken, oder wenn das Sammeln von Bytes zum Füllen
eines Pakets die Übertragung verzögern würde."
[https://de.wikipedia.org/wiki/Universal_Serial_Bus#Einsatzgebiete_des_USB]
Mit freundlichen Grüßen
Guido
OK...gibt's eine Möglichkeit herauszufinden, wie große diese Pakete
sind? Bei meiner Netzwerkschnittstelle weiß ich, dass die Gegenseite mit
1460 Nutzlast arbeitet.
Die Frage ist was du dir davon erhoffst?
Durch das Sammeln von mehr Daten für ein Paket steigt die Latenz noch
weiter. Dafür wird der Overhead kleiner.
Was ist das Ziel der Aktion?
Hallo,
SpacerX schrieb:> OK...gibt's eine Möglichkeit herauszufinden, wie große diese Pakete> sind? Bei meiner Netzwerkschnittstelle weiß ich, dass die Gegenseite mit> 1460 Nutzlast arbeitet.
da kann ich Dir leider nicht weiterhelfen.
Hier http://www.beyondlogic.org/usbnutshell/usb3.shtml#USBPacketTypes
steht einiges, vielleicht hilft Dir dies weiter.
Mit freundlichen Grüßen
Guido
Peter II schrieb:> Durch das Sammeln von mehr Daten für ein Paket steigt die Latenz noch> weiter. Dafür wird der Overhead kleiner.
Genau das ist mein Ziel: durch geringeren Overhead mehr Daten in
kürzerer Zeit übertragen. Die Latenz ist dabei zweitrangig.
SpacerX schrieb:> Peter II schrieb:>> Durch das Sammeln von mehr Daten für ein Paket steigt die Latenz noch>> weiter. Dafür wird der Overhead kleiner.>> Genau das ist mein Ziel: durch geringeren Overhead mehr Daten in> kürzerer Zeit übertragen. Die Latenz ist dabei zweitrangig.
Unter der Annahme, dass dein USB Bus bisher nicht voll ausgelastet ist,
erhöht das Sammeln nicht den Durchsatz. Du hast höchstens weniger USB
Interrupte auf deinem Gerät und häufig lassen sich die gesammelten Daten
leichter verarbeiten.
Für Bulk Endpoints ist die Paketgröße im Deskriptor angegeben. Meist
sind das 512 Byte.
Soweit ich das überblicke wird der Treiber buffern, wenn du schnell
genug Daten nachschiebst. Im Zweifel probier es aus (Wireshark hilft).
Natürlich ist es trotzdem effizienter, wenn du nicht für jedes Byte
einzeln write() aufrufst.
Sven B. schrieb:> Für Bulk Endpoints ist die Paketgröße im Deskriptor angegeben. Meist> sind das 512 Byte.
Bei CDC würde ich eher 64 Byte erwarten, das ist auch das Maximum für
Full Speed. Allerdings lohnen sich eventuell auch größere Transfers.
SpacerX schrieb:> Wie ist das jetzt bei so einem USB-CDC-Device? Ist es da - wie bei einer> echten seriellen Schnittstellenhardware - egal ob ich die Daten jeweils> einzeln absende oder ist es wie bei Ethernet schneller, den Krempel zu> sammeln und immer größere Pakete auf einen Rutsch durchzuschicken?
Problem: Es ist sowohl vom Host als auch vom Device abhängig.
Zwar erhöhen größere Transfers in aller Regel den Durchsatz, aber man
sollte trotzdem immer mit dem konkreten Device testen - es könnte sich
ja an großen Paketen "verschlucken" - Pufferüberlauf.
Die Durchsatzerhöhung kommt dadurch zustande, dass man der Bulktransfer
eine größere Datenmenge "in einem Rutsch" übertragen kann. Hat man diese
Datenmenge jedoch nicht, erhöht dies die Latenz. Die frei werdende
Kapazität auf dem USB Bus steht anderen Anwendungen zur Verfügung. Der
eigene Gesamt-Durchsatz wird nicht erhöht, sondern statt mehrerer
kleiner Bulktransfers, von denen jede ms einer angestoßen werden kann
wird ein großer nach vielen ms durchgeführt.
Speziell beobachte ich dies bei Anwendungen, welche eigentlich für die
RS232 geschrieben wurden und nun mit der virtuellen COM Schnittstelle
genutzt werden.
>Genau das ist mein Ziel: durch geringeren Overhead mehr Daten in
kürzerer Zeit übertragen. Die Latenz ist dabei zweitrangig.
Das geht so nicht. Wenn man groessere Mengen zB 1MByte + uebertragen
will, ist ueblicherweise die Latenz das Problem, speziell wenn mit
Bestaetigungen gearbeitet wird. Wenn also ueber die serielle
Schnittstelle viele Daten schnell uebertragen werden sollen. muss die
Blockgroesse rauf, aber vom originalen Protokoll. Die Blockgroesse kann
man adaptiv gestalten, dass die Blocke immer laenger werden solange
keine Retries erfolgen muessen.
Dabei sollte man die Restriktionen beachten. Ein 16bit CRC kann nur
2^16bit schuetzen. Also 8kbyte. Bei groesseren Bloecken muss auf einen
laengeren CRC gewechselt werden. Allenfalls verwendet man auch
Feedforward Error Correction, dh. einen ECC.
Des weiteren kann man das ACK, dh die Bestaetigung, verzoegern, muss
dafuer aber Zwischenspeichern. Und muss das kaputte Packet nach dem
Retry noch einfuegen koennen.
So erreicht man dann maximalen Durchsatz, kann den Kanal buendig
belegen.
Oder D. schrieb:> Ein 16bit CRC kann nur 2^16bit schuetzen. Also 8kbyte.
Selten so wirres Zeugs gelesen. Erstmal ist der CRC unabhängig von der
Anzahl der Bytes über die gerechnet wird - bei 16 Bit CRC wird halt
einer von 64k (Mehrbit-) Fehlern nicht erkannt. Außerdem sind 2^16 =
65536 und nicht nur 8192.
> es taucht im System als COMx bzw. /dev/ttyACMx
Auf der PC-Seite musst du dir gar keine Gedanken machen. Das
Betriebssystem kümmert sich selbst um die ideale Paketgröße. Die
USB-Treiber und das TCP/IP über dem Ethernet erzeugen selbst die
optimale Paketgröße aus dem Datenstrom.
Ganz anders sieht es aus, wenn du das Device baust. Hier musst du dir
Gedanken über die Puffergröße machen. Du rechnest aus, 512 Byte wären
ideal, aber dein MC hat gar nicht so viel RAM.
Noch einer schrieb:> Auf der PC-Seite musst du dir gar keine Gedanken machen. Das> Betriebssystem kümmert sich selbst um die ideale Paketgröße.
nein. Woher soll es denn wissen ob man niedrige Latenz oder hohen
Durchsatz will?
Die ideale größe ist aber davon abhängig. Nicht umsonst gibt es Flags
wie TCP_NODELAY.
Schickt man ein einzelnes Byte über den USB-Bus an ein CDC-Device, hat
man (mindestens) 8 Bytes Overhead. Jedem Nutzdatenpaket muß ein
Setup-Paket (das sagt, welches Gerät auf dem Bus man meint und was man
von dem erwartet) vorausgehen. Und das ist nun mal 8 Bytes lang.
Den "optimalen" Datendurchsatz dürfte man bei Full-Speed mit 64 Bytes
Nutzdaten und bei High-Speed mit 512 Bytes Nutzdaten erreichen (das sind
die jeweils maximalen Paketgrößen für Bulk-Transfers).
Das setzt natürlich voraus, daß der Treiber auch wirklich Bulk-Transfers
macht.
Peter II schrieb:> Die ideale größe ist aber davon abhängig. Nicht umsonst gibt es Flags> wie TCP_NODELAY.
Das gibt's hauptsächlich, damit man mit TCP auch irgendwie noch Dinge
hinkriegt, für die es eigentlich nicht geeignet ist.
Noch einer schrieb:> Ganz anders sieht es aus, wenn du das Device baust. Hier musst du dir> Gedanken über die Puffergröße machen. Du rechnest aus, 512 Byte wären> ideal, aber dein MC hat gar nicht so viel RAM.
Die USB-Endpoints haben ihre eigenen physikalischen Speicherbereiche zum
Senden und Empfangen. Controller mit integriertem USB 2.0 haben mehr als
genug RAM um 512 Byte irgendwo hin zu senden.
Was für ein wirres Durcheinander. Um das mal auf den Punkt zu bringen:
Guido C hat recht, alles andere in diesem Thread reicht dann von "genau
so richtig" bis "völliger Quatsch".
Ich habe den Transfer jetzt hostseitig umgestellt. Statt meine 3 bis 10
Byte großen Kommandos jedes mal sofort auf den Weg zu bringen, sammele
ich die Daten jetzt und sende sie erst ab, wenn mindestens 1024 Bytes
zusammen gekommen sind. Das dann abgesendete Datenpaket ist ebenfalls
immer genau 1024 Bytes groß und damit in jedem Fall ein ganzzahliges
Vielfaches der in Frage kommenden Puffergrößen.
Ergebnis: bei großen Datentransfers ist die Übertragung um ca. den
Faktor 10 schneller (nicht exakt gemessen, nur grob mit vorherigen
Transferzeiten verglichen).
Also findet bei CDC-Devices eine paketweise Übertragung mit
offensichtlich fester Paketgröße statt.
Rufus Τ. F. schrieb:> Genau hinsehen. 8192 Byte sind 2^16 Bit.
Ja, aber vermutlich nur im inneren eines schwarzen Loches oder nahe der
Lichtgeschwindigkeit. Ansonsten sind und bleiben 2^16 = 65535.
SpacerX schrieb:> OK...gibt's eine Möglichkeit herauszufinden, wie große diese Pakete> sind?
Natürlich. Man schaut einfach in den Standard, da steht das doch glatt
schwarz auf weiss drinne. Tipp: CDC benutzt Bulk-Transfers für den
Payload, also schaut man nach der maximalen Größe von Bulk-Transfers.
Und diese hängt nun wiederum vom "Speed-Grade" des Gerätes ab. Auch das
steht in dem Standard. Man muß ihn nur einfach mal lesen...
Du musst also zuerst herausfinden, ob es sich um ein Full-, High- oder
Super- oder Super+- Speed-Gerät handelt (Low-Speed-Geräten sind
Bulk-Transfers aus unerfindlichen Gründen vom Standard her grundsätzlich
nicht erlaubt).
Allerdings beschränken sich real existierende CDC-Geräte wohl in aller
Regel auf Full-Speed. In Einzelfällen mögen auch High-Speed-CDC-Geräte
vorkommen. Mir persönlich ist allerdings nie eins über den Weg gelaufen.
Soll heissen: du kannst Full-Speed mehr oder weniger als gegeben für ein
CDC-Gerät ansehen...
c-hater schrieb:> Allerdings beschränken sich real existierende CDC-Geräte wohl in aller> Regel auf Full-Speed. In Einzelfällen mögen auch High-Speed-CDC-Geräte> vorkommen. Mir persönlich ist allerdings nie eins über den Weg gelaufen.> Soll heissen: du kannst Full-Speed mehr oder weniger als gegeben für ein> CDC-Gerät ansehen...
Da bei USB HS CDC aller 125µs ein Transfer ausgelöst werden kann,
bekommt man hier bei wenig Daten die Latenz besser in den Griff und das
Interface verhält sich ähnlicher zu einer realen RS232.
Aber dies war dem TO nicht so wichtig.