Forum: Mikrocontroller und Digitale Elektronik PIC32MZ: Problem bei USB-Enumeration


von Charly (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche derzeit eine USB-Verbindung zwischen einem 
PIC32MZ2048EFH064 Mikrocontroller (USB Device) und einem Windows 10 PC 
(USB Host) herzustellen.

Im Grunde genommen sieht es schon gar nicht so schlecht aus. Das Device 
wird im Gerätemanager angezeigt, allerdings mit dem Hinweis, dass es 
nicht gestartet werden kann (Code 10). Anhand der Ergebnisse mehrerer 
Software USB Sniffer (siehe Screenshots) bin ich der Meinung, dass die 
Deskriptoren korrekt übertragen werden. Nach deren Übertragung fragt der 
Host dann den Device Status ab, woraufhin die Verbindung scheinbar 
abgebrochen wird.

Für die gleiche Hardware habe ich eine andere Software auf Basis von 
Harmony 3 (gleiche Clocksettings), mit der das Ganze funktioniert. 
Deshalb schließe ich Hardwareprobleme bzw. Oszillatoreinstellungen aus. 
Es muss sich um ein Softwareproblem handeln.

Ich wäre über jeden Tipp dankbar, da ich nicht mehr weiß, was ich noch 
ausprobieren könnte. Vielen Dank für eure Hilfe!

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Versuch's mal mit Linux, die Meldungen des Linux Kernel sind oft relativ 
hilfreich. Mit Wireshark kann man USB ebenfalls ganz gut debuggen.

Sicher dass du auf Get Status korrekt antwortest?

von Charly (Gast)


Lesenswert?

Ich habe das Problem anscheinend gefunden. Wenn ich den Configuration 
Descriptor wie folgt abändere, funktioniert es:

uint8_t USB_ConfigurationDescriptor[] = {
/* bLength                                  */ 
USB_CONFIGURATION_DESCRIPTOR_LENGTH,
/* bDescriptorType                          */ 0x02,
/* wTotalLength                             */ 
USB_CONFIGURATION_DESCRIPTOR_LENGTH,0x00,
/* bNumInterfaces              */ 0,
/* bConfigurationValue            */ 1,
/* iConfiguration              */ 0,           // no string
/* bmAttributes                             */ 0xC0,        // 
self-powered
/* bMaxPower                */ 0x00
};

So habe ich zwar noch kein Interface bzw. keine Endpoints definiert, 
aber immerhin klappt schonmal die Enumeration. Dann versuche ich jetzt 
mal das Interface und die Enpoints mit zu übergeben.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Charly schrieb:
> Ich habe das Problem anscheinend gefunden.

Ah, ja logisch, so wie es ursprünglich war kann es nicht funktionieren. 
Der Configuration-Deskriptor muss die Interface- und 
Endpoint-Deskriptoren mit enthalten, als ein großer Block. Dieser Block 
wird dann "am Stück" abgefragt.

Die einzelnen Interface/Endpoint-Deskriptoren werden nicht explizit 
abgefragt. Der Code dafür ist also überflüssig. In der USB-Spec heißt 
es:

"The standard request to a device supports three types of descriptors: 
device (also device_qualifier), configuration (also 
other_speed_configuration), and string."

PS: USB-Tutorial mit STM32 gesehen?

von Charly (Gast)


Lesenswert?

Niklas G. schrieb:
> Ah, ja logisch, so wie es ursprünglich war kann es nicht funktionieren.
> Der Configuration-Deskriptor muss die Interface- und
> Endpoint-Deskriptoren mit enthalten, als ein großer Block. Dieser Block
> wird dann "am Stück" abgefragt.

Ja genau, das habe ich mittlerweile auch woanders gesehen. Wenn ich das 
allerdings versuche, schlägt die Enumeration wieder fehl. So sieht mein 
Deskriptor nun aus, wobei USB_CONFIGURATION_DESCRIPTOR_wTotalLength = 25 
ist:
1
uint8_t USB_ConfigurationDescriptorFull[] = {
2
/* bLength                                  */ USB_CONFIGURATION_DESCRIPTOR_LENGTH,
3
/* bDescriptorType                          */ 0x02,
4
/* wTotalLength                             */ USB_16bitTo8bitArrange(USB_CONFIGURATION_DESCRIPTOR_wTotalLength),
5
/* bNumInterfaces              */ 1,
6
/* bConfigurationValue            */ 1,
7
/* iConfiguration              */ 0,                                   // no string
8
/* bmAttributes                             */ 0x80 | 0x40,                         // self-powered
9
/* bMaxPower                */ 0,
10
  
11
/* bLength                                  */ USB_INTERFACE_DESCRIPTOR_LENGTH,
12
/* bDescriptorType                          */ 0x04,
13
/* bInterfaceNumber                         */ 0x00,
14
/* bAlternateSetting            */ 0,
15
/* bNumEndpoints              */ 1,
16
/* bInterfaceClass              */ 0xff,        // vendor specific
17
/* bInterfaceSubClass            */ 0xff,
18
/* bInterfaceProtocol            */ 0xff,
19
/* iInterface                */ 0,           // no string
20
21
/* bLength                                  */ USB_ENDPOINT_DESCRIPTOR_LENGTH,
22
/* bDescriptorType                          */ 0x05,
23
/* bEndpointAddress                         */ 1 | 0x00,
24
/* bmAttributes                             */ 0x02,
25
/* wMaxPacketSize              */ USB_16bitTo8bitArrange(MAIN_SPI_RX_BUFFER_SIZE),
26
/* bInterval                */ 1
27
};

Deshalb folgende Frage: Bin ja gerade erstmal nur an der Enumeration 
dran. Das heißt ich teile dem Host mit, dass es ein Interface mit einem 
zusätzlichen Endpunkt 1 gibt. Innerhalb des Mikrocontrollers exisitert 
der Endpunkt 1 aber noch nicht. Könnte das ein Problem sein? Nach dem, 
was ich gelesen habe, versucht der Host ja zunächst gar nicht diesen 
Endpunkt zu erreichen, oder?

von Charly (Gast)


Lesenswert?

Niklas G. schrieb:
> PS: USB-Tutorial mit STM32 gesehen?

Das habe ich schonmal überflogen, weil ich ursprünglich auch einen 
STM32-Controller verwenden sollte. Allerdings benötige ich USB Hi-Speed, 
STM32 unterstützt von Haus aus allerdings nur Full Speed. Ich werde 
nochmal in dem Artikel lesen, vielleicht finde ich was Hilfreiches.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Charly schrieb:
> Könnte das ein Problem sein? Nach dem,
> was ich gelesen habe, versucht der Host ja zunächst gar nicht diesen
> Endpunkt zu erreichen, oder?

Das tut er wenn erst nach SET_CONFIGURATION. Wie gesagt: Schließ das 
Gerät einfach mal an einen Linux-Host an und schau dir die 
"dmesg"-Ausgabe an. Wenn du Glück hast sagt es dir direkt was falsch 
ist.

Charly schrieb:
> Allerdings benötige ich USB Hi-Speed,
> STM32 unterstützt von Haus aus allerdings nur Full Speed.

Die STM32F7x3 haben einen integrierten USB HS PHY. Viele weitere STM32 
wie die STM32F407 haben einen USB HS Controller, brauchen aber einen 
externen USB HS PHY der über ULPI angebunden wird.

von Thomas Z. (usbman)


Lesenswert?

Folgendes habe ich im UsbAudio Thread geschrieben:

Am wichtigsten ist erst mal, dass im Config Deskriptor die wTotalLength 
korrekt ist. Falls das nicht stimmt gibt es alle möglichen lustigen 
Fehler. Ansonsten gibt UsbDevView ja schon Hinweise und Warnungen aus.
Wenn ein Device gar nicht gefunden wird weil es nicht durch die Enum 
kommt kann der Fehler nur daran liegen, dass mindestens einer der unten 
beschriebenen Requests nicht so funktioniert wie er sollte.
Damit die Enum funktioniert müssen folgende Requests funktionieren
1. Getdescriptor für Device und Config
2. SetAddress
3. SetConfig
Danach kann usbview auch was anzeigen.
Ein Getdescriptor muss auch mit seltsamen Angaben im wLength Feld 
umgehen können und der Host kann jederzeit einen Request abbrechen wenn 
er keine Lust mehr hat mehr Daten zu lesen.

Ich würde im ersten Schritt erst mal alle Konstanten in den Deskriptoren 
überprüfen. Danach anstelle USB_16bitTo8bitArrange die Werte manuell in 
little Endian setzen.

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.