Forum: Mikrocontroller und Digitale Elektronik USB: Verständnisfrage


von Andi K. (fry12)


Lesenswert?

An alle USB-Experten ;-)

Ich arbeite mich gerade ein wenig in USB Full-Speed ein und habe eine 
Frage bezüglich des Data-Toggle-Verfahrens bei Bulk-Transfers. Ich 
versuche das Ganze mal mit meinen Worten zu erklären, korrigiert mich 
bitte, falls ich falsch liege ;)

Wenn die zu übertragenden Daten eine Größe von 64 Byte überschreiten 
(entspricht der maximalen Größe des Endpoint-Buffers bei Bulk-Transfers, 
die hier angenommen wird), müssen sie auf mehrere Transaktionen 
aufgeteilt werden. Angenommen ich möchte von einem USB Device bzw. von 
einer Function Daten an den USB Host senden und das Toggle-Bit ist bei 
Sender und Empfänger auf 0. Dann ist der Ablauf wie folgt:

Host   (0): Sendet IN-Token
Device (0): Falls USB-Adresse und Endpoint-Nummer gültig sowie 
Sende-FIFO des Endpoints mit Daten gefüllt sind, wird ein DATA0-Paket 
mit den entsprechenden Daten gesendet.
Host   (0) -> (1): Bestätigt Empfang der Daten, falls sie fehlerfrei 
empfangen wurden mit einem ACK-Handshake. Data-Toggle-Bit wird auf (1) 
gesetzt.
Device (0) -> (1): Empfängt ACK-Handshake und setzt daraufhin 
Data-Toggle-Bit ebenfalls auf (1).

Host   (1): Sendet IN-Token
Device (1): Sendet DATA1-Paket
Host   (1) -> (0): Sendet ACK-Handshake, Data-Toggle-Bit wird auf (0) 
gesetzt.
Device (1) -> (0): Empfängt ACK-Handshake und setzt daraufhin 
Data-Toggle-Bit ebenfalls auf (0).

Das Ganze wiederholt sich so lange, bis alle Daten gesendet wurden und 
der Host ein unvollständiges DATAx-Paket oder ein Zero-Length-Paket 
erhält.

Zu einer Asynchronität zwischen den Data-Toggle-Bits des Senders und 
Empfängers kann es nur bei einem fehlerhaft übertragenen Handshake 
kommen.  Also wieder am Beispiel einer IN-Transaktion:

Host   (0): Sendet IN-Token
Device (0): Sendet DATA0-Paket
Host   (0) -> (1): Empfängt DATA0-Paket fehlerfrei, setzt 
Data-Toggle-Bit auf (1), sendet ACK-Handshake
Device (0): Empfängt fehlerhaftes ACK-Token, kein Togglen des 
Data-Toggle-Bit.

Zu diesem Zeitpunkt hat der Host die Daten korrekt Empfangen, die 
Function denkt jedoch, dass bei der Datenübertragung Fehler aufgetreten 
sind und der Host die Daten verworfen hat, da die Transaktion nicht 
bestätigt wurde.

Host   (1): Sendet IN-Token
Device (0): Sendet DATA0-Paket erneut
Host   (1) -> (1): Empfängt DATA0-Paket fehlerfrei, Toggle-Bits stimmen 
jedoch nicht überein (DATA1-Paket wurde erwartet), Daten werden 
verworfen und Toggle-Bit nicht gesetzt, sendet trotzdem ACK-Handshake
Device (0) -> (1): Empfängt ACK-Token, setzt Data-Toggle-Bit auf (1).

Damit herrscht nun wieder Synchronität bezüglich des Data-Toggle-Bits.

Wo liegt nun der Sinn des ganzen Manövers? Dient das Data-Togglen nur 
dem Entdecken und Korrigieren eines Handshake-Fehlers?

Außerdem habe ich eine weitere Frage: USB ist ein Single-Master Bus, bei 
dem der Host der einzige Master ist und alle Transfers initiiert. Am 
Beispiel eines IN-Bulk-Transfers: Woher weiß der Host, dass das USB 
Device Daten senden möchte? Läuft das irgendwie über den 
Control-Endpoint?

Vielen Dank!

von matrixstorm (Gast)


Lesenswert?

Andi K. schrieb:
> Am
> Beispiel eines IN-Bulk-Transfers: Woher weiß der Host, dass das USB
> Device Daten senden möchte? Läuft das irgendwie über den
> Control-Endpoint?

Er pollt die Devices in einer vom Device konfigurierten Zeit. (Bei 
fullspeed minimal 5ms)

MfG

von Andi K. (fry12)


Lesenswert?

Dann müsste die Polling-Zeit aber in einem Descriptor stehen. Zwar gibt 
es an einer Stelle einen ähnlichen Eintrag, nämlich bIntervall in den 
Endpoint-Descriptors, der ist aber für Interrupt- oder 
Isochronous-Transfers gedacht und wird von Bulk-Transfers ignoriert.

von Andi K. (fry12)


Lesenswert?

Kann mir keiner weiterhelfen? Hier muss es doch USB-Kenner geben ;)

von Potter (Gast)


Lesenswert?

Andi K. schrieb:
> Wo liegt nun der Sinn des ganzen Manövers? Dient das Data-Togglen nur
> dem Entdecken und Korrigieren eines Handshake-Fehlers?

Genau.

Ausserdem: Was passiert, wenn der Empfänger nicht so schnell die Daten 
verarbeitet, wie der Sender sendet? - Dann gehen Datenpakete verloren.
Aber genau dann wird das Data-Toggle nicht umgeschaltet vom Empfänger, 
die Antwort lautet NAK und der Sender weiss, dass er das gleiche Paket 
noch einmal senden muss.

Was passiert, wenn der Empfänger ein Paket mit ACK bestätigt und der 
Sender das nicht mitbekommt? Der Sender sendet das gleiche Paket 
nochmal, aber der Empfänger verwirft es (falsches Data-Toggle) und gibt 
nur ein ACK zurück -> alles wieder synchron.

Bei den Control-Transfers ist es wieder etwas anders. Im Setup-Abschnitt 
immer Data0, Data1 in der ersten Transaktion (schaltet dann um bei 
weiteren) und im Status-Abschnitt immer Data0.

Andi K. schrieb:
> Läuft das irgendwie über den
> Control-Endpoint?

Nein. Das läuft über die Daten-Endpunkte und da steht dann in den 
Descriptoren auch das Polling-Intervall drin.

von Andi K. (fry12)


Lesenswert?

Vielen Dank für deine Antwort!

Im konkreten Fall habe ich hier einen Mikrocontroller, der als Device 
mit der Geräteklasse CDC ACM läuft und als virtueller COM Port am PC 
sichtbar ist. Dazu habe ich keine eigenen Funktionen geschrieben, 
sondern verwende Libraries vom Hersteller. Wenn ich nun im Code nach den 
Endpoint-Descriptors suche, erhalte ich für die beiden Data-Endpoints 
folgendes:
1
.ep_in.bLength                = sizeof(usb_ep_desc_t),\
2
.ep_in.bDescriptorType        = USB_DT_ENDPOINT,\
3
.ep_in.bmAttributes           = USB_EP_TYPE_BULK,\
4
.ep_in.bInterval              = 0,\
5
.ep_out.bLength               = sizeof(usb_ep_desc_t),\
6
.ep_out.bDescriptorType       = USB_DT_ENDPOINT,\
7
.ep_out.bmAttributes          = USB_EP_TYPE_BULK,\
8
.ep_out.bInterval             = 0,

Dass es sich um Bulk-Endpoints handelt ist klar. Allerdings ist hier 
kein Intervall angegeben; daher auch meine Frage, woher der Host weiß, 
wann Daten verfügbar sind.

Anscheinend wird das über einen Interrupt-Endpoint geregelt, da dieser 
(neben den beiden Bulk-Endpoints) als einziger noch definiert ist:
1
.ep_notify.bLength            = sizeof(usb_ep_desc_t),\
2
.ep_notify.bDescriptorType    = USB_DT_ENDPOINT,\
3
.ep_notify.bmAttributes       = USB_EP_TYPE_INTERRUPT,\
4
.ep_notify.wMaxPacketSize     = LE16(UDI_CDC_COMM_EP_SIZE),\
5
.ep_notify.bInterval          = 0x10,\
6
.ep_notify.bEndpointAddress   = UDI_CDC_COMM_EP_##port,\

Kann ich also davon ausgehen, dass der Host mit einem 
Interrupt-Intervall von 16 ms anfragt, ob Daten vorhanden sind und falls 
welche vorhanden sind, ein entsprechendes IN-Token an den Bulk-Endpoint 
sendet? Oder ist das zu sehr durch die Glaskugel geschaut? ;)

von Potter (Gast)


Lesenswert?

Das mit der 0 in den Bulk-Endpunkten ist meiner Meinung nach Käse. Ich 
gehe davon aus, wenn da eine Null drin steht, dass der Host das dann 
einfach ignoriert und das Intervall selber festlegt.

Der Interrupt-Endpunkt übernimmt die Steuerleitungen der RS232 - also 
RST, CTS, ...

Die Bulk-Endpunkte übertragen die Nutzdaten.

von Potter (Gast)


Lesenswert?

Ich muss mich korrigieren: Der Interrupt-Endpunkt schickt Status-Updates 
an den Host.
Ob das auch die Steuerleitungen betrifft, k.A. - es ist schon etwas her, 
dass ich mich damit beschäftigt habe.

von Andi K. (fry12)


Lesenswert?

Danke! Wo kann ich nähere Informationen dazu finden? Die 
USB-Spezifikation ist dafür wohl nicht der richtige Anlaufpunkt. Auch 
die Spezifikation der Communication Device Class ist hier nicht weiter 
ergiebig.

: Bearbeitet durch User
von Jim M. (turboj)


Lesenswert?

Andi K. schrieb:
> Kann ich also davon ausgehen, dass der Host mit einem
> Interrupt-Intervall von 16 ms anfragt, ob Daten vorhanden sind und falls
> welche vorhanden sind, ein entsprechendes IN-Token an den Bulk-Endpoint
> sendet?

Nein. Der Host sendet IN-Tokens an Bulk EPs, wenn "noch Platz im 1 ms 
Frame" ist.

Bedingung ist nur das auch jemand auf Host Seite die Daten haben will. 
Bei CDC muss also die Schnittstelle geöffnet sein.

Wenn das Device grade keine Daten im Puffer hat, sendet es ein NAK als 
Antwort.

Wie oft nun IN Tokens an einem Bulk EP eines Devices ankommen, hängt 
auch von der Auslastung des Busses ab.

von Andi K. (fry12)


Angehängte Dateien:

Lesenswert?

Jim Meba schrieb:
> Nein. Der Host sendet IN-Tokens an Bulk EPs, wenn "noch Platz im 1 ms
> Frame" ist.
>
> Bedingung ist nur das auch jemand auf Host Seite die Daten haben will.
> Bei CDC muss also die Schnittstelle geöffnet sein.

Okay vielen Dank! Das heißt es kommt auch auf die Busauslastung an, zu 
welchem Zeitpunkt ein Bulk-Transfer gestartet werden kann. Weiß jemand, 
wo man das nachlesen kann? In der USB-Spezifikation bin ich noch nicht 
fündig geworden.

Eine Frage hätte ich noch, dieses mal zu Interrupt-Transfers:

Laut USB-Spezifikation ist es mit Full-Speed-Geräten möglich, bei einer 
Paketgröße von 64 Bytes eine maximale Datenrate von 1216000 byte/s zu 
erreichen, falls 19 Interrupt-Transfers in einem 1-ms-Frame gepackt 
werden (siehe angehängtes Bild, vorletzte Zeile).

Allerdings wird auch erwähnt, dass die minimale Polling-Zeit des Hosts 
bei 1 ms liegt. Mit der maximalen Paketgröße (64 byte) hieße das, dass 
nur 64000 byte/s übertragen werden könnten (das liest man oft im 
Internet, u.A. auf wikipedia). Was ist nun richtig?

P.S.: Sorry für das Ausgraben meines alten Threads ;)

: Bearbeitet durch User
von Peter (Gast)


Lesenswert?

Andi K. schrieb:
> Allerdings wird auch erwähnt, dass die minimale Polling-Zeit des Hosts
> bei 1 ms liegt. Mit der maximalen Paketgröße (64 byte) hieße das, dass
> nur 64000 byte/s übertragen werden könnten (das liest man oft im
> Internet, u.A. auf wikipedia). Was ist nun richtig?

Das gilt bei Interrupt-Endpunkten.

Andi K. schrieb:
> Laut USB-Spezifikation ist es mit Full-Speed-Geräten möglich, bei einer
> Paketgröße von 64 Bytes eine maximale Datenrate von 1216000 byte/s zu
> erreichen, falls 19 Interrupt-Transfers in einem 1-ms-Frame gepackt
> werden (siehe angehängtes Bild, vorletzte Zeile).

Das gilt bei Bulk-Endpunkten. Stichwort: Micro-Frames.

von Andi K. (fry12)


Lesenswert?

Mir ist bewusst, dass das für Interrupt-Endpoints gilt, deswegen habe 
ich auch ausdrücklich von Interrupt-Transfers gesprochen ;)

Micro-Frames sind erstmal irrelevant, weil es hier nur um USB Full-Speed 
und nicht um High-Speed geht. Hast du dir das Bild angesehen? Das stammt 
direkt aus der USB-Spezifikation und zeigt, dass anscheinend 1216000 
byte/s statt 64000 bytes/s für USB Full-Speed Interrupt-Transfers 
möglich sind.

: Bearbeitet durch User
von Lattice User (Gast)


Lesenswert?

Andi K. schrieb:
> Mir ist bewusst, dass das für Interrupt-Endpoints gilt, deswegen habe
> ich auch ausdrücklich von Interrupt-Transfers gesprochen ;)
>
> Micro-Frames sind erstmal irrelevant, weil es hier nur um USB Full-Speed
> und nicht um High-Speed geht. Hast du dir das Bild angesehen? Das stammt
> direkt aus der USB-Spezifikation und zeigt, dass anscheinend 1216000
> byte/s statt 64000 bytes/s für USB Full-Speed Interrupt-Transfers
> möglich sind.

Die Applikation kann den Interrupttransfer schon so aufsetzen, dass pro 
Poll mehr als 64 Bytes übertragen werden (in einem URB). Ist nur 
unüblich.

Interrupt und Bulk unterscheiden sich nur in der Art und Weise wie das 
Polling gehandhabt wird.
Bulk: Wenn ein URB submitted wirdm wird der Transfer sofort eingeplant,
Interrupt: Der Transfer wird erst nach Ablauf des Interrupt Polling 
Intervals eingeplant.

von Lattice User (Gast)


Lesenswert?

Lattice User schrieb:
>>...

Kleiner Nachtrag:
Ein weiterer Unterschied besteht, wenn das Device den Transfer mit NAK 
ablehnt. Bulk: Sofort wiederholen, Interrupt: Erst beim nächsten 
Pollinginterval.

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.