Kampis Elektroecke

Aufbau des USB-Protokolls

In diesem Kapitel möchte ich euch einen kleinen Überblick über das USB-Protokoll und die Kommunikation zwischen Device und Host geben. Dazu werde werde ich auf die einzelnen Transaktionen und die grundlegende Kommunikation eingehen, wobei ich tiefgehende Einblicke in den USB auslasse, da diese in der Regel nur für die Entwicklung eigener USB-Hardware relevant sind. Falls ihr dennoch einen Einblick auf die unterste Ebene der USB-Kommunikation erhalten wollt, so könnt ihr diesen hier bekommen. 

Bei jedem USB-Device wird eine der beiden Datenleitungen über einen Pull-Up Widerstand auf einen High-Pegel gezogen. Je nachdem ob dieser Widerstand an D+ oder D- angeschlossen ist, handelt es sich entweder um ein Full Speed Device (Pull-Up an D+) oder um ein Low Speed Device (Pull-Up an D-).

Das Ende einer USB-Verbindung, welches sich näher am Host befindet, wird Upstream End Transceiver und das Ende, welches sich näher am Device befindet, wird Downstream End Transceiver genannt. Die Datenleitungen des Upstream End Transceiver werden über Pull-Down Widerständen auf Masse gezogen.

Jedes USB-Gerät wird zudem durch eine Mindestanzahl von Bitfeldern, den sogenannten Deskriptoren, beschrieben.

Deskriptor Beschreibung
Geräte Jedes Gerät besitzt einen Geräte-Deskriptor der ganz allgemeine Informationen, wie die verwendete USB-Version oder die Hersteller-, bzw. die Produkt-ID oder die Anzahl der Gerätekonfigurationen, bereitstellt.
Konfiguration Die unterschiedlichen Gerätekonfigurationen werden über Konfigurations-Deskriptoren abgebildet, die z. B. die Stromaufnahme oder die Anzahl der Interfaces einer Gerätekonfiguration beschreiben. Der Host kann immer nur eine Gerätekonfiguration gleichzeitig aktivieren.
Interface Jedes Interface wird durch einen Interface-Deskriptor beschrieben und anders als bei den Gerätekonfigurationen können mehrere Interfaces gleichzeitig aktiv sein.
Endpunkt Die einzelnen Endpunkte eines jeden Interfaces werden durch Endpunkt-Deskriptoren beschrieben. Diese beinhalten z. B. Informationen wie die Größe des Endpunktes und ob es sich um einen IN oder OUT Endpunkt handelt.
String Optionale Deskriptor. Es können folgende Strings hinterlegt werden:

  • Manufacturer String
  • Product String
  • Serial Number String

Die Kommunikation zwischen Host und Device findet mit Hilfe von Endpunkte und Pipelines statt. Jeder Endpunkt ist als Senke, bzw. Quelle von Daten definiert und wird über eine Pipeline mit dem Host verbunden. Insgesamt kann jedes USB-Gerät bis zu 16 IN und 16 OUT Endpunkte besitzen, wobei die Größe variabel ist und in der Regel vom verwendeten USB-Controller abhängt. Ein besonderer Endpunkt ist der Endpunkt 0, da dieser Endpunkt sowohl als IN, wie auch als OUT Endpunkt verwendet wird. Dieser Endpunkt ist zudem der Standardendpunkt, der bei der Konfiguration des Gerätes genutzt wird.

Ein Datentransfer beim wird USB Transaktion genannt. Der USB-Standard kennt drei verschiedene Arten von Transaktionen:

Transaktion Beschreibung
IN Übertragung vom Device zum Host
OUT Übertragung vom Host zum Device
SETUP OUT Transaktion um Konfigurations- oder Kontrolldaten zum Gerät zu senden oder abzufragen.

Eine solche Transaktion kann mit einer von vier verschiedenen Übertragungsarten durchgeführt werden, wobei jede Übertragungsart ihre speziellen Vorteile bietet.

Für die Kommunikation mit dem Host muss jedes USB-Gerät eine bestimmte Menge an Befehlen, die sogenannten Standard-Requests, verstehen und bedienen können. Der Host nutzt diese Requests um möglichst viele Informationen über das neue Gerät zu erfragen. Nachdem der Host alle notwendigen Informationen gesammelt hat, werden die Requests für die Konfiguration und Initialisierung des eingesteckten USB-Gerätes verwendet.

Sobald ein neues USB-Gerät eingesteckt wird, wird eine der beiden Datenleitungen auf einen High-Pegel gezogen, wodurch der Host über ein neues Gerät informiert wird. Bevor der Host mit dem „befragen“ des neuen Gerätes beginnt, führt er einen Reset des Gerätes durch, indem er beiden Datenleitungen für mindestens 10 Millisekunden auf Low zieht (dies ist kein Hardwarereset!). Durch den Reset wird die Adresse des USB-Gerätes auf 0 zurückgesetzt. Diese Adresse kann nun vom Host genutzt werden um mit das Gerät über Endpunkt 0 zu konfigurieren. Vor der eigentlichen Kommunikation muss der Host allerdings erst die Größe des Endpunktes 0 ermitteln, welche im Geräte-Deskriptor des angeschlossenen Gerätes hinterlegt ist (Bitfeld bMaxPacketSize0).

Die Erfragung des Geräte-Deskriptors beginnt der Host mit einen Control Transfer. Jeder Control Transfer enthält eine SETUP Stage, die eine SETUP Transaktion und darin ein 8 Byte großes Setup-Paket, welches die Anfrage des Hosts spezifiziert, beinhaltet. 

Offset Feld Größe Beschreibung
0 bmRequestType 1 Bit 7:
Richtung
0 = Host-to-device
1 = Device-to-host
Bit 6 – 5:
Typ
0 = Standard
1 = Class
2 = Vendor
3 = Reserviert
Bit 4 – 0:
Empfänger
0 = Device
1 = Interface
2 = Endpunkt
3 = Other
4 – 31 = Reserviert
1 bRequest 1 Art des Requests
2 wValue 2 Variiert je nach Request
4 wIndex 2 Variiert je nach Request
6 wLength 2 Anzahl der zu übertragenden Bytes

Dieses Setup-Paket enthält sämtliche Anfragedetails des Hosts an das Device und wird vom Host mit den entsprechenden Werten des Requests gefüllt. In der DATA Stage antwortet das Gerät dann mit dem angefragten Daten, falls die Anfrage vom Host eine Antwort des Gerätes verlangt. Zum Abschluss sendet der Host in der STATUS Stage noch eine CRC und wenn die Übertragung fehlerfrei war, wird die Nachricht vom Gerät mit einem ACK bestätigt.

Unter Windows sieht die SETUP Stage der ersten GET_DESCRIPTOR-Anfrage folgendermaßen aus:

Offset Feld Wert Beschreibung
0 bmRequestType 0x80

Device-to-host

Standard

Device

1 bRequest 0x06 GET_DESCRIPTOR (6)
2 wValue 0x100

Deskriptortyp 1 (Gerätedeskriptor)

Deskriptorindex 0

4 wIndex 0x00
6 wLength 0x40 64 Bytes

Ein Windowshost möchte bei der ersten Anfrage immer 64 Bytes einlesen, bricht die Übertragung aber nach den ersten 8 Bytes ab und führt einen weiteren Reset des Gerätes durch. Die 8 empfangenen Bytes beinhalten die Größe vom Endpunkt 0, die der Host nun kennt. Durch den zweiten Reset wird verhindert, dass das Gerät durch die Anfrage vom Host nicht in einem undefinierten Zustand ist.

Nach dem zweiten Reset führt der Host eine SET_ADDRESS-Anfrage durch um die USB-Adresse des angeschlossenen Gerätes zu setzen. Die verwendete Adresse hängt dabei von den bereits angeschlossenen Geräten ab und ist variabel. Danach führt der Host eine neue GET_DESCRIPTOR-Anfrage durch, nur das in diesem Fall wLength auf 18 gesetzt wird, was der kompletten Länge des Geräte-Deskriptors entspricht. Das Gerät antwortet erneut mit dem Gerätedeskriptor, nur dieses mal bricht der Host nicht die Übertragung ab, sondern empfängt alle Daten und quittiert den Transfer mit einem ACK. Der Host weiß nun wie das Gerät aufgebaut ist und führt weitere Anfragen durch um alle anderen Deskriptoren zu erfragen. Sobald sich der Host sich sicher ist um was für ein Gerät es sich handelt, lädt er einen entsprechenden Treiber (z. B. einen Maustreiber) und das Gerät kann verwendet werden.

Im nächsten Teil des Tutorials beschäftigen wir uns mit der Initialisierung von dem USB-Modul des Mikrocontrollers.

Zurück

2 Kommentare

  1. Servus,
    ich glaube da ist ein Fehler im Teil mit dem Geräte Reset.

    „Bevor der Host mit dem “befragen” des neuen Gerätes beginnt, führt er einen Reset des Gerätes durch, indem er beiden Datenleitungen für mindestens 10 Sekunden auf Low zieht (dies ist kein Hardwarereset!)“

    Ich meine das müssten 10 ms sein ;)

    PS. Sonst schön erklärt

    Grüße

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert