PIC32MZ: Problem bei USB-Enumeration

Gast #6389242
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!
Angehängte Dateien:
Gast #6389396
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.
Persönliche Seite #6389420
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?
Gast #6389635
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?
Persönliche Seite #6389695
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.
#6390122
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren