Forum: Mikrocontroller und Digitale Elektronik Atmel ARM: USB Communication Device Class


von Andi K. (fry12)


Lesenswert?

Hallo Leute!

Ich habe hier einen Atmel SAM4 Mirocontroller, den ich per USB an einen 
PC angeschlossen habe. Dabei wird die USB Communication Device Class 
(CDC) verwendet, um einen virtuellen COM Port benutzen zu können. Da ich 
nicht in die Untiefen von USB eindringen will, habe ich dazu einfach das 
Atmel Software Framework verwendet, d.h. ich könnte bspw. ganz einfach 
per printf() Daten an ein Terminalprogramm senden. Das funktioniert auch 
alles soweit.

Jetzt möchte ich aber bestimmte Daten (byteweise) sicher übertragen. 
Jetzt stellt sich allerdings die Frage, welchen USB Transfer Modus das 
Atmel Software Framework für CDC benutzt.

Laut diesem PDF http://www.atmel.com/Images/doc6269.pdf wird entweder 
ein Isochroner oder ein Bulk Transfer verwendet. Wie kann ich jetzt 
herausfinden, was genau verwendet wird? Der ASF Source Code ist leider 
sehr umfangreich und für mich als USB-Neuling nur schwer zu 
durchblicken.

Allerdings hängt von der Übertragungsart ab, ob ich noch eine CRC an die 
Daten anhängen sollte oder nicht. Kommt ein Bulk Transfer zum Einsatz, 
wird automatisch eine CRC16 Prüfsumme berechnet und mitgeschickt. Da 
wäre es natürlich überflüssig nochmal eine CRC Summe zu berechnen, zumal 
Bulk Transfers eine Übertragung ohne Fehler sicherstellen (d.h. erneutes 
Senden der Daten bei Fehlern).

Hat sich schon mal jemand mit dem Thema beschäftigt und kann mir 
weiterhelfen oder ein paar nützliche Hinweise geben, wie ich das 
herausfinden kann?

Besten Dank im Voraus!

Edit: Bevor es einer sagt: Ich weiß, dass der Begriff "Prüfsumme" bei 
CRC nicht ganz korrekt ist ;-)

: Bearbeitet durch User
von PittyJ (Gast)


Lesenswert?

Unter Linux kann man sich z.B. mit Wireshark auch das USB-Protokoll mit 
anzeigen lassen.
Beim der Arduino Kommunikation wird dort Bulk-Transfer verwendet.

Zum Sam kann ich nichts sagen.

von Andi K. (fry12)


Lesenswert?

PittyJ schrieb:
> Unter Linux kann man sich z.B. mit Wireshark auch das USB-Protokoll mit
> anzeigen lassen.
> Beim der Arduino Kommunikation wird dort Bulk-Transfer verwendet.
>
> Zum Sam kann ich nichts sagen.
Danke für den Tipp, das werd ich mir mal genauer ansehen

von Jim M. (turboj)


Lesenswert?

Andi K. schrieb:
> Jetzt stellt sich allerdings die Frage, welchen USB Transfer Modus das
> Atmel Software Framework für CDC benutzt.

Bei CDC Serial Port wird praktisch immer USB Bulk Mode für die Daten 
benutzt.
Isochrone Transfers sind nur bei USB Audio üblich.

>  Wie kann ich jetzt herausfinden, was genau verwendet wird?

An einer Linux Kiste (Live CD oder virtuell) anstecken und
1
# lsusb -v | less
ausführen. Das zeigt Dir u.a. die Endpoint Deskriptoren und auch deren 
Typ an. Ein CDC Serial Port hat 2 Interfaces, eins mit 1x Interrupt 
Endpoint für Steuerzwecke und eins mit 2x Bulk (In+Out) für die 
eigentlichen Daten.

Einfacher ist es natürlich, wenn man den USB Configuration Descriptor im 
Source Code findet, da steht das ja auch drin.

Andi K. schrieb:
> Kommt ein Bulk Transfer zum Einsatz,
> wird automatisch eine CRC16 Prüfsumme berechnet und mitgeschickt. Da
> wäre es natürlich überflüssig nochmal eine CRC Summe zu berechnen

Hätte ich auch gedacht - bis eine einfache XOR 8 Bit Prüfsumme einen 
subtilen Fehler in einem CDC Code Beispiel für NXPs LPC1768 aufdeckte. 
Auch eigene Fehler sind mit Checksumme oft leichter zu finden.

von Andi K. (fry12)


Lesenswert?

Jim Meba schrieb:
> Einfacher ist es natürlich, wenn man den USB Configuration Descriptor im
> Source Code findet, da steht das ja auch drin.
Müsste ich da nicht eher nach dem Endpoint Descriptor suchen? Im 
Configuration Desciptor steht doch eher drin, ob das Gerät Bus oder Self 
powered ist etc.

Der eigentliche Transfermodus dürfte im Endpoint Descriptor stehen, oder 
täusche ich mich da?

Edit:

Okay mit Wireshark in Verbindung mit USBPcap habe ich mir das ganze mal 
angesehen. Im Inteface Desciptor "class CDC data" gibt es zwei Endpoint 
Descriptors für die Datenübertragung und beide sind wie erwartet im 
Bulk-Modus ;)

: Bearbeitet durch User
von TomA (Gast)


Lesenswert?

Hallo Andi,

der Transfertyp steht, bei Offset 3, als "bmAttributes" im 
Endpunkt-Descriptor.

Mögliche Werte: 00=Control, 01=isochron, 10=Bulk und 11=interrupt. Bei 
USB2.0 werden auch die Bits 2...5 benutzt, näheres findest du in der 
Spezifikation dazu.

Gruß. Tom

von Andi K. (fry12)


Lesenswert?

Um das Ganze nochmal zu vervollständigen für alle Interessierten:

In der Datei udi_cdc.h des Atmel Software Frameworks steht die 
Festlegung der Transfermodi der beiden Data Endpoints:
1
#define UDI_CDC_DATA_DESC_COMMON \
2
   .iface.bLength                = sizeof(usb_iface_desc_t),\
3
   .iface.bDescriptorType        = USB_DT_INTERFACE,\
4
   .iface.bAlternateSetting      = 0,\
5
   .iface.bNumEndpoints          = 2,\
6
   .iface.bInterfaceClass        = CDC_CLASS_DATA,\
7
   .iface.bInterfaceSubClass     = 0,\
8
   .iface.bInterfaceProtocol     = 0,\
9
   .ep_in.bLength                = sizeof(usb_ep_desc_t),\
10
   .ep_in.bDescriptorType        = USB_DT_ENDPOINT,\
11
   .ep_in.bmAttributes           = USB_EP_TYPE_BULK,\
12
   .ep_in.bInterval              = 0,\
13
   .ep_out.bLength               = sizeof(usb_ep_desc_t),\
14
   .ep_out.bDescriptorType       = USB_DT_ENDPOINT,\
15
   .ep_out.bmAttributes          = USB_EP_TYPE_BULK,\
16
   .ep_out.bInterval             = 0,

Das Ganze ist sehr verschachtelt und unübersichtlich, aber irgendwann 
kommt man doch zu der eigentlichen Definition ;)

Jim Meba schrieb:
> Hätte ich auch gedacht - bis eine einfache XOR 8 Bit Prüfsumme einen
> subtilen Fehler in einem CDC Code Beispiel für NXPs LPC1768 aufdeckte.
> Auch eigene Fehler sind mit Checksumme oft leichter zu finden.

Okay, das ist interessant. D.h. du würdest sicherheitshalber trotzdem 
eine CRC Checksumme vorschlagen?

von uwe (Gast)


Lesenswert?

Zu Daten senden brauchst du aber trotzdem ein Protokoll, sonst weiß du 
ja nicht wann ein Datenpaket anfäng und Aufhört.

von Andi K. (fry12)


Lesenswert?

uwe schrieb:
> Zu Daten senden brauchst du aber trotzdem ein Protokoll, sonst weiß du
> ja nicht wann ein Datenpaket anfäng und Aufhört.

Das ist schon klar, ein Protokoll ist auch vorhanden. Mir geht es jetzt 
nur um die Frage, ob eine CRC benötigt wird oder ob die "interne" CRC16, 
die bei Bulk-Transfers genutzt wird, ausreichend ist.

von Andi K. (fry12)


Lesenswert?

Hat keiner Erfahrung mit USB Bulk Transfers bezüglich sicherer 
Datenübertragung und ob eine zusätztliche CRC/Prüfsumme o.Ä. verwendet 
werden sollte?

von W.S. (Gast)


Lesenswert?

Andi K. schrieb:
> Hat keiner Erfahrung mit USB Bulk Transfers

Anstatt dich auf umfängliche und leider oftmals nicht wirklich passende 
Libs von anderen zu verlassen ohne diese zu verstehen, solltest du 
besser die geräteseitige Funktionalität von sowas wie virtuellen COM 
Ports usw. verstehen lernen. Ja, ich weiß, die Doku ist auf den ersten 
Blick schwer verdaulich, aber wenn man erst mal das Prinzip verstanden 
hat, dann kommt man eigentlich mit allen USB-Devicecores klar.

Der Knackpunkt liegt m.E. immer wieder auf der Stoßstelle zwischen 
interruptgesteuertem blockweisen Abholen von Daten (dev --> host) und 
dem asynchronen byteweisen Eingeben von zu sendenden Daten von der 
Anwendung in den Treiber. Was da schiefgeht, darf man der eigentlichen 
USB-Funktionalität nicht anlasten, die funktioniert in sich - jedenfalls 
bei Bulk-Transfers - schon sicher.

Wenn du aber ganz besonders sicher gehen willst, dann bleibt dir nix 
anderes übrig, als auf die gesamte Datenübertragung noch ein blockweises 
prüfsummengesichertes Protokoll oben drauf zu setzen.

W.S.

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.