Hallo,
ich brauche mal jemanden, der sich mit USB auskennt. Ich habe ein
eigenes Board mit einem STM32L052x8. Das Board ist recht simpel. Außer
dem STM sind nur ein LDO zwei Eingänge und 4 viel LEDs darauf.
Das Board wird über USB versorgt und das USB ist an den STM verdrahtet.
Siehe Schaltplan. Der 1k5 Widerstand an D+ ist aktuell nicht bestückt.
Der STM kann diesen intern zuschalten.
Die Software habe ich euch angehängt. Das template (startup code /
linkerscript) habe ich selbst verbrochen. Könnte somit immernoch den ein
oder anderen Fehler haben.
Zur Nutzung des USBs habe ich mir von hier
https://github.com/kcuzner/led-watch
die USB Library rauskopiert und gegenwärtig noch nichts adaptiert. Das
Gerät sollte normal enumerieren.
Direktlink zur USB-Logik:
https://github.com/kcuzner/led-watch/blob/master/common/src/usb.c
Es wird der interne 48 MHz Oszillator mit Clock-Recovery für's USB
genutzt. Der Core/Peripherie läuft vom internen 16 MHz HSI mittels PLL
auf 32 MHz.
Das System scheint soweit auch korrekt zu sein. Sobald der STM seinen
internen Pullup an D+ aktiviert, beginnt der Rechner mit der
Enumerierung. Hierbei wird der Device Deskriptor korrekt ausgelesen. Das
kann ich mir mit Wireshark anschauen.
Das Problem tritt erst auf, sobald der Rechner über das SET_ADDRESS
Kommando eine USB Adresse vergeben will.
In Zeile 747 in usb.c wird die Adresse gesetzt, nachdem die Statusstage
des SET_ADDRESS Kommandos abgeschlossen ist.
1
USB->DADDR=(1<<7)|(last_setup->wValue&0x7F);
Diesen Code habe ich etwas adaptiert. Ursprünglich stnad hier:
1
USB->DADDR|=last_setup->wValue&0x7F;
Das Ergebnis bleibt jedoch das Gleiche:
Mein dmesg output zeigt mir:
1
[May19 19:41] usb 1-11: new full-speed USB device number 39 using
2
xhci_hcd
3
[ +0.123507] usb 1-11: Device not responding to setup address.
4
[ +0.206599] usb 1-11: Device not responding to setup address.
5
[ +0.206558] usb 1-11: device not accepting address 39, error -71
6
[ +0.123343] usb 1-11: new full-speed USB device number 40 using
7
xhci_hcd
8
[ +0.123458] usb 1-11: Device not responding to setup address.
9
[ +0.206686] usb 1-11: Device not responding to setup address.
10
[ +0.206496] usb 1-11: device not accepting address 40, error -71
11
[ +0.000093] usb usb1-port11: attempt power cycle
12
[ +0.643242] usb 1-11: new full-speed USB device number 41 using
13
xhci_hcd
14
[ +0.000188] usb 1-11: Device not responding to setup address.
15
[ +0.206616] usb 1-11: Device not responding to setup address.
16
[ +0.206475] usb 1-11: device not accepting address 41, error -71
17
[ +0.123383] usb 1-11: new full-speed USB device number 42 using
18
xhci_hcd
19
[ +0.000221] usb 1-11: Device not responding to setup address.
20
[ +0.206570] usb 1-11: Device not responding to setup address.
21
[ +0.206474] usb 1-11: device not accepting address 42, error -71
22
[ +0.000103] usb usb1-port11: unable to enumerate USB device
Wenn ich das Gerät mehrfach ab und anstecke klappt es sporadisch.
Manchmal erst nach einigen versuchen. Manchmal sofort:
1
[May19 19:23] usb 1-10: new full-speed USB device number 122 using
2
xhci_hcd
3
[ +0.123557] usb 1-10: Device not responding to setup address.
4
[ +0.206537] usb 1-10: Device not responding to setup address.
5
[ +0.206590] usb 1-10: device not accepting address 122, error -71
6
[ +0.123298] usb 1-10: new full-speed USB device number 123 using
7
xhci_hcd
8
[ +0.123599] usb 1-10: Device not responding to setup address.
9
[ +0.206508] usb 1-10: Device not responding to setup address.
10
[ +0.206686] usb 1-10: device not accepting address 123, error -71
11
[ +0.000098] usb usb1-port10: attempt power cycle
12
[ +0.643120] usb 1-10: new full-speed USB device number 124 using
13
xhci_hcd
14
[ +0.000189] usb 1-10: Device not responding to setup address.
15
[ +0.206593] usb 1-10: Device not responding to setup address.
16
[ +0.206582] usb 1-10: device not accepting address 124, error -71
17
[ +0.123315] usb 1-10: new full-speed USB device number 125 using
18
xhci_hcd
19
[ +0.018547] usb 1-10: New USB device found, idVendor=16c0,
20
idProduct=05dc, bcdDevice= 0.11
21
[ +0.000013] usb 1-10: New USB device strings: Mfr=1, Product=2,
22
SerialNumber=0
23
[ +0.000007] usb 1-10: Product: LED Wristwatch
24
[ +0.000004] usb 1-10: Manufacturer: kevincuzner.com
25
[ +0.002376] hid-generic 0003:16C0:05DC.001E: hiddev96,hidraw5: USB
26
HID v1.11 Device [kevincuzner.com LED Wristwatch] on usb-
27
0000:00:14.0-10/input0
Um das Problem zu debuggen, habe ich einen Breakpoint an die stelle
gesetzt, wo die Adresse ins USB-Modul geschrieben wird. an dieser Stelle
lese ich exemplarisch im wValue Feld der Setup Anfrage den Wert 15. Kurz
danach beschwert sich Linux, dass das Gerät Adresse 58 nicht akzeptieren
wollte. Ich verstehe das nicht... Ich kann dort nicht die "korrekte"
Adresse sehen.
hat irgendjemand eine Idee? Das treibt mich seit einigen Tagen um und
ich finde einfach keinen Fehler.
Anmerkung:
Ich weiß, dass USB vorschreibt, dass die Adresse erst nach der Status
stage im control kommando gesetzt wird. Das hat bei mir allerdings, als
ich etwas für den STM32F407 geschrieben habe nicht geklappt. Da musste
ich das Adressfeld umgehend beschreiben, damit sich der Host nicht
beschwert. Erhlich gesagt habe ich das nicht verstanden. Zum Test habe
ich das auch hier versucht. Ergebnis: bringt nichts.
Es wäre toll, wenn jemand eine Idee hat. Das einzige, was mich halbwegs
beruhigt, ist dass der Device Deskrtiptor korrekt gelesen wird und auch
das set address kommando zuverlässig erkannt wird. An ein HW Problem
glaube ich aktuell weniger.
(Ja ich weiß, dass ich auch einfach CubeMX oder so nehmen kann.... Aber
nein...)
Vielen Dank
M. H. schrieb:> Ich weiß, dass USB vorschreibt, dass die Adresse erst nach der Status> stage im control kommando gesetzt wird.
genau so ist es auch, Manchmal geht es auch wenn man das ignoriert und
einfach ein kurzes delay einbaut und die addresse direkt beim SetAddress
setzt, aber sauber ist das nicht.
Dein Usb Code ist etwas schwer zu verstehen. Deshalb ein paar Hinweise
- setzt du die USB Addresse wieder auf 0 wenn ein UsbReset kommt?
- USBSetAddress ist ein OutRequest d.h Status ist ein EP0In (ZLP)
Der Ablauf ist wie folgt:
- Setup(SetAddress) // auf Ep0Out mit wLenght == 0;
- EP0In // Status für out
erst dann die die Addresse setzen bevor der EP0In Handler verlassen
wird
Das funktioniert bei mir sowohl auf dem F103 als auch L05X (VCP)
Für dein Problem kann ich mir nur 2 Ursachen vorstellen
- du sendest kein ZLP mit der alten Addresse (normalerweise 0)
- du sendest das ZLP schon mit der neuen Addresse.
Edit: Ein USBReset kann während der Enum ein paar mal auftreten.
Hallo,
vielen Dank für die Antwort.
Thomas Z. schrieb:> - setzt du die USB Addresse wieder auf 0 wenn ein UsbReset kommt?
Ja. In usb.c:834 wird das DADDR Register zurückgesetzt.
Thomas Z. schrieb:> - USBSetAddress ist ein OutRequest d.h Status ist ein EP0In (ZLP)
Auch dies wird gemacht.
Thomas Z. schrieb:> - du sendest kein ZLP mit der alten Addresse (normalerweise 0)> - du sendest das ZLP schon mit der neuen Addresse.
Das ZLP wird gesendet und im Transmission complete des ZLP wird dann die
Adresse umkonfiguriert. ICh werde da mal noch ein wenig rumbasteln. Aber
wirklich nen Plan habe ich noch nicht.
Wie gesagt: Das ist fertiger Code aus einem wohl funktionierendem
Projekt. Aber ich versuche es nochmal.
Thomas Z. schrieb:> M. H. schrieb:>> Transmission complete>> das geht zwar ist aber nicht das gleiche wie EP0In Interrupt. Ich> filtere im EP0 In Interrupt auf SetAddress.
So habe ich es jetzt umgeschrieben. Es kommt das Setup Paket rein.
Controller erkennt, dass es sich um set Address handelt und sendet ein
ZLP. Nach dem schreiben des ZLP wir dann direkt das Adress-register
umprogrammiert. Ergebnis ist das gleiche: Mehrere male an und abstecken
führen sporadisch zum Ziel. Aber zuverlässig geht da nichts.
M. H. schrieb:> Es wird der interne 48 MHz Oszillator mit Clock-Recovery für's USB> genutzt.
Bin mir bei einem/diesem speziellen Controller nicht sicher
da ich das Datenblatt nicht durchforstet habe aaaaaber:
USB in Zusammenhang mit internen Oszillatoren halte ich immer
für wenig stabil und zuverlässig.
Ein interner Oszillator wird immer mehr oder weniger stark vor
sich hindriften, im Gegensatz zu einem Quarzoszillator. Auch
wenn das Datenblatt evtl. verspricht dass es möglich ist damit
USB zu betreiben.
beden kendräger schrieb:> Ein interner Oszillator wird immer mehr oder weniger stark vor> sich hindriften, im Gegensatz zu einem Quarzoszillator. Auch> wenn das Datenblatt evtl. verspricht dass es möglich ist damit> USB zu betreiben.
Deswegen synchronisiert sich dieser Oszillator auf den SOF des USBs und
trimmt sich automatisch nach.
M. H. schrieb:> Deswegen synchronisiert sich dieser Oszillator auf den SOF des USBs und> trimmt sich automatisch nach.
Und das funktioniert auch zuverlässig, habe ich auf einem L073 getestet.
Thomas Z. schrieb:> das geht zwar ist aber nicht das gleiche wie EP0In Interrupt. Ich> filtere im EP0 In Interrupt auf SetAddress.
Nochmal genau gefragt: Es gibt keinen In Interrupt. Soweit ich die
Register durchwühlt habe gibt es nur einen Transmission complete
interrupt. Sowohl für out, als auch für in.
Was genau meinst du mit EP0 In interrupt? Ein Interrupt, der ausgelöst
wird, sobald das IN token empfangen wird?
was ich seltsam fnde ist deine USB Addresse. Setz mal einen BP direkt
auf die den SetAddress Request. Dann solltest du auch die gleiche
Addresse in wValue sehen wie unter Linux.
Wie steht dein EP0IN Status wenn der Request kommt NAK ACK oder STALL?
M. H. schrieb:> Nochmal genau gefragt: Es gibt keinen In Interrupt.
natürlich gibt es den. Schau mal ins UsbIntStatus Register. Da gibts
Interrupts für sogut wie alles. Brauchst du z.B für Bulkin auch nur dann
halt nicht auf EP0
Thomas Z. schrieb:> was ich seltsam fnde ist deine USB Addresse. Setz mal einen BP direkt> auf die den SetAddress Request. Dann solltest du auch die gleiche> Addresse in wValue sehen wie unter Linux.
Breakpoint direkt nach dem empfangen des Setup commands. Linux meldet:
1
[ +0.859038] xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
2
[ +0.206619] usb 1-10: device not accepting address 80, error -62
3
[ +0.126687] usb 1-10: new full-speed USB device number 81 using xhci_hcd
4
[ +0.126696] usb 1-10: device descriptor read/64, error -71
5
[ +0.229968] usb 1-10: device descriptor read/64, error -71
6
[ +0.106702] usb usb1-port10: attempt power cycle
7
[ +0.643265] usb 1-10: new full-speed USB device number 82 using xhci_hcd
8
[ +0.000153] usb 1-10: Device not responding to setup address.
9
[ +0.209993] usb 1-10: Device not responding to setup address.
10
[ +0.206499] usb 1-10: device not accepting address 82, error -71
11
[ +0.123349] usb 1-10: new full-speed USB device number 83 using xhci_hcd
12
[ +0.000160] usb 1-10: Device not responding to setup address.
13
[ +0.206616] usb 1-10: Device not responding to setup address.
14
[ +0.206555] usb 1-10: device not accepting address 83, error -71
15
[ +0.000121] usb usb1-port10: unable to enumerate USB device
Adresse im wValue Feld des Setup Pakets: 41
Die restlingen Felder stimmen (bmrequest etc.)
Das EP0R register sieht direkt nach empfang des Setup request wie im
Anang aus. STAT_TX ist 00 => disabled. Die SW würde nach dem Breakpoint
nun dazu übergehen das ZLP für die Statusstage zu konfigurieren.
Thomas Z. schrieb:> natürlich gibt es den. Schau mal ins UsbIntStatus Register. Da gibts> Interrupts für sogut wie alles. Brauchst du z.B für Bulkin auch nur dann> halt nicht auf EP0
Du meisnt vermutlich den Transmission complete interrupt, wenn daten vom
Device an den host gesendet wurden. Einen anderen interrupt sehe ich
nicht. Siehe Register im Anhang.
Thomas Z. schrieb:> CTR in Verbindung mit DIR und EP Nummer> also CTR | DIR | 0 -> EP0In> ein Code ausschitt aus dem VCP Code von WS / Stefan und mir
Genauso wird das gemacht. Der Interrupt kommt auch. Aber es klappt
nicht.
Beim STM32F4 ist da genau die Konstellation, die bei mir nicht geklappt
hat. Da muss ich die Adresse direkt ändern, nachdem ich das ZLP
konfiguriert habe. Wenn ich die Adresse erst ändere, wenn das ZLP raus
ist, dann funktioniert da auch gar nichts.
Stefan ⛄ F. schrieb:> Ich würde hier den Vergleich mit F4 vermeiden, denn der hat eine andere> USB Schnittstelle. Siehe> https://www.st.com/resource/en/application_note/dm00296349-usb-hardware-and-pcb-guidelines-using-stm32-mcus-stmicroelectronics.pdf> Tabelle 3.
Ich weiß. Aber auch da saß ich mehrere Tage, bis ich herausgefunden
habe, dass ich die Adresse nicht im EP0In interrupt konfigurien kann, da
sonst gar nichts funktioniert. Das ist etwas, das ich bis heute nicht
verstanden habe. Aber nachdem ich gemerkt habe, dass ST da sowieso echt
üble Silicon Bugs im USB Modul hat, die nicht im Erratasheet stehen,
hatte ich die Lust an USB verloren und das alles ignoriert.
welche bugs meinst du? F407 ist OTG was naturgemäs aufwändiger ist.
Also im VCP code funktioniert das setzen der Addresse im EPIn0 Handler
problemlos.
nochmal ein codeausschnitt:
1
voidOnEpCtrlIn(void)
2
{
3
if(IsStandardRequest())
4
{
5
trace("IsStandardRequest\n");
6
switch(CMD.SetupPacket.bRequest)
7
{
8
caseUSB_GET_DESCRIPTOR:
9
trace("GET_DESCRIPTOR\n");
10
//if (CMD.TransferLen > 0)
11
DescriptorBlockwiseIn();
12
return;
13
// special case SET_ADDRESS
14
// spec requires that the address should be changed after
Thomas Z. schrieb:> welche bugs meinst du? F407 ist OTG was naturgemäs aufwändiger ist.> Also im VCP code funktioniert das setzen der Addresse im EPIn0 Handler> problemlos.> nochmal ein codeausschnitt:
Ich weiß, dass es so funktionieren sollte. Aber meine erfahrung ist da
anders. Da klappt gar nichts. Und ich weiß nicht warum.
Bugs bzw. features gibt's da viele. Mein Fovorit, der mich 3 Tage
gekostet hat: https://github.com/libopencm3/libopencm3/issues/531
Wenn man auf das FIFO zugreift, darf kein USB Interrupt kommen, in dem
das das Interrupt status register gelesen wird. Sonst verliert das FIFO
ein Wort und baut stattdessen den Wert des Statusregisters ins TX FIFO
ein.
Thomas Z. schrieb:> Also im VCP code funktioniert das setzen der Addresse im EPIn0 Handler> problemlos.
So macht der Code das auch. Exakt so. Aber es funktioniert einfach nicht
:(.
Außer manchmal. Wenn es gut läuft geht es auch mal 3 mal
hintereinanader. Aktuell geht es wieder gar nicht mehr.... Sehr komisch.
Was mich total verwirrt, ist dass das wValue Feld in der Anfrage eine
Adresse zeigt, die mein Kernel nicht meldet. Andere USB Geräte klappen
aber einwandfrei an dem Port. Sogar mit demselben Kabel.
wie gesagt ich hab dein USB nur kurz überflogen kann also nicht viel
darüber sagen. Eie ist denn das Buffersetup gemacht?
Du hast warscheinlich gesehen, dass wir das komplette Setup Packet in
eine variable kopieren. Was ich sagen kann ist dass obiger VCP code
problemlos enumeriert. das ist vielfach von verschiedenen Leuten hier im
Forum getestet worden. Da gibts einige Threats zu. Die Enum war nie ein
Problem.
Das wValue feld bei dir kann ich mir auch nicht erklären.
Thomas Z. schrieb:> wie gesagt ich hab dein USB nur kurz überflogen kann also nicht viel> darüber sagen. Eie ist denn das Buffersetup gemacht?> Du hast warscheinlich gesehen, dass wir das komplette Setup Packet in> eine variable kopieren. Was ich sagen kann ist dass obiger VCP code> problemlos enumeriert. das ist vielfach von verschiedenen Leuten hier im> Forum getestet worden. Da gibts einige Threats zu. Die Enum war nie ein> Problem.>> Das wValue feld bei dir kann ich mir auch nicht erklären.
Das Funktioniert bei mir ähnlich. Sobald ein Setup Paket eintrudelt wird
es in eine "last setup packet" Variable gespeichert. Dann wird geschaut
was es ist.
Bei Device deskriptor wird der Deskriptor gesendet und anschließend auf
ein ACK gewartet.
Bei der adresse wird erstmal gar nichts gemacht sondern direkt in die
Status stage gewechselt (ZLP In auf EP0).
Sobald dann der von dir beschriebene Interrupt kommt, wird geschaut, ob
es eine Status stage war und was das letzte Setup paket war. Wenn das
was gerade gesendet wurde eine Status IN stage war und das letzte Setup
paket ein SET_ADDRESS war, dann wird die Adresse umgebogen.
Deswegen verstehe ich das alles ja auch nicht. Es sieht ganz richtig
aus.
Um nochmal auszuholen: Beim STM32F4 sagt ST:
> Endpoint initialization on SetAddress command> This section describes what the application must do when it receives a
SetAddress command in a SETUP packet.
> 1.Program the OTG_FS_DCFG register with the device address received in the
SetAddress command
> 2.Program the core to send out a status IN packet
Hier schreibt ST, dass man die Adresse vor der status stage setzen soll.
Das ist komplett gegen mein Verständis von USB. Funktioniert aber. Wenn
man die Adresse nach der Status stage setzt geht das nicht.
Leider zeigt mir Wireshark die SET_ADDRESS commands nicht an. Sonst
könnte ich da mal mitsniffen...ICh glaube ich code einfach mal selber
einen USB Treiber und schaue mal, ob ich in die selben Probleme laufe..
M. H. schrieb:> Hier schreibt ST, dass man die Adresse vor der status stage setzen soll.> Das ist komplett gegen mein Verständis von USB.
Den F407 hab ich noch auf meiner Todo Liste.
Ich kenne aber USB Cores wo das genauso wie beschrieben gemacht werden
muss.
Der FX2 von Cypress ist da ein Beispiel. Die haben ein Schattenregister
dafür was dann automatisch ins Adressregister überträgt.
Die ST USB Cores ind ziemlich seltsam um es mal freundlich auszudrücken.
Man merkt dass die einfach einen IP core schlecht angeflanscht haben,
noch dazu mit viel zu wenig USB Mem für die Buffer
Thomas Z. schrieb:> Die ST USB Cores ind ziemlich seltsam um es mal freundlich auszudrücken.> Man merkt dass die einfach einen IP core schlecht angeflanscht haben,> noch dazu mit viel zu wenig USB Mem für die Buffer
Ja. Habe beruflich Kontakt zu ST aus anderen Gründen und habe wegen dem
F4 mal gefragt. Er konnte mir leider nur sagen, dass das kein eigener
Core von ST ist und man dementsprechend nicht reinschauen kann, warum da
so viele Sachen komisch sind. Soweit ich mich erinnere ist das IP von
Synopsis.
Ich habe mal dem Typen geschrieben, von dem ich den USB Code kopiert
habe. Vielleicht hat der ja ne Idee... Ich verweifel hier komplett...
Ein nettes FPGA Projekt für die Zukunft wäre vielleicht mal ein USB
sniffer. USB ist ja ansich nicht sooo sehr Voodoo. Aber ich falle jedes
Mal komplett auf die Schnautze.
Danke aber für die Vorschläge. Ich hoffe irgendjemand hat noch die
zündende Idee...
Da wird mir langsam klar, warum die Nucleo-Board den USB Port gar nicht
nutzen/demonstrieren. Stattdessen setzen diese Baords auf einen externen
USB-UART Adapter (als Bestandteil vom ST-Link).
Hallo zusammen. Ich habe nun eine weitere Erkenntnis gewonnen:
Wenn ich nach dem Empfang des Setup Pakets für Set address einen
Breakpoint platziere und dort nach circa einer halben Sekunde auf
"Continue" klicke, dann enumeriert alles einwandfrei.
Ich habe nun zu Testzwecken ein hartes Delay von ca 0.6 Sekunden
eingefügt. Das Gerät enumeriert nun in 9/10 Fällen.
Kann sich das jemand erklären? Ich bin absolut ratlos.
M. H. schrieb:> Kann sich das jemand erklären? Ich bin absolut ratlos.
Das sieht nach einem Protokolfehler aus. Ich mache bei SetAddress()
gleich ein Ack()
1
voidOnSetup(void)
2
{
3
uint8_trequest;
4
//bool requestError = true; reject all setup packets by default
Ich hab jetzt nicht den ganzen Thread gelesen, aber einen kurzen
Hinweis. Genau diese Stelle hatte ich dazumal im Code von W.S. gefixt.
Der hatte versucht das mit einem Delay zu lösen. Stefan hat das
inzwischen in seinem Code übernommen. Such da mal nach "DeviceAddress".
Nachdem die Adresse vom Host kommt merke ich mir die, sende das ACK
zurück und erst im nächsten Interrupt wird die Adresse in das Register
geschrieben. Macht man das zu früh gehts in die Hose.
Ich weiss nicht ob das jetzt dein Problem löst oder ob ich das falsch
interpretiere, es kam mir nur so bekannt vor.
temp schrieb:> Ich hab jetzt nicht den ganzen Thread gelesen, aber einen kurzen> Hinweis. Genau diese Stelle hatte ich dazumal im Code von W.S. gefixt.> Der hatte versucht das mit einem Delay zu lösen. Stefan hat das> inzwischen in seinem Code übernommen. Such da mal nach "DeviceAddress".> Nachdem die Adresse vom Host kommt merke ich mir die, sende das ACK> zurück und erst im nächsten Interrupt wird die Adresse in das Register> geschrieben. Macht man das zu früh gehts in die Hose.> Ich weiss nicht ob das jetzt dein Problem löst oder ob ich das falsch> interpretiere, es kam mir nur so bekannt vor.
Danke für deinen Beitrag. Das läuft bereits alles so.
1) Es kommt das Setup Paket mit Adresse
2) Es wird ein ACK gesendet
3) In interrupt (ACK ging raus): Adresse wird ins Register übernommen
Das klappt aber nicht wirklich.
Jetzt läuft es so:
1) Es kommt das Setup Paket mit Adresse
2) Es wird hart 0,6 s geartet
3) Es wird ein ACK gesendet
4) In interrupt (ACK ging raus): Adresse wird ins Register übernommen
Das klappt jetzt besser. Aber auch nicht zuverlässig. Irgendwas anderes
muss flasch sein, was da irgendwie das Protokoll total verwurstet.
Leider kann ich den USB Verkehr nicht mitsniffen. Wireshark zeigt nicht
alles an.
temp schrieb:> Genau diese Stelle hatte ich dazumal im Code von W.S. gefixt.
Das erklärt, warum ich gestern das diffuse Gefühl hatte, das wir das
schon einmal hatten.
M. H. schrieb:> Das klappt jetzt besser. Aber auch nicht zuverlässig.
Ich kann dir versichern, dass es ohne delay zuverlässig funktioniert,
wenn man sonst keine anderen relevanten Fehler im Ablauf hat.
ob mit dem Delay wie im Originalcode von WS oder oder so wie es temp
später gefixt hat, mit dem SetAddress hatte der Code nie ein Problem.
Enum klappte immer. Das Delay war auch nie 0.6s lang. Wenn die obige
Sequenz nicht funktioniert würde ich mir das Ack näher anschauen.
M. H. schrieb:> Kann sich das jemand erklären? Ich bin absolut ratlos.
Ohne Logic Analyzer Trace vom Bus ist‘s natürlich Spekulation... aber:
Das Ganze deutet ja irgendwie auf ein Timing Problem hin.
Ich denke der Linux Kernel wird den SetAdress Request wiederholen wenn
vom Device keine Reaktion kommt. Könnte also sein, dass Du mit dem Delay
zufällig zur richtigen Zeit einen Retry vom Host bedienst.
Du hast geschrieben, dass Du den USB Code unverändert kopiert hast. Hast
Du das Timing sonstwie verändert, z.B. durch andere Interrupts, die den
USB IRQ verzögern? Oder machst Du evtl. im IRQ Handler noch andere
Sachen, welche die Laufzeit verlängern, z.B. Debug Traces?
Bedenke, dass für den SetAdress Request spezielle Timing Anforderungen
gelten.
In diesem Zusammenhang noch ein Hinweis: Der F103 USB Core hat m.M.n.
eine Race Condition zw. einem Status OUT (Host ACK an Device) und dem
nächsten SETUP Packet. Laut USB Standard muss ein SETUP Packet immer
ge-ACK-t werden. So lange aber der CTR_Rx IRQ von der Status OUT Stage
noch aktiv ist, wird die Hardware das SETUP Packet ignorieren. Das kann
den Host schon mal verwirren.
Ich erwähne das deshalb: Der Linux Kernel scheint zunächst die ersten
Bytes des Device Descriptors zu lesen, erst dann wird das SetAdress
gemacht. Vielleicht fängt das Problem schon dort an?
Wie gesagt: Letzlich Spekulation ohne LA Trace. Vielleicht sind es aber
doch Gedankenanstöße, die Dich weiter bringen.
Philip S. schrieb:> Ich erwähne das deshalb: Der Linux Kernel scheint zunächst die ersten> Bytes des Device Descriptors zu lesen
Das macht nicht nur Linux so. Der ersre GetDesriptor(Device) findet auf
der Addresse 0 statt und dient im Prinzip dazu Ep0Size zu ermitteln.
EP0Size kann 8 16 32 oder 64 Bytes haben.
Die Enumererierung läuft so ab:
- UsbReset
- UsbGetDescriptor(Device) mit wlenght=8 (linux) oder wLength=0x40 (win)
- UsbReset
- UsbGetDescriptor(Device)
- UsbGetDescriptor(Config) mit (wLength=9)
- UsbGetDescriptor(Config) mit (wLength=wTotalLength)
- UsbGetDescriptor(String)
....
- UsbSetConfig(cfgValue)
zusätzlich sind zumindest unter Win noch Suspend /Resume drin.
Thomas Z. schrieb:> Der ersre GetDesriptor(Device) findet auf> der Addresse 0 statt und dient im Prinzip dazu Ep0Size zu ermitteln.
Interessant, macht ja Sinn, so hatte ich das noch gar nicht gesehen.
macOS schickt als erstes den SetAddress, liest dann die ersten 8 Bytes
des Device Descriptors und fordert dann den Device Descriptor mit der
vom Device gemeldeten Länge an.
Das ist jedenfalls was mein Device sieht; mein LA läuft unter macOS
nicht.
Vor ein paar Wochen lief hier ein Thread, da wurden schon bei der
Takterzeugung Fehler gemacht, die sich so auswirkten, dass mit der
Taktsynchronisierung ueber SOF alles noch schlimmer wurde. Wenn du
sagst, der Code geht bei dem Projekt wo du es her hast, dann würde ich
sowas auch im Auge behalten. Ohne den Takt wirklich mal zu messen würde
ich nicht weiter machen.
Guten Tag zusammen,
ich habe das Problem nun "gelöst". Ich habe den Code aus dem Internet in
die Tonne gekloppt und es selbst gemacht. Mehr als die Enumerierung
steht zwar noch nicht, aber diese klappt ohne Probleme.
IMHO, macht der Code aus dem Netz genau das Gleiche. Aber irgendein
Detail muss anders sein.
Bei weiteren Problemen melde ich mich.
Vielen Dank für die Hinweise, auch wenn sie nicht zum Ziel geführt
haben.