USB HID Device mit STM32F042

OP Persönliche Seite #7303144
Lesenswert?

Hallo zusammen,

erst mal allen ein frohes neues Jahr 2023 mit Glück, Gesundheit und lieferbaren Bauteilen!

Ich habe versucht, den USB-Code von W.S. auf dem STM32F042 zum Laufen zu bringen und auf ein reines HID-Device umzubauen. Das Gerät wird inzwischen sauber enumeriert, sowohl Windows als auch Linux sind damit prinzipiell zufrieden.

Ich möchte auf EP1 Reports mit 64 Byte Größe senden (und in einem zweiten Schritt empfangen). Der Host pollt auch fröhlich, aber ich schaffe es absolut nicht, eine Antwort zu senden.

Beobachtungen:

  • Double Filtering hatte ich mal aktiviert, aber inzwischen auskommentiert.
  • Wenn ich den EP Type korrekt auf "3" für "Interrupt" stelle, löst der IRQ-Handler nicht aus. Wenn ich den EP Type (inkorrekt) auf "2" für "ISO" stelle, löst der IRQ-Handler aus, aber Linux beschwert sich mit -71 über einen Protokollfehler.
  • Wenn ich in OnEpIntIn() versuche, zu antworten, scheinen immer 0 Byte auf der Host-Seite anzukommen, auch wenn ich die Länge auf die (korrekten) 64 stelle. Ob ich (entgegen dem User Manual) die oberen Bits von USB_COUNTn_TX (also BL_SIZE und NUM_BLOCKS) auch noch setze, ist dabei egal.
  • Ich habe User Manual, USB in a Nutshell, eccelerator.com, usbmon, Beyond Logic, jede Menge Forenbeiträge und natürlich das USB-Tutorial von µC.net durch. Man werfe mir also gerne Blödheit vor, aber nicht Faulheit...

Der (mit dem beiliegenden Skript etwas aufgepeppte) Trace von usbmon sieht wie unten aus. Problematisch wird es nach dem letzten "Callback Control In" (das ist die Antwort auf die Frage nach dem HID Descriptor).

Hat jemand der Anwesenden einen heißen Tipp, wo ich noch schauen könnte? Langsam bin ich echt frustriert. Ach so: CubeMX ist mindestens genauso frustrierend, und auf CDC zurück will ich nicht[1].

Vielen Dank! Max

1
>>  Ci:1:000:0 s 80 06 0100 0000 0040 64 < [submission Control In]
2
<<  Ci:1:000:0 0 18 = 12010002 00000040 addeefbe 00010102 0301 [callback Control In]
3
12 01 00 02 00 00 00 40 ad de ef be 00 01 01 02 03 01
4
>>  Co:1:000:0 s 00 05 0006 0000 0000 0 [submission Control Out]
5
0006
6
006:
7
>>  Ci:1:006:0 s 80 06 0100 0000 0012 18 < [submission Control In]
8
<<  Ci:1:006:0 0 18 = 12010002 00000040 addeefbe 00010102 0301 [callback Control In]
9
12 01 00 02 00 00 00 40 ad de ef be 00 01 01 02 03 01
10
>>  Ci:1:006:0 s 80 06 0600 0000 000a 10 < [submission Control In]
11
<<  Ci:1:006:0 -32 0 [callback Control In]
12
>>  Ci:1:006:0 s 80 06 0600 0000 000a 10 < [submission Control In]
13
<<  Ci:1:006:0 -32 0 [callback Control In]
14
>>  Ci:1:006:0 s 80 06 0600 0000 000a 10 < [submission Control In]
15
<<  Ci:1:006:0 -32 0 [callback Control In]
16
>>  Ci:1:006:0 s 80 06 0200 0000 0009 9 < [submission Control In]
17
<<  Ci:1:006:0 0 9 = 09022900 010100c0 0e [callback Control In]
18
09 02 29 00 01 01 00 c0 0e
19
>>  Ci:1:006:0 s 80 06 0200 0000 0029 41 < [submission Control In]
20
<<  Ci:1:006:0 0 41 = 09022900 010100c0 0e090400 00020300 00000921 10010001 22200007 05010340 [callback Control In]
21
09 02 29 00 01 01 00 c0 0e 09 04 00 00 02 03 00 00 00 09 21 10 01 00 01 22 20 00 07 05 01 03 40
22
>>  Ci:1:006:0 s 80 06 0300 0000 00ff 255 < [submission Control In]
23
<<  Ci:1:006:0 0 4 = 04030904 [callback Control In]
24
04 03 09 04
25
>>  Ci:1:006:0 s 80 06 0302 0409 00ff 255 < [submission Control In]
26
<<  Ci:1:006:0 0 32 = 20035500 53004200 20005600 69007200 74007500 61006c00 44006500 6d006f00 [callback Control In]
27
20 03 55 00 53 00 42 00 20 00 56 00 69 00 72 00 74 00 75 00 61 00 6c 00 44 00 65 00 6d 00 6f 00
28
>>  Ci:1:006:0 s 80 06 0301 0409 00ff 255 < [submission Control In]
29
<<  Ci:1:006:0 0 8 = 08034d00 61007800 [callback Control In]
30
08 03 4d 00 61 00 78 00
31
>>  Ci:1:006:0 s 80 06 0303 0409 00ff 255 < [submission Control In]
32
<<  Ci:1:006:0 0 26 = 1a034e00 54003200 30003000 39003100 30003100 34003000 3000 [callback Control In]
33
1a 03 4e 00 54 00 32 00 30 00 30 00 39 00 31 00 30 00 31 00 34 00 30 00 30 00
34
>>  Co:1:006:0 s 00 09 0001 0000 0000 0 [submission Control Out]
35
<<  Co:1:006:0 0 0 [callback Control Out]
36
>>  Ci:1:006:0 s 80 06 0303 0409 00ff 255 < [submission Control In]
37
<<  Ci:1:006:0 0 26 = 1a034e00 54003200 30003000 39003100 30003100 34003000 3000 [callback Control In]
38
1a 03 4e 00 54 00 32 00 30 00 30 00 39 00 31 00 30 00 31 00 34 00 30 00 30 00
39
>>  Co:1:006:0 s 21 0a 0000 0000 0000 0 [submission Control Out]
40
<<  Co:1:006:0 0 0 [callback Control Out]
41
>>  Ci:1:006:0 s 81 06 2200 0000 0020 32 < [submission Control In]
42
<<  Ci:1:006:0 0 32 = 05010900 a1011500 26ff0085 01750895 40090081 82850275 08954009 009182c0 [callback Control In]
43
05 01 09 00 a1 01 15 00 26 ff 00 85 01 75 08 95 40 09 00 81 82 85 02 75 08 95 40 09 00 91 82 c0
44
>>  Ii:1:006:1 -115:8 65 < [submission Interrupt In]
45
<<  Ii:1:006:1 0:8 0 [callback Interrupt In]
46
>>  Ii:1:006:1 -115:8 65 < [submission Interrupt In]
47
<<  Ii:1:006:1 -71:8 0 [callback Interrupt In]
48
>>  Ii:1:006:1 -115:8 65 < [submission Interrupt In]
49
<<  Ii:1:006:1 -71:8 0 [callback Interrupt In]
50
>>  Ii:1:006:1 -115:8 65 < [submission Interrupt In]
51
<<  Ii:1:006:1 -71:8 0 [callback Interrupt In]
52
>>  Ii:1:006:1 -115:8 65 < [submission Interrupt In]
53
<<  Ii:1:006:1 -71:8 0 [callback Interrupt In]

[1] CDC ist wie der Sylt-Shuttle: man setzt sich ins Auto, um Zug zu fahren. Ich will aber einfach nur Zug fahren ;)

Angehängte Dateien:
OP Persönliche Seite #7303673
Lesenswert?

Hallo Thomas usbman,

danke für die Unterstützung. Mit deiner Hilfe bin ich weiter gekommen. Bei Full Speed können maximal 64 Byte in einem Paket übertragen werden, ich habe deshalb die Report Size auf 63 reduziert.

Es sieht aus, als funktioniere nun endlich die Kommunikation. Extrem verwirrend war, dass der Linux-Kernel mit dem Pollen bei Interrupts wohl erst dann anfängt, wenn man einmal was auf das Device geschrieben hat - aber vielleicht ist das Problem auch nur irgendwo zwischen Kernel, USB-Spec, usblib, hidapi und Python versteckt. Oder ich habe doch noch irgendwo einen Wurm drin. Aber nun kommen die Pakete und Interrupts auch mit dem korrekten Endpoint Type.

Mit Windows habe ich noch nicht getestet. Morgen ist auch noch ein Tag :)

Viele Grüße,

Max

(der sich viel, viel mehr freut, als aus diesem eher nüchternen Post herauszulesen ist. Ich habe jetzt vier Tage mit dem blöden USB gekämpft).

Gast #7305633
Lesenswert?

Wenn der Report keine ReportID verwendet (= 0), dann rechnet die auch nicht zur Reportlänge dazu.

Der ST USB-Stack hat aber zwei spaßige Fehler die wir ST auch mitgeteilt haben, die aber bisher in der Library nicht behoben wurden.

Einer davon betrifft bidirektionale Interrupt-Endpoints. Da kann mittendrin plötzlich die Senderichtung einfrieren, weil die Interrupt-Routine immer beide Interrupt-Flags, also für In und Out gleichzeitig löscht.

OP Persönliche Seite #7305672
Lesenswert?

Guido Körber schrieb:

Wenn der Report keine ReportID verwendet (= 0), dann rechnet die auch nicht zur Reportlänge dazu.

Hallo Guido,

ja, danke. Im Moment bin ich ganz froh, dass es überhaupt funktioniert. Der Rauswurf des (letztendlich unnötigen) Report Descriptors kommt dann in v 0.02 :)

Der ST USB-Stack hat aber zwei spaßige Fehler die wir ST auch mitgeteilt haben, die aber bisher in der Library nicht behoben wurden.

Ach ja, ST und CubeMX. Wenn ich recht überlege, habe ich bis jetzt jedes Mal am Ende den CubeMX-Code rausgeworfen und nur die HAL genommen. Bloaty (ohne -Os eigentlich nie zu linken), buggy (siehe dein Beispiel) und schlecht dokumentiert (habe zwei Tage gesucht, warum CAN nicht funktioniert).

Deswegen habe ich (nach einem vegeblichen Versuch, das zu Fuß zu stricken) auf die Library von W.S. aus dem Forum hier aufgesetzt und der das Rauchen, nein das CDC abgewöhnt.

Grüße und frohes neues Jahr,

Max

Gast #7306112
Lesenswert?

Max G. schrieb:

Deswegen habe ich (nach einem vegeblichen Versuch, das zu Fuß zu stricken) auf die Library von W.S. aus dem Forum hier aufgesetzt und der das Rauchen, nein das CDC abgewöhnt.

Hier im Forum gibt es ja einige die sich mit dem Code von W.S. ausgiebig beschäftigt haben und ihn auch benutzen. Vor einiger Zeit hatte ich hier auch mal ein Beispiel für eine Midi-Implementierung eingestellt. Es wäre jedenfalls schön, wenn du am Ende hier ein funktionierendes Beispiel einstellen könntest.

Gast #7306437
Lesenswert?

Max G. schrieb:

ja, danke. Im Moment bin ich ganz froh, dass es überhaupt funktioniert. Der Rauswurf des (letztendlich unnötigen) Report Descriptors kommt dann in v 0.02 :)

Nicht den Descriptor raus werfen, nur das Element für die ReportID. Das ist 0x85 gefolgt von einem Byte für die ID.

Wenn der Descriptor fehlt, wird das Device nicht enumeriert.

Den USB-Stack von ST haben wir mittlerweile recht gründlich umgegraben, der kann jetzt mehr und braucht deutlich weniger Platz :)

OP Persönliche Seite #7306683
Lesenswert?

Guido Körber schrieb:

Nicht den Descriptor raus werfen, nur das Element für die ReportID.

Ja, ist klar. Da hatte ich mich falsch ausgedrückt. Nicht enumerierende Devices hatte ich drei Tage lang, damit bin ich vorerst versorgt.

Im Moment lasse ich die Report ID aber drin. Es muss ja noch Potenzial bestehen. :)

temp schrieb:

Es wäre jedenfalls schön, wenn du am Ende hier ein funktionierendes Beispiel einstellen könntest.

Das ist selbstverständlich. Ich habe noch aufgeräumt, Ergebnis ist nun hier: Beitrag "USB mit HID für STM32"

Gast #7307513
Lesenswert?

Harry L. schrieb:

Kann man sich das irgendwo anschauen?

Nur als fertiges Produkt :)

Die Bugs haben wir an ST gemeldet, da waren zwei Klöpse drin die gefährlich werden können, wenn das in irgend etwas wichtigem passiert. Also so wie bei Kunden von uns, die damit z.B. Joysticks bauen und teilweise sehr große Maschinen steuern. Wenn da mitten im Betrieb der Controller absäuft, dann ist das nicht so witzig.

Die konstruktiven Änderungen sind aber unser Know How, das gibt es nicht als Code, sondern nur im Produkt.

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