Forum: Mikrocontroller und Digitale Elektronik An W.S.: Läuft deine USB Implementierung auch auf STM32F303?


von Stefan F. (Gast)


Lesenswert?

Hallo W.S., wie du weisst, nutze und empfehle ich gerne deine USB 
Implementierung. Hast du diese schon einmal auf einem STM32F303 
ausprobiert? Ich würde gerne dokumentieren, ob das geht.

von Jitterer (Gast)


Lesenswert?

Um weiche implementierung geht es?

von Stefan F. (Gast)


Lesenswert?

Jitterer schrieb:
> Um welche Implementierung geht es?

Diese: Beitrag "Re: STM32F4 USB CDC"

Oder falls er für den STM32F303 eine andere veröffentlicht hat, würde 
ich sie gerne weiter empfehlen.

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

Stefanus F. schrieb:
> Hast du diese schon einmal auf einem STM32F303
> ausprobiert?

Nö. Aber einer für den STM32F302 ist mit dabei. Ich nehme mal an, daß 
diese Version ohne großartige Änderungen auch auf dem F303 läuft. 
Allenfalls müssen die Leute, die den GCC benutzen, sich um dessen 
Eigenheiten kümmern. Irgendwo hab ich auch noch eine Version für den 
LPC4088 herumfliegen, falls da ein dediziertes Interesse besteht. 
Ansonsten ist die weitestgehend baugleich zu der für den LPC1751, 
lediglich die Mechanik mit dem INAK_BI funktioniert beim LPC4088 nicht, 
weswegen ich da ein "Software-INAK_BI" eingebaut habe.

W.S.

von Stefan F. (Gast)


Lesenswert?

Vielen Dank!

von Stefan F. (Gast)


Lesenswert?

Das ist übrigens der gleiche Code, wie der von 2015 für STM32F103.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo W.S.,

ich habe gerade das Nucleo-F303RE Board erhalten und konnte die USB-CDC 
Implementierung der HAL erfolgreich testen. Daraus schliesse ich, dass 
keine Hardware Ok ist. Sie besteht nur auf einem abgeschnittenen USB 
Kabel und einem Pull-Up Widerstand and DP, den ich mit 3,3V verbunden 
habe.

Nun probiere ich deinen Code aus, den ich wegen seiner Kompaktheit 
bevorzugen würde.

Ein paar Zeilen musste ich für meine Entwicklungsumgebung (Eclipse, gcc, 
AC6 Tools) anpassen, damit ich den Code compilieren kann. Dabei habe ich 
mich an dem bereits funktionierenden Programm für den STM32F103RB 
orientiert.

Mit ist aufgefallen, dass die Adressen der NVIC Register anders sind - 
habe ich (hoffentlich korrekt) angepasst. Es funktioniert aber noch 
nicht.

Die LED blinkt wie gewünscht. Wenn ich das USB Kabel an den Laptop 
stecke, erscheinen folgende Meldungen (Linux, dmesg):
1
[ 9380.967330] usb 1-3.2: new full-speed USB device number 28 using xhci_hcd
2
[ 9396.500206] usb 1-3.2: device descriptor read/64, error -110
3
[ 9412.117042] usb 1-3.2: device descriptor read/64, error -110
4
[ 9412.304996] usb 1-3.2: new full-speed USB device number 29 using xhci_hcd
5
[ 9427.733833] usb 1-3.2: device descriptor read/64, error -110
6
[ 9443.350617] usb 1-3.2: device descriptor read/64, error -110
7
[ 9443.459037] usb 1-3-port2: attempt power cycle
8
[ 9444.062612] usb 1-3.2: new full-speed USB device number 30 using xhci_hcd
9
[ 9449.158919] xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
10
[ 9454.535186] xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
11
[ 9454.743043] usb 1-3.2: device not accepting address 30, error -62
12
[ 9454.823072] usb 1-3.2: new full-speed USB device number 31 using xhci_hcd
13
[ 9459.915358] xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
14
[ 9465.287711] xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command
15
[ 9465.499570] usb 1-3.2: device not accepting address 31, error -62
16
[ 9465.499933] usb 1-3-port2: unable to enumerate USB device

Ich habe zur Kontrolle einen Breakpoint in den Interrupthandler gesetzt 
und konnte so feststellen, dass er aufgerufen wird, sobald ich das USB 
Kabel an den Laptop stecke. Innerhalb der ISR passiert das:

I = 10111100000000
(I & ERR) ist wahr
(I & SUSP) ist wahr
(I & RESET) ist wahr

Zweiter Aufruf der ISR:

I= 1000000000
(I & SOF) ist wahr

Dritter Aufruf der ISR:

I = 110100000000
(I & SUSP) ist wahr
(I & RESET) ist wahr

Danach wird die ISR nicht mehr angesprungen.

Ich habe den Quelltext und ein Protokoll von Wireshark angehängt, weil 
ich mal gelesen habe, dass dies helfen könnte. Den Inhalt des Protokolls 
kann ich mangels Know-How aber nicht verstehen.

Ich würde mich sehr freuen, wenn du mir helfen könntest, das Ding ans 
Laufen zu bringen. Dann kann ich das funktionierende Projekt zu meiner 
neuen Webseite http://stefanfrings.de/stm32/stm32f3.html hinzufügen.

von W.S. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Ich habe zur Kontrolle einen Breakpoint in den Interrupthandler gesetzt

Das funktioniert nicht. Bei sowas wirst du vom Host binnen weniger ms 
auf Passiv gesetzt und rausgeschmissen. Ich habe nicht umsonst das 
"debugfkt.inc" mit reingegeben. Damit kann man sich diverse Meldungen, 
die man an irgend einer Stelle (oder mehreren) erzeugen will, temporär 
in einen RAM Bereich schreiben und dann anschließend außerhalb des 
Interupthandlers über irgend einen anderen Kanal ausgeben.

Merke: bloß im Int-Handler keine Zeit vertrödeln.

Probiere das ganze doch mal an einem Windows-PC aus und guck dir mit 
usbview an, was der Host vom deinem µC an Descriptor-Paketen gekriegt 
hat.

Wenn da garnix ist, dann stimmt entweder was mit den Interruptnummern 
und Namen nicht oder der USB-Core ist tatsächlich etwas anders als 
erwartet. Oder hast du's mit dem nop() übertrieben?

Ich hab derzeit weder nen F302 noch einen F303 da - geschweige denn auf 
LP gelötet, kann das ganze also momentan nicht nachvollziehen.

W.S.

von Stefan F. (Gast)


Lesenswert?

W.S. schrieb:
> Oder hast du's mit dem nop() übertrieben?

Ich hoffe nicht. Genau so funktioniert es auf dem STM32F103.

Ich versuche morgen mal etwas mit Hilfe von Trace Meldungen 
herauszufinden, damit die ISR zügig durchläuft.

von Stefan F. (Gast)



Lesenswert?

Ich habe jetzt Trace Meldungen eingebaut, die alle Verzweigungen an if() 
und switch() anzeigen (ausser bei "Start of Frame"). Dabei erscheinen 
folgende Meldungen:
1
setup
2
Hello World!
3
(jetzt USB einstecken)
4
ERR
5
SUSP
6
RESET
7
CTR
8
DIR
9
logEpCtrl
10
SETUP
11
isStandardReques
12
GET_STATUS
Soweit ich dem Wireshark Trace entnehme, antwortet der µC jedoch nicht 
auf den GET DESCRIPTOR Request.

Beitrag #5761466 wurde von einem Moderator gelöscht.
Beitrag #5761482 wurde von einem Moderator gelöscht.
von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Mehr Trace Meldungen bringen mich leider nicht weiter. Ich erkenne die 
Problemursache nicht, weil ich den Soll-Zustand nicht kenne.
1
setup
2
InitEndpoints
3
setAddr adr=0
4
Hello World!
5
(USB Kabel einstecken)
6
ERR
7
SUSP
8
RESET
9
InitEndpoints
10
setAddr adr=0
11
CTR
12
DIR
13
logEpCtrl
14
SETUP
15
rdCtrlBlock maxlen=8
16
clrBuf logEpNum=0
17
isStandardRequest
18
GET_STATUS
19
doGetStatus for 00
20
forElse
21
stall
22
Hello World!
23
CTR
24
DIR
25
logEpCtrl
26
SETUP
27
rdCtrlBlock maxlen=8
28
clrBuf logEpNum=0
29
isStandardRequest
30
GET_STATUS
31
doGetStatus for 00
32
forElse
33
stall

von Stefan F. (Gast)


Lesenswert?

Hurra, ich habe etwas greifbares gefunden: In der Funktion 
ReadControlBlock ist count immer 0.

Das ist gar kein GET_STATUS Request, es sieht  nur so aus, weil der CMD 
Puffer voller Nullen ist und 0 zufällig der Wert von GET_STATUS ist.

Ich bin ziemlich sicher, dass der Code zum USB Interface des STM32F303 
passen müsste, weil ich beim Vergleich mit dem Referenzhandbuch keine 
Abweichungen gefunden habe. Ich konnte alle Registerzugriffe in der Doku 
wieder finden und umgekehrt habe ich kein relevantes Register/Bit 
gefunden, das eventuell noch gesetzt werden muss.

WS, kannst du mir helfen, heraus zu finden, warum ReadControlBlock nur 0 
Bytes liest?

von W.S. (Gast)


Lesenswert?

Stefanus F. schrieb:
> In der Funktion
> ReadControlBlock ist count immer 0.

Nanana.. du hast dich offenbar auf einen ACK vom Host gesetzt.

Also, bei einem EP-Interrupt wird der Endpointstatus aus den 
USB_EpRegs(EpNum) gelesen. Und wenn dort das SETUP Bit (1<<11) gesetzt 
ist, dann HAT der Host 8 Byte in den µC transferiert. Wenn nicht, dann 
ist das bloß ein leerer Block vom Host, der als ACK dient - und dann 
wird auch nicht OnSetup aufgerufen, sondern OnEpCtrlOut. Und das dient 
lediglich dazu, den evtl. vorhandenen Rest an Daten in weiteren Blöcken 
zum Host zu schaufeln.

W.S.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Ich hab den Fehler gefunden (freu)!

Und zwar hat dieser Mikrocontroller ein 1:1 Mapping für den Speicher der 
USB Schnittstelle, anstatt diese komische Lösung wo jedes zweite Word 
fehlt.

Ich habe den Code entsprechend angepasst. Man kann jetzt am Anfang der 
usb.c einstellen, welche Variante man benötigt.

Ich glaube, jetzt bin ich Fit genug, mir das Tutorial von Niklas 
(https://www.mikrocontroller.net/articles/USB-Tutorial_mit_STM32) an zu 
tun :-)

Also falls jemand eine schlanke USB-CDC Implementierung für STM32F3 
sucht, jetzt haben wir eine - siehe Anhang.

Nochmal herzlichen Dank an W.S für seine Hilfestellungen. Ohne Dich 
hätte ich das sicher nicht so schnell hinbekommen.

von Stefan F. (Gast)


Lesenswert?

In der main.c fehlte eine Funktion, die habe übereifrig weg geputzt:
1
// Delay some milliseconds
2
void delay_ms(int ms)
3
{
4
    uint32_t start=systick_count;
5
    while (systick_count-start<ms);
6
}

von Stefan F. (Gast)


Lesenswert?

Weiss zufällig jemand, warum man den Pull-Up Widerstand an D+ 
üblicherweise mit einem Transistor schaltet und nicht einfach direkt an 
einen GPIO Pin anschließt?

von STM Apprentice (Gast)


Lesenswert?

Stefanus F. schrieb:
> Also falls jemand eine schlanke USB-CDC Implementierung für STM32F3
> sucht, jetzt haben wir eine - siehe Anhang.

Das ist schön, aber ich vermute dass die Nichtfunktionalität
dieses Teils mit 32-Bit(-Windows7)-Systemen immer noch besteht.

Meine Vermutung wäre dass irgend ein Endpoint-Request von den
32-Bit Treibern von dieser USB-Implementierung nicht richtig
oder gar nicht ge-handled wird.

Ich weiss schon, das klingt unplausibel aber mir fällt nichts
besseres ein .... hab schon so manche Programmfehler entdeckt
die sich nur auf 32-Bit Systemen äussern.

Muss ja auch nicht unbedingt ein Fehler des "Nuvoton" USB Teils
sein.

von Stefan F. (Gast)


Lesenswert?

W.S. schrieb:
> Oder hast du's mit dem nop() übertrieben?

Ich weiss nicht mehr woher ich das habe. Jedenfalls habe ich 
ausprobiert, wie viele NOP innerhalb der Nop() Funktion nötig sind und 
bin nun auf einen gekommen - entsprechend deiner Vorlage.

von W.S. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Ich hab den Fehler gefunden (freu)!

Uff... na gottseidank. Wieder ein Chip mehr in der Liste.

Stefanus F. schrieb:
> Weiss zufällig jemand, warum man den Pull-Up Widerstand an D+
> üblicherweise mit einem Transistor schaltet und nicht einfach direkt an
> einen GPIO Pin anschließt?

Nö, ich schätze mal, das weiß keiner so recht. Vielleicht liegt es an 
irgendwelchen USB-Cores, die den 1k5 über ein dediziertes Pin bedienen 
und dabei dessen Polarität nicht vom Programmierer einstellen lassen.

Es gibt auch Schaltungen, wo der 1k5 einfach an +3.3V geht. Ohne 
irgendwelches Schalten. In solchen Fällen muß man sich aber mit dem 
Anwerfen des USB nach dem Einschalten beeilen.

W.S.

von Stefan F. (Gast)


Lesenswert?

W.S. schrieb:
> Wieder ein Chip mehr in der Liste.

Das war mein Ziel. Der STM32F303 fehlte mir dort.

Falls du meine Anpassung in deine Vorlage übernehmen möchtest, sind die 
relevanten Änderungen folgende:

Zwei neue defines:
1
/* For devices with 2 x 16 bits / word access schema (e.g. STM32F303xD and xE) */
2
#define shift 0
3
#define memwidth word
4
5
/* For devices with 1 x 16 bits / word access schema (e.g. STM32F103xx, STM32F302xx, STM32F303xB and xC) */
6
// #define shift 1
7
// #define memwidth dword

Sowie alle weiteren Stellen, wo die diese dann benutzt werden. Es 
betrifft Shift Operationen, die Größe der Felder in der Struktur 
TEpTableEntry und die Größe der temporären Variablen in 
ReadControlBlock() und WriteControlBlock().

Und dann hast du einen Text bezüglich der "kruden" Speicherstruktur 
hinterlassen, dieser gilt nur für für die kleineren STM32F303xB und xC. 
Der STM32F303xD und xE hat keine "krude" Speicherstruktur.

von N. M. (mani)


Lesenswert?

Stefanus F. schrieb:
> Weiss zufällig jemand, warum man den Pull-Up Widerstand an D+
> üblicherweise mit einem Transistor schaltet und nicht einfach direkt an
> einen GPIO Pin anschließt?

Ich habe den Widerstand bei mir direkt an einem GPIO des uC. 
Funktioniert bei mir zumindest ohne Probleme. Hab aber glaub ich 
vorsichtshalber einen High Current Pin genommen gehabt.

Könnte es daran liegen, dass man vermeiden will das beim Strecken 
Spannung direkt an dem uC Pin über D+ anliegen kann bevor VCC dann ist.
Sollte zwar über den Stecker geschehen, aber vllt nochmal zusätzlich?

von Stefan F. (Gast)


Lesenswert?

N. M. schrieb:
> Könnte es daran liegen, dass man vermeiden will das beim Strecken
> Spannung direkt an dem uC Pin über D+ anliegen kann bevor VCC dann ist.

Gute Idee, ja das könnte es sein. Wie war das nochmal - ich glaube ohne 
VCC dürfen an den 5V Toleranten Pins maximal 4V anliegen. Das wiederum 
wäre nur mit zusätzlichen Schutzdioden sicher einzuhalten.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Stefanus F. schrieb:
> Weiss zufällig jemand, warum man den Pull-Up Widerstand an D+
> üblicherweise mit einem Transistor schaltet und nicht einfach direkt an
> einen GPIO Pin anschließt?

Vielleicht weil es lästig ist, zwischen "High" und "Hochohmig" 
umzuschalten; auf "Low" sollte man den Widerstand m.W. nicht schalten. 
Vielleicht auch weil man die Basis/Gate des Transistors dann noch 
zusätzlich mit einem Pull-Up versehen kann, welcher dafür sorgt, dass 
der 1,5kΩ-Pullup beim Starten der Firmware nicht versehentlich aktiviert 
wird. Vielleicht auch einfach um den uC-Pin anderweitig verwenden zu 
können, falls USB nicht benutzt wird (wird durch den Transistor von D+ 
"entkoppelt").
PS: Einige neuere STM32 (F0 glaube ich) haben ebenfalls die einfache 
"USB"-Peripherie wie der F103, aber mit integriertem Pullup. Damit 
erledigt sich dieses ganze Problem. Die "OTG"-Peripherie der größeren 
Controller hat diesen Pullup auch immer integriert. Die ist aber wie 
gesagt nicht so einfach zu programmieren.

von Stefan F. (Gast)


Lesenswert?

Hallo Niklas,
ich habe mir übrigens gestern dein USB Tutorial erneut durchgelesen. 
Dieses mal habe ich vieles davon verstanden und konnte die Parallelen 
zwischen deinen Erklärungen und W.S. Quelltext (der ja anders 
strukturiert ist, als deiner) erkennen.

Ich glaube der Knackpunkt war, die laufende Schnittstelle einmal mit 
Trace Meldungen zu beobachten und ab und zu mal mit dem Debugger in 
weitere Details zu gucken.

Langsam werde ich daraus schlau :-)

von Stefan F. (Gast)


Lesenswert?

Den aktuellen Stand USB Implementierung findet man immer hier: 
http://stefanfrings.de/stm32/stm32f3.html#vcpnohal

von Willi S. (willi_s)


Lesenswert?

... als das durch einen PortPin schaltbaren 1,5kΩ an D+ hat einen 
einfachen Grund ... es kann eine erneute Enumeration des USB Device 
erzwungen werden ... wenn der Portpin von "Input" auf "Output high" 
geschaltet wird ... dann ist der 1,5kΩ aktiv und der USB Host meit ein 
neues Device ist angesteckt gewirden ... ihne den USB-Stecker betätigen 
zu müssen ... uch nutze gerne dies ... um nach dem Laden des Codes in 
den STM32F103 sofort eune Enumeration durch den Host auszulösen ...

... leider hab' ch auf meinem STM32F193 den Code von W.S. (nich) nicht 
zum laufen gebracht ... der GCC mit "Option 0" wird der NOP unangetastet 
gelassen ... ein PID / VID wird (leider) nicht übertragen ... Clock und 
Ports sind nach Angaben initialisiert PA11 PA12 bleiben in ihrem 
ResetZustand - umschalten auf "alternate" zeigt keinen Effekt - wie auch 
in RM0008 erwähnt ...  aber ich suche noch weiter ...

... übrigens ... wo finde ich einen CDC Treiber für WinXP ? ... meine 3 
PCs laufen noch wunderbar damit und sind damit zu schade für den Schrot 
...

von Stefan F. (Gast)


Lesenswert?

Willi S. schrieb:
> wo finde ich einen CDC Treiber für WinXP

Am einfachsten auf der Webseite von ST. Im Quellcode änderst du dann die 
VID und PID auf die Nummern von ST

> "Option 0"

Was soll das sein?

> leider hab' ich auf meinem STM32F193 den Code von W.S. nicht zum laufen gebracht

Stimmt die Modellnummer? Ich habe dazu kein Datenblatt gefunden.

Meine Rechtschreibung ist schlimm, aber deine so schlimm, dass man 
teilweise nicht mehr erkennen kann, was du gemeint hast.

von Florian Hinterleitner (Gast)


Lesenswert?

Grüß Euch!

Hat jemand schon versucht, diese USB-Implementierung auf einem STM32L103 
zu verwenden?
AN3422 von STMicro behandelt 'Migration from F1 to L1'
Darin find ich gleiche Basisadressen für die USB Register und sonst 
keine Unterschiede, ausser daß der L1 kein OTG mehr kann. Daraus 
schliesse ich, daß der USB-Code von W.S. auf dem L! laufen sollte, 
wüsste aber gern, ob das jemand schon verifiziert hat.


mfg, Flo

von Stefan F. (Gast)


Lesenswert?

Florian Hinterleitner schrieb:

> STM32L103

Es gibt keinen STM32L103.

> keine Unterschiede, ausser daß der L1 kein OTG mehr kann.

Der STM32103 konnte auch kein OTG

> Daraus schliesse ich, daß der USB-Code von W.S. auf dem L!
> laufen sollte, wüsste aber gern, ob das jemand schon verifiziert hat.

Du meinst wohl den STM32L100.

Ich schätze auch, dass der Code passen wird.

Laut 
https://www.st.com/resource/en/application_note/an4879-usb-hardware-and-pcb-guidelines-using-stm32-mcus-stmicroelectronics.pdf 
verwendet der STM32L100 den gleichen USB core Typ A.

Allerdings gibt es davon zwei Varianten der Speicher-Anbundung: 1x16 und 
2x16 bit/word. In meiner modifizierten usb.c kannst du das einstellen.

Ich habe leider keine Angabe im Datenblatt/Referenzhandbuch gefunden 
welches zutrifft. Allerdings stimmen die Adressbereiche mit dem 
STM32F103 überein, deswegen schätze ich, dass die gleiche Einstellung 
passt.

Die aktuelle Version (konfiguriert) für den F1 ist dort: 
http://stefanfrings.de/stm32/stm32f1.html#vcpnohal

Teste es und berichte.

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.