Mein DDS-Ad9910 Board aus China ist angekommen und ich würde es gerne mit einem STM32F103 ansteuern. Dazu habe ich mit CubeMX und SW STM32 ein Projekt mit USB-CDC generiert. Beide Programme sagen sie wären auf dem neuesten Stand. Das Projekt kompiliert und die SPI und I2C Schnitstelle funktionieren. Das Ansteuerprogramm dazu läuft unter Windows 7 und ich schicke im Moment zum Testen Strings über USB an den STM32F103 und gebe das empfangene Paket in "CDC_Receive_FS" direkt an das Display über I2C weiter. An den STM32F103 hängt noch ein Nucleo64 über SWD zum Programmieren und Debuggen. Der STM32F103 meldet sich im Gerätemanager als Virtueller COM Port, lässt sich öffen und das USB Monitorprogramm zeigt an das richtig enumeriert wird und meine Strings abgeschickt werden. Manchmal funktioniert es für ein oder zwei Strings aber dann spätestens hängt sich der STM32F103 auf. Debuggen funktioniert überhaupt nicht da wird das Device nicht mal erkannt. Alles was ich bisher im Internet und hier gelesen habe ist entweder älter und trifft nicht auf den generierten Quellcode zu. Hier liest man immer wieder das Die HAL Probleme hat. Stimmt das auch noch für die aktuelle Version ?. Oder ist an der Geschichte den USB Stack grösser machen was dran ? Den falschen Pullup Widerstand an der D+ Leitung habe ich übrigends bei dem China Bluepill Board von 10k auf 1,5k geändert daran sollte es also auch nicht liegen.
Im generierten Code sind die Sende/Empfangsbuffer auf 4 gesetzt nach erhöhen auf 64 funktionierts .... Man muss nur noch erraten das uint8_t* Buf ein Zeiger auf UserRxBufferFS ist. Wenn der Buffer kleiner als das Packet ist wird er scheinbar gnadenlos überbügelt .... Generierter Code "usbd_cdc_if.c":
1 | #define APP_RX_DATA_SIZE 4
|
2 | uint8_t UserRxBufferFS[APP_RX_DATA_SIZE]; |
3 | |
4 | static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len) |
5 | {
|
6 | /* USER CODE BEGIN 6 */
|
7 | USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); |
8 | USBD_CDC_ReceivePacket(&hUsbDeviceFS); |
9 | |
10 | return (USBD_OK); |
11 | /* USER CODE END 6 */
|
12 | }
|
Hans-Georg L. schrieb: > Debuggen funktioniert überhaupt > nicht da wird das Device nicht mal erkannt. Das ist normal, bei den Standard Requests gibt es enge Timeouts. Ist die Enumeration aber erstmal vollständig, kann man das Device durchaus anhalten - dann kommen nur noch Interrupts, wenn Nutzdaten übertragen wurden. Hans-Georg L. schrieb: > Wenn der Buffer kleiner als das Packet ist wird er scheinbar > gnadenlos überbügelt .... Richtig, das muss auch so sein, denn ein Usb Device muss immer dazu in der Lage sein, Pakete in der Größe wMaxPacketSize aus dem Endpoint Deskriptor zu empfangen. Wenn man der Hardware im USB_COUNTn_RX Register eine kleinere als die max. Paketgröße einstellt, wird gar nichts mehr empfangen (Gerät sendet immer NAK). Um ein bisschen Werbung zu machen: Ich habe unter USB-Tutorial mit STM32 auch eine CDC-Implementierung mit detaillierter Erläuterung, die ich grad noch ausbaue...
Niklas G. schrieb: > Hans-Georg L. schrieb: >> Wenn der Buffer kleiner als das Packet ist wird er scheinbar >> gnadenlos überbügelt .... > Richtig, das muss auch so sein, denn ein Usb Device muss immer dazu in > der Lage sein, Pakete in der Größe wMaxPacketSize aus dem Endpoint > Deskriptor zu empfangen. Wenn man der Hardware im USB_COUNTn_RX Register > eine kleinere als die max. Paketgröße einstellt, wird gar nichts mehr > empfangen (Gerät sendet immer NAK). > Das sollten doch auch die Entwickler der HAL und CubeMX wissen ..... Vielleicht kann dein Tutorial denen auch helfen ;-) Ich werde es auch mal lesen aber im Moment will ich erst mal mein AD9910 Board zum laufen bringen. Optimieren kann man immer noch.
Mal weiter geforscht .., Bei der Konfiguration der Endpoints und Descriptoren werden die beiden Konstanten CDC_DATA_FS_IN_PACKET_SIZE und CDC_DATA_FS_OUT_PACKET_SIZE benutzt. Deshalb ist es am geschicktesten die auch zu verwenden und ich habe bei mir direkt das CubeMX template entsprechend gefixed. Unter Windows zu finden unter: C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeMX\db\templates\usbd_cdc_if_ c.ftl Wenn man unbedingt auch High Speed CDC machen will kann man das auch noch mit den Konstanten CDC_DATA_HS_IN_PACKET_SIZE und DC_DATA_HS_OUT_PACKET_SIZE und #ifdef erweitern. @ Niklas Gürtler Ich habe mal dein Tutorial überflogen ... STM32 HAL Code habe ich direkt nicht gefunden und unter Windows benutze ich: CreateFile(portName, .... ); Keine usblib, keine winusb, kein extra Teiber, nix ...
Hans-Georg L. schrieb: > STM32 HAL Code habe ich direkt nicht gefunden und unter Windows benutze > ich: Ja das war Absicht, es ging darum die HAL zu vermeiden, um ein besseres Verständnis für die Abläufe zu bekommen. Eigentlich ist das gar nicht so kompliziert, braucht nur etwas an Verständnis und Vorarbeit, aber die 4 Abstraktionsebenen in der HAL fördern die Lesbarkeit nicht besonders... Hans-Georg L. schrieb: > CreateFile(portName, .... ); > Keine usblib, keine winusb, kein extra Teiber, nix ... Ja, funktioniert aber eben nur mit virtuellen Serial-Ports. Das Bestimmen des "portName" ist schon das erste Problem, weil man dem nicht so wirklich ansehen kann, welcher Port welches Gerät ist (siehe z.B. Beitrag "Zuweisung COM Port zu USB Gerät" ). Die Nutzung von libusb+WinUSB ist unwesentlich komplizierter und vermeidet dieses und andere Probleme. Dafür kann man so ggf. Software nutzen die auf alte Geräte mit Serial-Port ausgelegt ist.
Beitrag #5222952 wurde von einem Moderator gelöscht.
Niklas G. schrieb: > Hans-Georg L. schrieb: >> CreateFile(portName, .... ); >> Keine usblib, keine winusb, kein extra Teiber, nix ... > Ja, funktioniert aber eben nur mit virtuellen Serial-Ports. Das > Bestimmen des "portName" ist schon das erste Problem, weil man dem nicht > so wirklich ansehen kann, welcher Port welches Gerät ist (siehe z.B. > Beitrag "Zuweisung COM Port zu USB Gerät" ). Die Nutzung von > libusb+WinUSB ist unwesentlich komplizierter und vermeidet dieses und > andere Probleme. Dafür kann man so ggf. Software nutzen die auf alte > Geräte mit Serial-Port ausgelegt ist. Natürlich funktioniert CreateFile auch mit Hardware Comports es gibt noch gnügend Maschinen mit Windows NT4,CE und XPEmbedded die wunderbar damit laufen. Wenn ich Informationen über ein Device möchte benutze ich die setupapi von Windows.
> Um ein bisschen Werbung zu machen: Ich habe unter > USB-Tutorial mit STM32 auch eine CDC-Implementierung mit > detaillierter Erläuterung, die ich grad noch ausbaue... Großartig, endlich mal etwas, das nicht von der HAL abhängt. Das muss ich mir mal anschauen, wenn ich Zeit habe. Vor einer Woche wäre es besser gewesen, aber jetzt ist mein Urlaub zu ende. Jedenfalls kommt das in meine Bookmarks. Ich hoffe, der Artikel setzt keine Detail-Kenntnisse zu USB voraus.
Hans-Georg L. schrieb: > Natürlich funktioniert CreateFile auch mit Hardware Comports Ja natürlich. Ich meinte, es funktioniert nicht mit USB Geräten, welche nicht als COM Port definiert sind. Der virtuelle COM Port ist schon eine Krücke, die man nicht unbedingt braucht... libusb_open statt CreateFile ist jetzt auch nicht viel schlimmer. Über libusb hat man genauere Kontrolle über die USB Transfers, kann z.B. Control Requests senden. Stefan U. schrieb: > Großartig, endlich mal etwas, das nicht von der HAL abhängt So war das gedacht ;-) Stefan U. schrieb: > Ich hoffe, der Artikel setzt keine Detail-Kenntnisse zu USB voraus. Ich habe mich bemüht alles nötige kurz zu erläutern. Wenn dennoch etwas unverständlich ist, kannst du ja Bescheid geben.
Stefan U. schrieb: > Großartig, endlich mal etwas, das nicht von der HAL abhängt. Dafür hängt es jetzt an C++ und Klassen-Programmierung. Keine guten Voraussetzungen für eine schnelle und einfache Implementierung. Manche Leute die sich das antun wollen werden damit nicht glücklich werden. Ich sehe nicht ein dass man das dadurch wieder verkompliziert. Wenn ich so etwas kapseln möchte dann geht das auch mit regulären C-Mitteln, ganz gut, man muss nicht gleich mit Kanonen auf Spatzen schiessen. Ich als Geschwindigkeits-Fanatiker habe noch Bedenken ob durch die Klassen-Implementierung da nicht ein paar (zig) Mikrosekunden verloren gehen (weiss es aber nicht). Gut, die Verwendung der HAL-Strukturen ist auch nicht von Effizienz geprägt. Ich habe aber nichts gegen dieses ausgezeichnete Tutorial und die Implementierung an sich.
Das C++ Einzug in die Mikrocontroller Programmierung gefunden hat, sollte man nicht einfach weg ignorieren. Fortschritt ist nur möglich, wenn man ihn zulässt. Genauso gut könntest du dich beklagen, dass das Tutorial nicht in BASCOM geschrieben wurde oder in was-weiss-ich welcher Programmiersprache. Überlege mal: Sogar Arduino nutzt C++. Das wurde für totale Anfänger konzipiert. Und es hat Erfolg, sogar richtig viel davon.
Stefan U. schrieb: > Genauso gut könntest du dich beklagen, dass das Tutorial nicht in BASCOM > geschrieben wurde oder in was-weiss-ich welcher Programmiersprache. Nö. Ich sage nur dass sich die USB Implementierung verkompliziert. Und es ist eine alte Programmier-Weisheit dass für eine Geschwindigkeits-optimierte Programmierung die untersten Levels möglichst effizient arbeiten sollen. Genau deswegen würde ich auch immer HAL vermeiden wo es nötig ist. Stefan U. schrieb: > Überlege mal: Sogar Arduino nutzt C++. Das wurde für totale Anfänger > konzipiert. Und es hat Erfolg, sogar richtig viel davon. Das hat deswegen Erfolg weil 99.99% aller (Arduino-) Benutzer von der Klassen-Programmierung absolut nichts sehen ausser Klassen- Instanzierung und Methoden aufrufen die im Tutorial stehen.
Mitlesa schrieb: > > Dafür hängt es jetzt an C++ und Klassen-Programmierung. Keine > guten Voraussetzungen für eine schnelle und einfache > Implementierung. Manche Leute die sich das antun wollen > werden damit nicht glücklich werden. Ich sehe nicht ein dass > man das dadurch wieder verkompliziert. Wenn ich so etwas > kapseln möchte dann geht das auch mit regulären C-Mitteln, > ganz gut, man muss nicht gleich mit Kanonen auf Spatzen > schiessen. Ich als Geschwindigkeits-Fanatiker habe noch > Bedenken ob durch die Klassen-Implementierung da nicht ein > paar (zig) Mikrosekunden verloren gehen (weiss es aber nicht). > Gut, die Verwendung der HAL-Strukturen ist auch nicht von > Effizienz geprägt. > Mit C++ Metatemplate Programmierung wird alles während der Compilezeit berechnet und das ist schneller als die C Implementierung. Die HAL z.b. verschwendet dafür Ram und Rechenzeit. Schau dir mal KAVASIR an. Allerdings ist das keine leichte Kost und nichts für C+++ Anfänger. Beispiel: Das setzen von Bits in Registern. Du hast einzelne bits die während der Laufzeit verschoben werden und dann verodert und ins Register geschrieben werden. KAVASIR macht diese Bitschieberei während der Compilezeit. Du tauscht also längere Compilezeit gegen kürzere Laufzeit und hast eine wesendlich bessere Typsicherheit weil jedes einzelne Bit seine Attribute hat. Der Compiler meckert dich z.b. an wenn du versuchst ein readonly Bit zu schreiben usw. Ich habe KAVSIR allerdings auch noch nicht real verwendet und kenne auch kein Projekt.
Oh Mann, freu dich doch über den tollen Artikel! Und zeige diese Freude, indem du solche Lapalien einfach für Dich behältst. Wenn eine Frau Dich fragt "Und, wie sehe ich aus?" dann antwortest du doch auch nicht "Super, aber ich kann deine Periode riechen". Es ist ja jetzt nicht so, dass C++ hier ein großes Problem wäre. Ganz im Gegenteil, jeder der in den vergangenen 20 Jahren Programmieren in einer Schule/Uni gelernt hat, ist mit Objektorientierter Programmierung vertraut. C wird heute hingegen kaum noch gelehrt. Schreib es halt um, wie es Dir passt, und veröffentliche deine Variante daneben als Alternative!
@Niklas Ich möchte dein Tutorial auf keinem Fall kritisieren ich habe nur bei der Programmierung für Windows eine andere Ansicht.
Stefan U. schrieb: > Oh Mann, freu dich doch über den tollen Artikel! Ich hoffe du bist des Lesens eines gesamten Beitrags mächtig. Hier noch einmal ein Auszug den du offensichtlich übersehen hast. Mitlesa schrieb: > Ich habe aber nichts gegen dieses ausgezeichnete Tutorial > und die Implementierung an sich. Stefan U. schrieb: > Und zeige diese Freude, indem du solche Lapalien einfach für Dich > behältst. Das Thema Meinungsfreiheit scheint dich nicht zu begeistern? Dann lieber so herumlabern wenn einem die Argumente ausgehen.
Mitlesa schrieb: > Dafür hängt es jetzt an C++ und Klassen-Programmierung Es war so klar dass das kommt... Die OOP ist seit 30 Jahren so ziemlich das beliebteste Paradigma, wird von den meisten Sprachen unterstützt, an allen Unis gelehrt und sollte damit so ziemlich jedem bekannt sein. Ich hatte sogar versucht, es erst prozedural zu machen, und das Resultat war nicht so schön. Daher fand ich es sehr sinnvoll, die einzelnen Teile in Klassen zu kapseln, und nicht 1000 einzeln herumschwirrende Funktionen wie in der HAL zu haben. So sollte es deutlich übersichtlicher sein. Niemand hindert dich, das Tutorial in C ohne Klassen durchzuarbeiten - schreibe statt class halt struct, und schau ob der Code besser wird... Mitlesa schrieb: > Ich sehe nicht ein dass > man das dadurch wieder verkompliziert. Ich finde, es wird weniger kompliziert weil immer klar ist, was wozu gehört. Mitlesa schrieb: > ob durch die Klassen-Implementierung da nicht ein > paar (zig) Mikrosekunden verloren gehen (weiss es aber nicht). Ich habe absichtlich etwas auf Effizienz verzichtet (insbesondere mit Hinblick auf Speicher), denn die steht in einem Tutorial mehr so an dritter Stelle. Wenn man den USB Teil begriffen hat, kann man das immer noch optimieren. Wenn alle 3 COM Ports unter Volllast laufen ist der CPU Load immer noch weit unter 1%... Mitlesa schrieb: > Ich habe aber nichts gegen dieses ausgezeichnete Tutorial > und die Implementierung an sich. Na danke ;-) Mitlesa schrieb: > Und es ist eine alte Programmier-Weisheit dass für eine > Geschwindigkeits-optimierte Programmierung die untersten Levels > möglichst effizient arbeiten sollen. Eine andere Weisheit ist, dass man erstmal übersichtlich programmieren soll, messen (!) soll ob und wo es zu langsam ist, und nur wo nötig optimieren soll. Übrigens wäre z.B. eine derart komfortable und gleichzeitig effiziente Zusammenstellung der USB Deskriptoren in C m.W. nicht möglich, insbesondere die UTF-16-Strings. Das wird z.B. in den ST Beispielen mit HAL zur Laufzeit umgerechnet - ineffizient und unflexibel, kann nämlich nur ASCII. Hans-Georg L. schrieb: > Mit C++ Metatemplate Programmierung wird alles während der Compilezeit > berechnet Ist aber auch mit Vorsicht zu genießen, das wird schnell sehr kompliziert. Hans-Georg L. schrieb: > Ich möchte dein Tutorial auf keinem Fall kritisieren ich habe nur bei > der Programmierung für Windows eine andere Ansicht. Danke... schau dir das libusb Beispiel einfach mal an, so schlimm ist das nicht ;-) und so ganz nebenbei geht der Code dann auch unter Linux.
Niklas Gürtler schrieb: > Hans-Georg L. schrieb: >> Ich möchte dein Tutorial auf keinem Fall kritisieren ich habe nur bei >> der Programmierung für Windows eine andere Ansicht. > > Danke... schau dir das libusb Beispiel einfach mal an, so schlimm ist > das nicht ;-) und so ganz nebenbei geht der Code dann auch unter Linux. Ich schreibe das für mich und für Windows7 und usblib hat mir vor Jahren mal den Rechner lahmgelegt weil es sich alles was sich usb nennt unter den Nagel gerissen hat und nichts mehr lief. Natürlich keine Deinstallation und keine Warnung dabei und ich habe etliche Zeit verbraten bis ich alles wieder aus der Registry hatte und das mitten in einem Projekt. Für komplexere USB Sachen nehme ich dann lieber WinUsb.
Niklas G. schrieb: > Um ein bisschen Werbung zu machen: Ich habe unter > USB-Tutorial mit STM32 auch eine CDC-Implementierung mit > detaillierter Erläuterung, die ich grad noch ausbaue... Wieviel kByte/s darf man denn eigentlich von so einem kleinen STM32F103 erwarten? Macht die Übertragungsrichtung einen Unterschied?
Hans-Georg L. schrieb: > usblib hat mir vor Jahren mal den Rechner lahmgelegt weil es sich alles > was sich usb nennt unter den Nagel gerissen hat libusb hat sich stark weiterentwickelt. Man braucht den Filter Driver nicht mehr installieren, man muss überhaupt nichts mehr mit Admin Rechten machen, somit kann es auch nichts mehr kaputt machen ;-) es greift einfach nur auf WinUSB (oder eine der Alternativen) zu. Hans-Georg L. schrieb: > Für komplexere USB Sachen nehme ich dann lieber WinUsb. Kann man natürlich auch, aber dann ist's nicht mehr portabel. LSB schrieb: > Wieviel kByte/s darf man denn eigentlich von so einem kleinen STM32F103 > erwarten? Hab's jetzt nicht genau ausprobiert, aber ich denke bei anständiger Programmierung (z.B. nutzen des HW Doppel Puffers, nicht im Tutorial abgedeckt) sollte man FullSpeed schon auslasten können. Fragt sich natürlich, wohin mit so vielen Daten! LSB schrieb: > Macht die Übertragungsrichtung einen Unterschied Eher nicht, funktionieren beide quasi gleich.
> Ich habe aber nichts gegen ... die Implementierung an sich. > Ich sehe nicht ein dass man das dadurch wieder verkompliziert. > Das Thema Meinungsfreiheit scheint dich nicht zu begeistern? Ah ja.
LSB schrieb: > Wieviel kByte/s darf man denn eigentlich von so einem kleinen STM32F103 > erwarten? Unter optimalen Bedinungen (da zählt der PC ebenfalls) sind die 1MByte/sec von USB Full speed drin. Man muss aber relativ große Puffer benutzen. In die Host->µC Richtung schafft man sehr oft die Weiterverarbeitung der Daten nicht mit voller Geschwindigkeit, bzw. hat nicht den RAM für größere Puffer frei.
Kannst du deinen Code so umschreiben, dass er mit C++ 11 zufrieden ist? Ich frage, weil die System Workbench for STM32 noch kein C++ 17 unterstützt. Auch nicht, wenn ich den Dialekt manuell einstelle. (Was mich ein bisschen wundert, denn der Compiler hat die Version 6.3.1)
:
Bearbeitet durch User
Niklas Gürtler (erlkoenig) hat doch extra einen eigenen Thread dafür aufgemacht. Ich finde da ist die Diskussion über das Tutorial und den Code dazu besser aufgehoben. Beitrag "USB-Tutorial mit STM32" @stefan Du kannst doch ISO C++ 1y einstellen das entspricht C++14 und da ist die Arbeit mit constexpr einfacher wie mit C++11.
> Ich finde da ist die Diskussion über das Tutorial und den > Code dazu besser aufgehoben. Ja, ich gehe dort hin.
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.