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.
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.
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.
Das ist übrigens der gleiche Code, wie der von 2015 für STM32F103.
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.
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.
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.
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.
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 |
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?
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.
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.
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 | }
|
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?
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.
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.
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.
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.
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?
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.
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.
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 :-)
Den aktuellen Stand USB Implementierung findet man immer hier: http://stefanfrings.de/stm32/stm32f3.html#vcpnohal
... 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 ...
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.