Warum ist die USB/CDC Implementierung der Cube HAL so groẞ?

OP #8005583
Lesenswert?

Eine minimale Hello-World Anwendung belegt auf STM32F3 ca. 20 kB Flash, wenn sie mit der Cube-HAL oder Arduino (was ja darauf basiert) erstellt wird.

Eine alternative Implementierung, die ich hier im Forum gefunden habe, braucht jedoch nur 5 kB. Der Effekt betrifft nicht nur den STM32F3 auf. Ich konnte ihn ebenso mit anderen STM32 Familien reproduzieren.

Mir ist durchaus Klar, dass das Framework alleine aufgrund seiner Struktur einen gewissen Overhead mit sich bringt. Aber dass es so viel ist, überrascht mich dann doch. Enthält die USB/CDC Implementierung der HAL vielleicht irgend welche nützlichen Zwangs-Features, die über die minimale CDC Implementierung hinaus gehen?

Falls es jemand nachvollziehen will, das ist mein vollständiger Arduino Sketch, der die 20 kB ergibt:

1
void setup() {
2
    pinMode(PC13, OUTPUT);
3
}
4

5
void loop() {
6
    digitalWrite(PC13, LOW);
7
    Serial.println("Tick");
8
    delay(500);
9

10
    digitalWrite(PC13, HIGH);
11
    Serial.println("Tack");
12
    delay(500);
13
}

Das andere Projekt (für die STM32 Cube IDE) habe ich angehängt.

Wer das angehängte Projekt compilieren will, muss die Suchpfade zur CMSIS Bibliothek einstellen. In meinem Fall:

  • .arduino15/packages/STMicroelectronics/tools/CMSIS/6.2.0/CMSIS/Core/Include
  • .arduino15/packages/STMicroelectronics/hardware/stm32/2.12.0/system/Drivers/CMSIS/Device/ST/STM32F3xx/Include

Oder aus dem STM32CubeF3 Paket nehmen

Aber bitte hängt euch nicht an kleinen Unterschieden in den Compiler Optionen und loop() bzw. main() auf. Mir geht es nicht um 1 kB mehr oder weniger, sondern um den krassen Unterschied von 20 kB versus 5 kB.

Angehängte Dateien:
: Bearbeitet durch User
#8005588
Lesenswert?

Du hast doch den Sourcecode oder? Warum liesst du den dann nicht und beantwortest deine Frage selber? Ich meine wofuer ist der wohl sonst da? Du kannst auch deinen Compiler bitten ein Mapfile anzulegen wo du fuer jedes Byte nachschauen kannst wo es bleibt.

Die allgemeine Antwort ist, die Welt besteht heute aus unfaehigen und faulen Programmierern die nur noch ihren Source von sonst wo zusammenkopieren, die fuer alles fertige Libs brauchen. Keiner versteht mehr im Detail was sein Programm eigentlich macht. Also werden die immer fetter.

Achte darauf das du nicht selbst zu so einem Loser wirst. .-)

Vanye

OP #8005596
Lesenswert?

Vanye R. schrieb:

Warum liesst du den (source code) dann nicht und beantwortest deine Frage selber?

Hast du dir mal den Code der HAL angeschaut? Wenn ja, dann kennst du die Antwort. Ich frage hier lieber, als mich so tief einzuarbeiten, denn für mich sind Mikrocontroller nur ein kleiner Bestandteil von Hobby Projekten - nicht meine Lebensaufgabe.

Vanye R. schrieb:

die Welt besteht heute aus unfaehigen und faulen Programmierern

Beruflich bin ich Softwareentwickler, aber nicht für Mikrocontroller. Ja, ich benutze sehr viele Bibliotheken (oft hunderte in einem Projekt) ohne sie im Detail zu kennen. Niemand gibt mir die Zeit, mich so intensiv damit zu beschäftigen, weil das wirtschaftlich nicht funktioniert. Ich werde nicht dafür bezahlt, jedes Bit dreimal von allen Seiten zu bewundern.

Ein Bauarbeiter analysiert auch nicht alle Bauteile, aus denen er ein Haus zusammen setzt. Das Haus muss zügig fertig werden, nur das zählt.

Achte darauf das du nicht selbst zu so einem Loser wirst.

Beim Hobby hat man den Luxus, sich intensiver beschäftigen zu können, wenn man will. Mit dem angehängten kleineren Projekt habe ich das getan. Dort ist mir der Sinn von fast jeder einzelnen Zeile Code klar.

Die HAL ist mir allerdings eine Nummer zu groß. Dafür reicht meine Lebenszeit nicht aus. Und STM32 sind auch nicht die einzigen Mikrocontroller, mit denen ich hantiere. Wenn also jemand anderes die HAL gut kennt und meine Frage beantworten kann, dann wäre das super. Wenn nicht, dreht sich die Welt auch ohne Antwort weiter.

Wenn mir der Speicherplatz aus geht: Größere Speicher sind billiger als Arbeitszeit.

: Bearbeitet durch User
(Firma: Universität Tartu) #8005638
Lesenswert?

Anstatt mit dem (in der Tat umfangreichen und unübersichtlichen, und nicht unbedingt als Lektüre für den Anwender gedachten) Quelltext des HAL anzufangen, würde ich mir erst einmal die beiden erhaltenen Binärdateien (idealerweise im ELF Format) mit objdump vornehmen und schauen, welche Funktionen dort überhaupt eingebunden wurden. Die Namen der Funktionen findet man ja schon im entsprechender Header. Um zu sehen, wann und von wo sie aufgerufen werden, würde ich das ganze auch noch disassemblieren. Im Anschluss daran würde ich konkret diese Funktionen, die tatsächlich eingebunden und aufgerufen werden, im Quelltext des HAL suchen und einen Blick darauf werfen, was sie eigentlich tun. Das ist vielleicht zielführender, als in medias res zu gehen, wenn man noch gar nicht weiß, wo man die "Übeltäter" suchen soll.

Meine Vermutung: Die Arduino-Umgebung neigt dazu, eine Menge Initialisierung vor dem Aufruf von setup() vorzunehmen. Da werden der Timer für millis() gestartet, Standardwerte für Taktgeneratoren gesetzt, Interrupts eingestellt... Aus der Cube HAL werden daher einige Funktionen aufgerufen und somit eingebunden, die man eigentlich nicht bräuchte, um nur Hello World auszugeben. Und diese Funktionen sind nicht unbedingt klein, weil sie recht allgemein gehalten sind. Also wird eine Menge Code eingebunden, selbst wenn nur bestimmte Pfade innerhalb jeder Funktion tatsächlich ausgeführt werden, weil die Arduino-Initialisierung eben genau diese Funktion mit bestimmten Parameterwerten aufruft.

Wie gesagt, das ist nur meine Vermutung. Vielleicht hilft auch schon ein Blick auf den Arduino-Initialisierungscode, um von dort aus die aufgerufenen Funktionen zu identifizieren und dann gezielt unter die Lupe zu nehmen.

Persönliche Seite #8005674
Lesenswert?

Manuel H. schrieb:

Um zu sehen, wann und von wo sie aufgerufen werden, würde ich das ganze auch noch disassembliere

Ganz simpler Ansatz: die ELF Datei disassemblisieren, und durchschscrollen. Da sieht man recht schnell, welche Funktionen, oder Gruppen von Funktionen (typischerweise am Namen erkennbar, wie eben USBD_xxx) groß sind. "nm" kann auch die Größen der Funktionen ausgeben.

OP #8005680
Lesenswert?

Manuel H. schrieb:

im Quelltext des HAL suchen und einen Blick darauf werfen, was sie eigentlich tun.

Wenn du das schon mal gemacht hättest, würdest du es nicht empfehlen. Der USB Code ist extrem komplex verschachtelt. Daraus erschließt sich mir nicht, was den 4x so großen Code rechtfertigt.

Manuel H. schrieb:

Meine Vermutung: Die Arduino-Umgebung neigt dazu, eine Menge Initialisierung vor dem Aufruf von setup() vorzunehmen.

Hatte ich vergessen zu schreiben, daß er auch ohne Arduino auf die ca. 20 kB kommt? Arduinos Overhead ist hier ausnahmsweise mal irrelevant.

Nick schrieb:

Ich würde zuallererst die Compiler- und Linker-Optionen ansehen.

Damit kann ich das binary nur noch größer machen. Habe ich vergessen zu erwähnen, daß diese Settings für meine Frage irrelevant sind?

Nochmal, die Frage war: Was kann die HAL Implementierung, was die andere kleinere Implementierung aus diesem Forum nicht kann?

Anbei die elf und map Dateien, sowie die Ausgabe von nm -S. Ich kann damit nichts anfangen.

Angehängte Dateien:
: Bearbeitet durch User
Beitrag #8005681 wurde vom Autor gelöscht.
#8005701
Lesenswert?

Nemopuk schrieb:

Nochmal, die Frage war: Was kann die HAL Implementierung, was die andere kleinere Implementierung aus diesem Forum nicht kann?

Vermutlich alle Versionen "können" die mit einem STM32 an USB- Implementierungen möglich sind.

Schaue ich mir das in CubeMX an, dann gibt es da eine ganze Menge:

  • Communication Device Class
  • Audio Device Class
  • Download Firware Update Class
  • Human Interface Device Class
  • Custom Human Interface Device Class
  • Mass Storage Class

Da wird nicht alles "von Haus aus" enthalten sein, aber der Kern- Code muss so strukturiert sein dass alle Implementierungen möglich sind. Das wird sicherlich einen Code Overhead verursachen.

: Bearbeitet durch User
OP #8005703
Lesenswert?

Mein Code enthält nur CDC.

der Kern-Code muss so strukturiert sein dass alle Implementierungen möglich sind. Das wird sicherlich einen Code Overhead verursachen.

Sicher, aber kann das schon der Grund für ein 4x so großes Binary sein? Ich mag es nicht glauben. Sorry, aber ich bin von 8 Bit Mikrocontrollern anderes gewohnt (auch mit USB).

Kann die HAL ein seriöses Framework sein, wenn sie so schluderig mit der Code-Größe (und damit auch Performance) umgeht? Noch hoffe ich auf eine bessere Erklärung, die nicht so abtörnt.

: Bearbeitet durch User
(Firma: Universität Tartu) #8005710
Lesenswert?

Nemopuk schrieb:

Wenn du das schon mal gemacht hättest, würdest du es nicht empfehlen. Der USB Code ist extrem komplex verschachtelt. Daraus erschließt sich mir nicht, was den 4x so großen Code rechtfertigt.

Tatsächlich habe ich das schon mal gemacht (für den F4 statt für den F3, aber die Komplexität dürfte ähnlich sein). Ja, es stimmt, der Code ist verschachtelt - aber mit nm oder objdump bekommt man ja immerhin eine Liste der Funktionen und kann sich erst einmal die einfachen vornehmen, statt der Verschachtelung zu folgen.

Hatte ich vergessen zu schreiben, daß er auch ohne Arduino auf die ca. 20 kB kommt? Arduinos Overhead ist hier ausnahmsweise mal irrelevant.

Stimmt, du hast geschrieben, dass es auch nur mit Cube-HAL 20kB sind. Mir war nur entgangen, wie du den kleineren Code bekommst. (Deinen angehängten Code hatte ich nicht kompiliert, da ich keine IDE benutze.)

Nach kurzer Durchsicht (falls ich morgen etwas mehr Zeit habe, nehme ich mir die Dateien mal im Detail vor - ich bin neugierig) würde ich nach wie vor auf ausführlichere Initialisierung bei Cube-HAL vs. deinem kleineren Code tippen. Außerdem sehe ich im HAL Code DMA (scheint dein Code nicht zu benutzen), die einige generische Funktionen mit sich bringt. Außerdem eine Menge Timer-Funktionen (die vermutlich nur einmal aufgerufen werden - Initialisierung...). Und der PCD (Peripheral Controller Driver) fällt ebenfalls auf. Wie gesagt, mit etwas mehr Zeit, schaue ich gerne etwas genauer rein.

: Bearbeitet durch User
OP #8005714
Lesenswert?

Manuel H. schrieb:

Tatsächlich habe ich das schon mal gemacht

Mein herzliches Beileid. Die dazu nötige Ausdauer habe ich nicht mehr.

Manuel H. schrieb:

Außerdem sehe ich im HAL Code DMA (scheint dein Code nicht zu benutzen),

ja, das hast du richtig erkannt

Und der PCD (Peripheral Controller Driver) fällt ebenfalls auf

Der ist mir auch auf aufgefallen. Ehrlich gesagt weiß ich nicht, was das ist. Im Reference Manual vom STM32F3 steht dazu nichts.

Laut https://deepwiki.com/grblHAL/STM32F3xx/4.2.3-usb-low-level-configuration geht es beim PCD offenbar darum, Takt und I/O Pins für USB zu konfigurieren. Also das, was die kleinere Implementierung mit nur wenigen direkten Registerzugriffen macht.

mit etwas mehr Zeit, schaue ich gerne etwas genauer rein.

Das wäre echt super. Denn vielleicht verbirgt sich in dem ganzen Code irgendein nützliches Neben-Feature, womit man die Codegröße rechtfertigen kann (anstatt ihn "aufgeblasen" zu nennen).

Eigentlich will ich ja gar nicht über die HAL ab lästern. So programmiert man heute halt, das habe ich akzeptiert. Ich will nur verstehen, was zu der enormen Größe führt.

: Bearbeitet durch User
OP #8006207
Lesenswert?

Nur digitalWrite: 6 kB

digitalWrite + Serial.println (über UART): 12 kB

digitalWrite + Serial.println (über USB/CDC): 22 kB

digitalWrite + Serial.println (über USB/CDC) + analogRead: 27 kB

Es ist also wohl nicht nur der USB-Code, sondern einfach alles in dem Framework ist erstaunlich groß.

Beim PC habe ich mich längst daran gewöhnt, aber beim Mikrocontroller jucken mir bei dem Gedanken die Fußnägel. Die Vernunft sagt mir "scheiß drauf", aber ich kann es nicht ignorieren. Gibt es dafür kein funktionierendes De-Sensibilisierungs Programm ? :-)

: Bearbeitet durch User
Persönliche Seite #8006216
Lesenswert?

Nemopuk schrieb:

Es ist also wohl nicht nur der USB-Code, sondern einfach alles in dem Framework ist erstaunlich groß.

Ja so ist es, die ganze CubeHAL ist ziemlich "nicht-smart" implementiert. Alles wird sehr umständlich und explizit zur Laufzeit berechnet, jeder Datentyp ist ein 32bit-Integer usw. Die einzelnen Architekturschichten und Module sind penibel voneinander getrennt, obwohl sie in der Praxis nie unabhängig genutzt werden können. Gerade auch weil C wenig Möglichkeiten zur Modularisierung bietet wird es dadurch ziemlich kompliziert und dann doch nicht mehr so toll wiederverwendbar.

Man könnte den Code dennoch als einigermaßen "sauber" oder "gut strukturiert" bezeichnen, aber effizient wird er dadurch nicht. Er ist eigentlich schon einigermaßen übersichtlich, wenn man sich mal rein gearbeitet hat. ST-intern gibt es sicherlich Übersichtsdiagramme die vieles klarer machen, die bekommen wir aber nicht zu sehen...

Ich glaube das ist Absicht, damit das Heer an Junior-Entwicklern einigermaßen damit klar kommt, was bei cleveren effizienten Strukturen nicht mehr der Fall wäre. Das Heer an Entwicklern braucht man, weil es sehr viele Zeilen Code sind, weil der Code so stringend strukturiert ist, weil das für die Junior-Entwickler nötig ist, weil man so viele Entwicklerstellen eben primär mit Juniors besetzen muss, derer man ein Heer braucht weil ...

Richtig lustig wird es dann wenn man noch ein RTOS à la Zephyr drüber stülpt, dann hat es nochmal mehrere Abstraktionsschichten über der STM32CubeHAL.

Das alles ist natürlich nicht nur bei ST so, sondern Industrie-Standard. Ach, und LLMs kommen mit dem sehr expliziten Code sicher auch besser klar.

Nemopuk schrieb:

Gibt es dafür kein funktionierendes De-Sensibilisierungs Programm ? :-)

Einfach mal die Kosten für Flash-Speicher mit den Kosten von Senior-Entwicklern vergleichen...

: Bearbeitet durch User
#8006221
Lesenswert?

Vanye R. schrieb:

Die allgemeine Antwort ist, die Welt besteht heute aus unfaehigen und faulen Programmierern die nur noch ihren Source von sonst wo zusammenkopieren, die fuer alles fertige Libs brauchen. Keiner versteht mehr im Detail was sein Programm eigentlich macht. Also werden die immer fetter.

Also ich habe ehrlich gesagt kein Interesse mich groß in USB und fremde Bibliotheken einzuarbeiten. Ich habe auch keine Lust selber Monate und Jahre zu verbrauchen, um große Frameworks zu entwickeln, die vollends durchgeprüft werden müssen.

Wozu soll ich das Rad neu erfinden? Und die paar kB jucken mich nicht, da ich die heutigen Mikrocontroller in der Regel eh nur zu einem Bruchteil voll bekomme.

(Firma: 1984now) #8006229
Lesenswert?

Nemopuk schrieb:

Es ist also wohl nicht nur der USB-Code, sondern einfach alles in dem Framework ist erstaunlich groß.

Dafür gibt es zwei Hauptursachen:

Die ganze Initialisierung passiert über Strukturen (und die sind dann auch noch standardmäßig zur Laufzeit beschreibbar), was dazu führt, dass sie sowohl im Flash als auch zur Laufzeit im RAM Platz verbrauchen.

Dieser Ansatz ist ganz schick, wenn irgendwas zur Laufzeit umkonfiguriert werden muss. Bloß unterstützt CubeMX das erstens nicht wirklich und zweitens braucht man es bei kleinen µC auch eher selten. Was natürlich der tiefere Grund dafür ist, dass CubeMX praktisch keine Unterstützung dafür liefert.

Das Interrupthandling ist massiv suboptimal. Es wird immer das gesamte Gedöhns mitgeschleppt, welches praktisch alle möglicherweise auftretende Situationen abdeckt, auch wenn oft in der konkreten Anwendung der Hardware 2/3 bis 3/4 davon unmöglich auftreten können. Und natürlich wird auch hier wieder massiv mit Strukturen im RAM gearbeitet, in denen die aufgelaufene Weisheit der Interuptroutine (aus der Abfrage der ganzen Hardware-Flags) etwas handlicher abgelegt wird, bevor der Callback des Frameworks aufgerufen wird.

Der unbestreitbare Vorteil ist hier, dass aus Sicht der Awnendung das Handling massiv vereinfacht wird. Es spielt fast keine Rolle mehr, ob Polling, Interruptbetrieb oder Interruptbetrieb mit DMA verwendet wird.

Beim PC habe ich mich längst daran gewöhnt, aber beim Mikrocontroller jucken mir bei dem Gedanken die Fußnägel. Gibt es dafür kein funktionierendes De-Sensibilisierungs Programm ? :-)

Man kann STM32 auch zu Fuß programmieren. Das macht aber sehr viel mehr Arbeit und ist allenfalls für die ganz kleinen STM32 zu empfehlen.

Der Witz ist allerdings: in vielen Fällen kann HAL-freier Code dafür sorgen, dass man mit einem deutlich kleineren STM32 auskommt, als man ihn bei Verwendung der HAL brauchen würde. Allerdings sind die Preisunterscheide der Hardware so gering, dass der erhöhte Aufwand bei der Software sich erst bei recht großen Stückzahlen auszahlt.

#8006243
Lesenswert?

Nemopuk schrieb:

digitalWrite + Serial.println (über USB/CDC): 22 kB

digitalWrite + Serial.println (über USB/CDC) + analogRead: 27 kB

Achso, du wunderst dich, dass Programme größer werden, wenn du zusätzliche libraries verwendest?! Was genau hat analogRead mit USB zu tun? Was Serial.println? Verwendet das println auch noch floats? Wunderst du dich dann auch, dass die ganze Fließkommaarithmetik mit dazu gelinkt wird? C-Compiler analysieren die formatierungsstrings nicht (Rust und OCaml tun das) und haben somit absolut Null Chancen den float-Krempel wegzulassen.

OP #8006245
Lesenswert?

Nick schrieb:

Achso, du wunderst dich, dass Programme größer werden, wenn du zusätzliche libraries verwendest?!

Nein, ich staune über die Größe. Die USB Implementierung aus diesem Forum ist keine 5 kB groß, die HAL legt jedoch 10 kB drauf.

DigitalWrite und Serial.Println habe ich einzeln aufgelistet, damit man den Platzbedarf der Framework-Komponenten sehen kann. Damit keiner sagt: Dein USB Test ist nur so groß, weil er DigitalWrite und Serial beinhaltet.

Was genau hat analogRead mit USB zu tun?

AnalogRead habe ich zum Schluss aus Neugier hinzugefügt - auch weil ich ein Gefühl dafür habe, wie viele Zeilen Code direkte Registerzugriffe für diesen Schritt brauchen würden. Nämlich ganz sicher keine 5 kB, nicht mal 1/10 davon.

: Bearbeitet durch User
#8006269
Lesenswert?

Nemopuk schrieb:

die HAL legt jedoch 10 kB drauf.

Das ist wohl eher das println. Scheinbar bist du dir nicht darüber bewusst was dahinter steckt. Ein putch wäre der einfachste Einstiegspunkt. println ist schon garnicht Teil der C-Standardbibliothek. Das öffnet schon Tür und Tor für irgendwelche Spinnereien.

Nemopuk schrieb:

Um einen analogen Eingang zu lesen, brauche ich mit klassischen Registerzugriffen ganz sicher keine 5 kB

Ganz sicher nicht. Das analogRead bietet aber wohl (ich vermute) floats an. Und sonst noch irgend ein Gedöns das du in den header-Files rausfindest. Genau darauf zielte meine Frage nach den linker-options ab. Ordentliche Compiler/Linker werfen das nicht benötigte Zeug einfach wieder raus. Tw. kann man explizit floats ausschließen. Aber wenn man (der Hersteller) Spaghetti-code produziert und den dann noch 2 Tage eintrocknen lässst, dann kommt auch nur ein riesen Kneuel als ein Teil aus dem Topf raus. Das hat übrigens absolut nichts mit HAL zu tun. HAL bedeutet Hardware Abstraction Layer. Das ist eine dünne Schicht die Zugriffe auf die Hardware vereinfacht und vereinheitlicht. Der Compiler kann daraus fast immer direkte Registerzugriffe machen. Wenn das bei dem Cube nicht geht, wäre das ein Argument für mich die Plattformwahl nochmal zu überdenken.

Aber ich glaub, ich rede da gegen eine Wand.

OP #8006276
Lesenswert?

Nick schrieb:

die HAL legt (für USB) jedoch 10 kB drauf.

Das ist wohl eher das println

Eben nicht! Schau dir meine Zahlen an:

1
digitalWrite + Serial.println (über UART): 12 kB
2
digitalWrite + Serial.println (über USB/CDC): 22 kB

Serial.println über USB ist 10 kB größer als Serial.println über UART. Ich beiden Fällen habe die jeweils andere Schnittstelle komplett raus gelassen.

Ein putch wäre der einfachste Einstiegspunkt

Ich frage mich gerade, ob du mit dem Arduino Framework vertraut bist.

println ist schon garnicht Teil der C-Standardbibliothek. Das öffnet schon Tür und Tor für irgendwelche Spinnereien.

Ach wirklich? Das ist ja gerade der Punkt! Das Framework ist erstaunlich groß. Es geht ums Framework, nicht um die C-Standardbibliothek.

Um einen analogen Eingang zu lesen, brauche ich mit klassischen Registerzugriffen ganz sicher keine 5 kB

Ganz sicher nicht.

Wolltest du damit meine Aussage bestätigen, oder widersprechen? Ist mir jetzt nicht klar.

Schau dir meine Zahlen an:

1
digitalWrite + Serial.println (über USB/CDC): 22 kB
2
digitalWrite + Serial.println (über USB/CDC) + analogRead: 27 kB

Nur durch Hinzufügen von einem simplen analogen Lesezugriff ist der Code erstaunliche 5 kB größer geworden. Für "eine dünne Schicht" ist das sehr viel Code.

Das analogRead bietet aber wohl (ich vermute) floats an.

Nun ist klar dass du überhaupt keine Ahnung von Arduino hast.

Genau darauf zielte meine Frage nach den linker-options ab. Ordentliche Compiler/Linker werfen das nicht benötigte Zeug einfach wieder raus.

Ja sicher, tut Arduino natürlich auch.

(HAL) ist eine dünne Schicht die Zugriffe auf die Hardware vereinfacht und vereinheitlicht. Der Compiler kann daraus fast immer direkte Registerzugriffe machen.

Du kennst weder Arduino noch die HAL von ST, hast nicht mal in ihren Quellcode geschaut. Also erspare uns bitte solche dumm falschen Aussagen.

Tu mir einen Gefallen: Halte dich aus dieser Diskussion heraus.

Angehängte Dateien:
: Bearbeitet durch User
#8006297
Lesenswert?

Nemopuk schrieb:

Nun ist es klar, du hast keine Ahnung von Arduino.

Stimmt. Will ich auch nicht. Dein Gesülze bestätig es mir nur wieder. Arduinoisten wissen nicht was sie tun, jammern aber gerne drüber.

Nemopuk schrieb:

Du kennst die HAL von ST nicht, hast nicht mal in ihren Quellcode geschaut.

Nein, kenn ich nicht mehr (mehr). Vor über 10 Jahren hab ich mal einem Freund was damit aus Gefallen programmiert. Das hat mich überzeugt, dass der code von Armateuren geschrieben wurde. Aber der Begriff HAL ist mir durchaus geläufig. Zu der Zeit als der Begriff geprägt wurde gabs so ein Arduino-Betreutes-Denken noch nicht mal. Übrigens ist Arduino ein Framework und hat rein garnichts mit ST zu tun. Aber selbst das zu erkennen bist du nicht fähig.

Nemopuk schrieb:

Ich frage mich gerade, ob du mit dem Arduino Framework vertraut bist.

Ich weiß, dass du nicht den blassesten Schimmer von C hast. Ich weiß, dass dir der Begriff HAL nicht geläufig ist, denn jetzt verwendest du ihn synonym mit Framework. Gleichzeitig jammerst du aber, dass der code kompakter wird, wenn du auf die Arduino-Blase verzichtest. Da gehört schon einiges an Realitätsverweigerung dazu.

Du kannst natürlich gerne weiter in deiner Galaxie weiterarbeiten, solltest dich aber nicht darüber beklagen.

OP #8006307
Lesenswert?

Nachdem ich 30 Jahre lang auf Registerebene Programmiert habe, darf ich mir ja wohl mal die längst etablierten Frameworks anschauen, und über Punkte diskutieren, die mir dabei besonders auffallen. Daran ist nichts verwerfliches.

Und was kann ich dafür, daß ST sein Produkt "Cube HAL" nennt?

Eine vernünftige Diskussion ist hier mit dir unmöglich. Also nochmal: Halte dich bitte aus dieser Diskussion heraus.

Persönliche Seite #8006308
Lesenswert?

Nick schrieb:

Aber der Begriff HAL ist mir durchaus geläufig.

Da versteht aber jeder was anderes drunter. Wenn ich einen Elefanten "Maus" nenne, ist es immer noch kein Nagetier, trotz langer Zähne.

Ein wichtiger Punkt bei einer HAL ist die Abstraktion, d.h. dass das API "nach oben" Hardware unabhängig ist. Genau diese Funktion erfüllen die HALs vom Linux-Kernel, Windows, Android. Aber nicht die STM32CubeHAL - da ist das API je nach Hardware unterschiedlich. Teilweise sogar bei identischer Hardware: Das was beim STM32F4 das "SDIO" ist, heißt beim STM32F7 "SDMMC". Die Hardware ist sehr ähnlich, die Register größtenteils kompatibel. Aber die APIs der HAL heißen einmal SDIO und einmal SDMMC. Man muss also im gesamten Code die HAL-Aufrufe ändern, um vom F4 auf den F7 umzusteigen, obwohl die Hardware nahezu gleich ist. Ist zwar hauptsächlich suchen & ersetzen, aber trotzdem blöde dass man nicht die selbe Codebase für beides nutzen kann.

Nicht alles wo "HAL" dran steht ist auch "HAL".

OP #8006313
Lesenswert?

Nick schrieb:

Übrigens ist Arduino ein Framework

deswegen habe ich es bereits im Eröffnungsbeitrag so genannt.

und hat rein garnichts mit ST zu tun.

Es geht hier um den STM32duino Core. Das ist die konkrete Implementierung von Arduino, auf Basis der Cube HAL. Beides kommt von ST. Das map File meines Arduino Sketches und die Ausgabe von nm haben bestätigt, dass überwiegend die HAL für den großen Code verantwortlich ist.

Außerdem schrieb ich bereits im Eröffnungsbeitrag, dass auch eine reine HAL Anwendung ebenso groß ist.

: Bearbeitet durch User
#8006333
Lesenswert?

Niklas G. schrieb:

Aber die APIs der HAL heißen einmal SDIO und einmal SDMMC.

Und das macht jetzt genau was besser? Dass ST nicht mal den Begriff HAL richtig verstanden hat? Sollte das nicht Plattformunabhängig sein? Also sowohl Arduino und HAL? Zumindest beim Begriff HAL sind wir uns ja wohl einig.

Nemopuk schrieb:

Und was kann ich dafür, daß ST sein Produkt "Cube HAL" nennt?

Und was kann ich dafür?

Nemopuk schrieb:

Nachdem ich 30 Jahre lang auf Registerebene Programmiert habe, darf ich mir ja wohl mal die längst etablierten Frameworks anschauen,

Kannst Du, klar. Um so verwunderlicher ist es aber, dass selbst 30 Jahre nicht geholfen haben zu verstehen woher der aufgeblasene code kommt.

Nemopuk schrieb:

Halte dich bitte aus dieser Diskussion heraus.

Ja, genau du wirst mir das verbieten. Ich warte schon drauf! Versuch einfach meine Argumente zu verstehen und entspann dich. Versuch einfach zu verstehen was println letztendlich bedeutet und friss die Kröte die du dir selbst bestellt hast. Versuch rauszufinden was hinter analogRead steht und verwende es nicht mehr wenn es zu viel code generiert.

OP #8006350
Lesenswert?

Nick schrieb:

Um so verwunderlicher ist es aber, dass selbst 30 Jahre nicht geholfen haben zu verstehen woher der aufgeblasene code kommt.

Erkläre du es mir! Was habe ich übersehen?

Aber schaue dir dieses mal die Dateien an und probiere es aus. Auf noch mehr falschen Blödsinn habe ich nämlich keine Lust.

Die Frage im Eröffnungsbeitrag war:

Mir ist durchaus Klar, dass das Framework alleine aufgrund seiner Struktur einen gewissen Overhead mit sich bringt. Aber dass es so viel ist, überrascht mich dann doch. Enthält die USB/CDC Implementierung der HAL vielleicht irgend welche nützlichen Zwangs-Features, die über die minimale CDC Implementierung hinaus gehen?

: Bearbeitet durch User
#8006366
Lesenswert?

Abstraktionen wie eine HAL haben Vor- aber auch Nachteile. Wenn mal etwas nicht funktioniert was nicht davon abgedeckt ist und man muss auf Register Ebene herunter, ist es sehr mühsam herauszufinden warum die HAL ein bestimmtes Bit nicht gesetzt hat. Ich hatte gerade kürzlich das Vergnügen mit den Sync Eingängen vom DMAMUX und DMA bei einem H7.

(Firma: Universität Tartu) #8006382
Lesenswert?

Ich habe mal einen Blick in den mit der HAL generierten Code geworfen. Als erstes ist mir der Interrupt-Handler aufgefallen:

1
08000590 g     F .text  00000976 HAL_PCD_IRQHandler

https://github.com/STMicroelectronics/stm32f3xx-hal-driver/blob/master/Src/stm32f3xx_hal_pcd.c#L859

https://github.com/STMicroelectronics/stm32f3xx-hal-driver/blob/master/Src/stm32f3xx_hal_pcd.c#L1538

Der schlägt schon mit 0x976 = 2422 bytes zu Buche. Die Funktion HAL_PCD_IRQHandler sieht zwar auf den ersten Blick kompakt aus, allerdings wird die Funktion PCD_EP_ISR_Handler inline eingebunden. So weit ich das auf den ersten Blick sehe, werden da mehr mögliche Fälle behandelt, als im HAL-freien Interrupt-Handler (und die im kleinen Code vermutlich gar nicht auftreten, weil sie zu Dingen gehören,die nicht benutzt werden).

Die "umfangreiche" Interrupt-Behandlung hatte 1984now ja auch schon erwähnt.

Dann sind mir noch folgende Funktionen zum Systemtakt aufgefallen:

1
08001608 g     F .text  00000138 HAL_RCC_ClockConfig
2
08001740 g     F .text  00000208 HAL_RCCEx_PeriphCLKConfig
3
08001124 g     F .text  0000049c HAL_RCC_OscConfig

https://github.com/STMicroelectronics/stm32f3xx-hal-driver/blob/master/Src/stm32f3xx_hal_rcc.c

Das sind zusammen 0x7dc = 2012 bytes. Wie ich schon vermutet habe, sind das generische Initialisierungsroutinen. Je nachdem, welche Parameter übergebe werden, initialisieren sie eine Taktquelle und konfigurieren diese, und daher ist natürlich Code für alle vorhandenen Quellen und Optionen vorhanden - auch wenn der Anwender davon in der Praxis nur eine benutzt. Das lässt sich durch direkten Registerzugriff, der die eine tatsächlich benötigte Konfiguration vornimmt, natürlich massiv verkleinern.

Ein ähnliches Bild bei USB Endpoint Funktionen:

1
08002444 g     F .text  0000046e USB_EPStartXfer

https://github.com/STMicroelectronics/stm32f3xx-hal-driver/blob/master/Src/stm32f3xx_ll_usb.c#L419

Immerhin 0x46e = 1134 bytes für USB_EPStartXfer - das lässt sich auch kompakter lösen, wenn man nur CDC haben möchte und keinen generischen Code...

So weit ich das bis hierhin sehe, sind im HAL keine Zusatzfunktionen, von denen der Anwendungscode irgendwie Gebrauch machen würde. Der größte Teil scheint einfach "toter" Code zu sein, der in der konkreten Anwendung nie ausgeführt wird, und einfach nur da ist, weil man den HAL ja auch für andere Dinge nutzen könnte, wenn man das denn wollte.

Wie schon von anderen hier erwähnt, liegt der Vorteil des HAL meiner Meinung nach nur darin, dass der Anwendungsprogrammierer hier ein generisches Interface bekommt und sich nicht um die individuellen Register kümmern muss, die sich je nach STM32-Familie doch merklich unterscheiden. Ich würde vermuten, dass sich der Code mit HAL leichter auf andere Familien portieren lässt als ohne HAL.

Zugegebenermaßen könnte man das sicher auf platzsparender erreichen. Anstatt z.B. die Taktkonfiguration durch eine Fallunterscheidung in einer generischen Funktion zur Laufzeit vorzunehmen, könnte man diese Fallunterscheidung auch schon beim kompilieren vornehmen, und dem Anwendungsprogrammierer ein dafür passendes Interface geben (z.B. separate Funktionen für HSE, HSI, LSE, LSI). Einen generischen Interrupt-Handler um ungenutzte Fälle zu verschlanken ist vermutlich etwas schwieriger umzusetzen.

OP #8006400
Lesenswert?

Nick schrieb:

Was ist das Equivalent von println in der C-Standard-Library? Was hängt dann da noch mit dran? Gäbe es eine noch einfachere Lösung in C die minimal Resourcen verbraucht?

1
void setup() {}
2
void loop() {}

ergibt 18 kB ohne lto und 15 kB mit lto

Wenn ich dann noch USB/CDC deaktiviere, sind es 4,2 kB ohne lto und 2,8 kB mit lto.

Das angehängte Programm kommt auf 20 kB ohne lto und 17 kB mit lto. Es wurde von Cube MX generiert, mit Cube HAL, ohne Arduino, ohne printf.

Falls du nochmal mit dem 5 kB Code aus dem Forum vergleichen willst: den findest du im Anhang des Eröffnungsbeitrages.

Angehängte Dateien:
: Bearbeitet durch User
#8006410
Lesenswert?

Nemopuk schrieb:

void setup() {} void loop() {} ergibt 15 kB

Wenn ich dann noch USB/CDC deaktiviere, sind es 2,8 kB.

Also unabhängig davon, ob du USB verwendest wird USB-code mit generiert und gelinkt. Das ist gelinde gesagt eine wenig professionelle Umgebung.*) Aber wenn ST es schon nicht hinbekommt eine durchgängige Benamsung bei der HAL hinzubekommen, dann vermute ich, dass ST nur mal schnell irgendwas mit Duino hinpfuschen wollte für den Hobbybereich. Für mich wäre das dann klar das Signal die Finger von STCube zu lassen. Wenn man sich aber bewusst drauf einlässt, dann kann man sich auch nicht darüber beklagen.

*) Wenn die Nicht-Verwendung von USB nicht mal der Compiler/Linker schnallt, vermute ich immer noch falsche Einstellungen im Projekt. Aber das hab ich ja schon mal gesagt.

OP #8006411
Lesenswert?

Nick schrieb:

Also unabhängig davon, ob du USB verwendest wird USB-code mit generiert und gelinkt.

Ja logisch, das muss so sein. Das Ding soll sich schließlich als CDC Device beim PC zu erkennen geben, weil ich CDC Support aktiviert habe.

vermute ich immer noch falsche Einstellungen im Projekt

Zeige mir, was ich einstellen soll. Gerne am Beispiel des leeren Sketches, der Einfachheit halber. Oder an dem gerade geposteten Programm für die Cube IDE, da hast du mehr Einstellmöglichkeiten.

vermute ich, dass ST nur mal schnell irgendwas mit Duino hinpfuschen wollte für den Hobbybereich

Ich verstehe deinen Eindruck. Vor ein paar Jahren war ich auch mal so weit, aber inzwischen pflegen sie das STM32duino Projekt seit 8 Jahren und die HAL ist noch älter. Die meinen das wohl ernst.

Kennst du eine Alternative? Wie komme ich als Hobbybastler an eine andere/bessere USB Implementierung für die aktuellen Modelle (ich denke dabei an die STM32G Familie)?

: Bearbeitet durch User
#8006431
Lesenswert?

Nemopuk schrieb:

Das Ding soll sich schließlich als CDC Device beim PC zu erkennen geben, weil ich CDC Support aktiviert habe.

Wenn das eine Initialisierung im code erfordern würde, dann könnte das der Linker rauswerfen. Mitdenken ist aber seitens ST wohl nicht erwünscht.

Nemopuk schrieb:

Kennst du eine Alternative?

Nein, mit STM hab ich keine Erfahrung. Bei den PICs ist die HAL durchgängig, den Prozessor zu wechseln (nur innerhalb einer Familie tatsächlich gemacht) erfordert keine Code-Änderung. Gleiches für den Framework. Allerdings erfordert auf den PIC32 USB FreeRTOS. Und darauf will ich mich nur unter Zwang einlassen. Da mach ich lieber Ethernet oder nimm einen FTDI. Der FTDI wäre ja auch eine Option für dich, wenn du deine 4-lagige Platine machst.

OP #8006454
Lesenswert?

Nick, ich bin enttäuscht.

Du hast mich beleidigt und wie einen Dummkopf da stehen lassen. Du hast mehrfach von falschen Projekteinstellungen geschrieben, konntest dabei aber nicht helfen. Du hast Arduino und Cube HAL scharf kritisiert, konntest aber keine Alternative nennen.

Zu deiner Erleichterung muss ich sagen, dass bisher niemand helfen konnte. Allerdings wurden meine Erkenntnisse bestätigt.

Aus meiner Sicht sieht das so aus, dass ich alle Möglichkeiten bereits vor diesem Thread ausgeschöpft hatte. So viel dazu, dass ich keinen blassen Schimmer habe.

: Bearbeitet durch User
Persönliche Seite #8006473
Lesenswert?

Nick schrieb:

Und das macht jetzt genau was besser?

Nichts, aber es zeigt dass die CubeHAL eben nicht deiner Vorstellung einer HAL entspricht, auch nicht dahingehend dass sie nicht "dünn" ist. Im Übrigen ist die HAL von Windows, Linux, Android alles andere als dünn; gerade bei Android ist sie eigentlich das Hauptproblem für die Fragmentierung zwischen den unterschiedlichen Herstellern und der daraus folgende Mangel an Updates für ältere Geräte.

Nemopuk schrieb:

Ja, finde ich auch schade. Wenn ich wie du imstande wäre, die USB Schnittstelle selbst zu programmieren

So schwierig ist es nicht...

https://www.mikrocontroller.net/articles/USB-Tutorial_mit_STM32#Virtueller_COM-Port

Müsste so in der Art auch für den STM32F3 funktionieren.

: Bearbeitet durch User
#8006477
Lesenswert?

Nemopuk schrieb:

Nick, ich bin enttäuscht.

Das kommt vor im echten Leben.

Nemopuk schrieb:

Du hast mich beleidigt und wie einen Dummkopf da stehen lassen.

Beleidigt? Kannst du bestimmt belegen. Und dann die Sache mit dem Schuh.

Nemopuk schrieb:

Du hast Arduino und Cube HAL scharf kritisiert, konntest aber keine Alternative nennen.

Hast Du danach gefragt? Ich könnte dir eine nennen, aber die würde dir nicht gefallen. Daher lass ich das lieber sein, ich will dich nicht zu einer anderen Sekte bekehren und ich bin kein Missionar. Du willst Arduino, dann nimm es, aber beklag dich nicht.

Nemopuk schrieb:

Aus meiner Sicht sieht das so aus, dass ich alle Möglichkeiten bereits vor diesem Thread ausgeschöpft hatte.

Schön! Dann hast du also verstanden, dass die CubeHALDingsbums nicht Deinen Anforderungen entspricht. Das ist doch schon mal was.

(Firma: Universität Tartu) #8006563
Lesenswert?

Nemopuk schrieb:

Kennst du eine Alternative? Wie komme ich als Hobbybastler an eine andere/bessere USB Implementierung für die aktuellen Modelle (ich denke dabei an die STM32G Familie)?

Es gibt da auch noch LibOpenCM3:

https://github.com/libopencm3/libopencm3

Auf den ersten Blick sieht es schlanker aus als Cube HAL, wobei es vermutlich auch weniger Funktionalität bietet. STM32G0 und STM32G4 werden unterstützt. Immerhin gibt es ein USB/CDC Beispiel, hier für STM32F3:

https://github.com/libopencm3/libopencm3-examples/tree/master/examples/stm32/f3/stm32f3-discovery/usb_cdcacm

Allerdings muss ich dazu sagen, dass ich weder Cube HAL, noch LibOpenCM3 bisher für eigene Projekte benutzt habe, und auch kein USB in meinen Projekten benutzt. Von daher kann ich nicht sicher sagen, ob mein erster Eindruck zutreffend ist.

(Firma: 1984now) #8006956
Lesenswert?

Manuel H. schrieb:

Wie ich schon vermutet habe, sind das generische Initialisierungsroutinen. Je nachdem, welche Parameter übergebe werden, initialisieren sie eine Taktquelle und konfigurieren diese, und daher ist natürlich Code für alle vorhandenen Quellen und Optionen vorhanden - auch wenn der Anwender davon in der Praxis nur eine benutzt.

Diesen Teil kann man allerdings (mal abgesehen vom Platzbedarf der Strukturen) durch Verwendung der Optimierung (insbesondere LTO) noch einigermaßen in den Griff bekommen.

Das klappt aber nicht für die ISRs! Hier ist die Intelligenz von Compilern einfach mal nicht ausreichend. Um hier besser zu werden, müßten sie verstehen, wie die Hardware funktioniert. Also z.B. wissen, dass sich dieses und jenes Flagbit bei der gegebenen Initialierung der Hardware mit absoluter Sicherheit nicht ändern wird, also alle Verzweigungen im ISR-Code, die nur existieren, um den Fall zu behandeln, dass es sich ändert, in der konkreten Anwendung einfach mal überflüsig sind.

Das können sie nicht und werden sie wahrscheinlich auch nie "lernen" (also beigebracht bekommen) können.

Oder anders ausgedrückt: Hier läßt sich durch manuelle Implementierungen am meisten sparen, sowohl Speicherplatz als insbesondere auch Laufzeit.

Aber immerhin: Die HAL enthält zum Glück die Möglichkeit, hier ohne große Klimmzüge reinzugrätschen. Man kann als weite Teile des Standard-Handling problemlos "abklemmen" (und effektiv wirklich aus dem Code entfernen). Aber ist dann natürlich selber dafür verantwortlich, einen bezüglich der Anwendung vollständigen und fehlerfreien Ersatz bereitzustellen.

Und das Allerbeste ist: man kann aus diesem eigenen Teil dann auch wieder den Standard-Callback der HAL aufrufen. Aus Anwendungssicht muss sich also dadurch nicht mal zwingend etwas ändern.

Um das alles allerdings tun zu können, muss man die HAL schon ziemlich gut verstanden haben, insbesondere deren Schicht-Struktur. Die ist leider nirgendwo wirklich gut erklärt. Man muss sich in den HAL-Code einlesen, um das Konzept zu verstehen. Bei einfachen Sachen wie etwa UART, I2C oder SPI ist das für einen erfahrenen Entwickler noch mit recht überschaubarem Aufwand möglich, aber bei USB wird's schon ziemlich heftig, da verliert man schnell mal die Orientierung...

OP #8006962
Lesenswert?

Ob S. schrieb:

Bei einfachen Sachen wie etwa UART, I2C oder SPI ist das für einen erfahrenen Entwickler noch mit recht überschaubarem Aufwand möglich, aber bei USB wird's schon ziemlich heftig, da verliert man schnell mal die Orientierung...

Zu blöd, dass USB gerade der Teil ist, weswegen ich mir die HAL und Arduino anschaue. Alle anderen Schnittstellen kann ich "zu Fuß" programmieren.

(Firma: 1984now) #8006997
Lesenswert?

Nemopuk schrieb:

Zu blöd, dass USB gerade der Teil ist, weswegen ich mir die HAL und Arduino anschaue. Alle anderen Schnittstellen kann ich "zu Fuß" programmieren.

OK. Dann als erstes mal ganz beherzt den Arduino-Kram weglassen. Das ist nun wirklich eine völlig unnötige Abstraktionsschicht on top, die nicht nur unnötigen Overhead einführt, sonder obendrein alles weitere bezüglich einer Optimierung nur unnötig verkompliziert.

(Firma: 1984now) #8007015
Lesenswert?

Nemopuk schrieb:

Ob S. schrieb:

OK. Dann als erstes mal ganz beherzt den Arduino-Kram weglassen.

Das bringt doch nichts!

Doch, natürlich bringt das was. Du musst nämlich "bloß" nach die HAL verstehen, um die gegebenen Hinweise zur Optimierung umsetzen zu können.

Glaub' mir, das ist viel einfacher, als es umzusetzen, wenn da noch ein drübergestülptes Arduino rumwerkelt...

(Firma: 1984now) #8007024
Lesenswert?

Nemopuk schrieb:

Ob S. schrieb:

Doch, natürlich bringt das was. Du musst nämlich "bloß" nach die HAL verstehen, um die gegebenen Hinweise zur Optimierung umsetzen zu können.

Zeige mir, wie du das konkret meinst. Optimiere das angehängte Programm. Wenn du auf 10 kB kommst bin ich zufrieden.

Zahlst du mir dann auch deinen Lohn für die Zeit aus, die ich dafür brauche?

(Firma: 1984now) #8007063
Lesenswert?

Nemopuk schrieb:

Du bist jetzt schon der zweite, der behauptet, ich müsse nur die Optimierungen richtig einstellen, ohne konkret zu werden.

Nein, das habe ich keinesfalls behauptet, sondern klar abgegrenzt, dass das nur bezüglich der Initialiserung etwas bringen kann, nicht aber bezüglich all dem Scheiß, der als Folge von Interrupts passiert, sondern dass da Handarbeit zur Optimierung nötig wird.

Du kannst also offensichtlich nicht mal deutschen Text lesen. Schlechte Voraussetzungen...

Vielleicht ist dir aber auch nur nicht klar, dass bei USB ein sehr großer Teil der Funktionalität in den Handlern von ISRs steckt (stecken muss).

OP #8007066
Lesenswert?

Ob S. schrieb:

Vielleicht ist dir aber auch nur nicht klar, dass bei USB ein sehr großer Teil der Funktionalität in den Handlern von ISRs steckt (stecken muss).

Das ist mir durchaus klar. Der kleinere Code, denn ich ganz oben im Eröffnungsbeitrag angehängt hatte, zu dem ich schrieb, dass ich ihn Zeile für Zeile analysiert und weitgehend verstanden habe, besteht zu 90% aus einer einzigen ISR.

Umso mehr erstaunt mich, dass du es für möglich hältst, den 20 KB Code mit HAL signifikant zu verkleinern. Schade, dass du diesbezüglich nicht konkreter werden möchtest.

(Firma: 1984now) #8007089
Lesenswert?

Nemopuk schrieb:

Umso mehr erstaunt mich, dass du es für möglich hältst, den 20 KB Code mit HAL signifikant zu verkleinern. Schade, dass du diesbezüglich nicht konkreter werden möchtest.

Naja, wollen wir dich nicht mal ganz doof sterben lassen. Der Trick ist: Funktionalität aus ISRs entfernen.

Sprich: Das Konzept umsetzen, was auch richtige OS verwenden. Auch die sind nämlich mit der dramatischen Unfähigkeit der Compiler geschlagen. Die Lösung ist typisch: Es gibt noch eine zusätzliche Schicht zwischen Applikation und ISRs. Und zusätzlich: die eigentliche Applikation läuft nicht wirklich auf main()-Level, sondern nur dann, wenn das, was nunmehr auf main()-Level läuft, also diese zusätzliche Zwischenschicht, mal Zeit läßt für Anwendungscode.

Reichere das noch mit entsprechenden Gimmicks an, und du bist du bei einem typischen RTOS. Man muss aber nicht notwendigerweise so weit gehen. Ein "angedeutetes RTOS-Konzept" reicht halt in vielen Fällen auch.

Und falls du dich fragst, warum das nun bezüglich der Größe des Codes effizienter ist: weil der recht doofe Compiler so seine Fähigkeiten zur Optimierung wesentliche besser ausspielen kann. In main() beherrscht er das nämlich ziemlich gut...

#8007100
Lesenswert?

Niklas G. schrieb:

Also der GCC kann die CubeHAL kleiner kompilieren als der GCC der bei Arduino oder STM32CubeIDE mitgeliefert ist?

Quatsch. Hör endlich auf dir so wirres Zeug zusammen zu fantasieren.

Ich habs schon mal gesagt: Was das CubeHAL macht ist einfach schlecht angelegt. Die sollten sich mal den Unterschied von modularer und monolithischer Programmierung ansehen. Und dann ihr Zeug entsprechend zerfleddern und neu strukturieren. Dass das aber bei dir jemals ankommt bezweifle ich inzwischen massiv.

(Firma: 1984now) #8007108
Lesenswert?

Nemopuk schrieb:

Ich will die HAL benutzen, nicht editieren.

Dann wirst du wohl mit der Codegröße leben müssen.

Wie beim Auto. Wenn ich einen Ferrari F350 fahren will, muss ich halt auch damit leben können, das 'ne blöde Inspektion ein paar Tausender kostet und die Reparatur einer auf dem Parklatz eingedellten Front mal eben mit 35000€ zu Buche schlägt.

Nur der Tod ist umsonst.

#8007164
Lesenswert?

Ob S. schrieb:

Nur der Tod ist umsonst.

Nein.

. . .

Der kostet Dich das Leben...

Noch was zum Thema: Wenn man unbedingt will, kann man USB sicher auch ohne HAL verwenden. Dadurch das der USB-Core eingekaufte IP ist, ist die Philosophie, die dahinter steckt eine andere als bei der restlichen Peripherie von ST. Ich habe für meine Testimplementierung damals dann doch die HAL genommen und war relativ schnell fertig mit meiner Applikation.

Aber dem TO scheint es wichtiger sein zu lamentieren statt zu implementieren.

: Bearbeitet durch User
#8007199
Lesenswert?

Nick schrieb:

K.A. was das kostet.

Für Privatanwender / Hobbyisten? Zu viel. (irgendwas im oberen kEuro-Bereich...)

Von Keil gibts glaub ich eine freie (und eingeschränkte) Version.

Zum Glauben geht man in die Kirche. Es gibt eine Version, die auf eine maximale Codegröße beschränkt ist. Die unterstützt aber nicht alle Funktionalitäten der Vollversion. Ein USB-Device kann man damit AFAIR programmieren - einen USB-Host nicht. Ich arbeite dienstlich mit der Vollversion, daher weiß ich nicht genau, ob USB von der beschränkten Version überhaupt unterstützt wird. Ist aber sinnfrei, wenn man Privatanwender ist, und die CubeIDE verwendet.

#8007215
Lesenswert?

Moin,

Nur mal so als uninteressante Zusatzinfo: Bei der libopencm3 gibt's in der Nachbarschaft auch uninteressante libopencm3-examples. Dort u.a. unter: libopencm3-examples/examples/stm32/f4/stm32f429i-discovery/usb_cdcacm ein uninteressante Simpelbeispiel, was wohl nur so eine Art 1:1 RX-TX Verbindung per USB macht:

1
static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
2
{
3
    (void)ep;
4

5
    char buf[64];
6
    int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
7

8
    if (len) {
9
        while (usbd_ep_write_packet(usbd_dev, 0x82, buf, len) == 0);
10
    }
11
}

Da wird (wohl aus Gruenden der Einfachheit des Beispiels) nichts mit Interrupts gemacht, sondern mit polling. Das .bin file ist 6760 bytes gross.

Gruss WK

#8007339
Lesenswert?

Vanye R. schrieb:

Die allgemeine Antwort ist, die Welt besteht heute aus unfaehigen und faulen Programmierern die

... jeden Scheiß selbst von Hand machen, weil sie sich für die genialsten Entwickler unter G~ttes schöner Sonne und alle anderen für unfähige und faule Vollidioten halten.

Als Kollegen sind solche Leute eine absolute Pest. Jeder Quatsch wird extra manuell implementiert, jedes Mal neu und nach ganz eigenen "Standards", und das Ergebnis ist ein Kartenhaus aus Not-Invented-Here, das augenblicklich in sich zusammenfällt und exorbitante Aufwände erforderlich macht, sobald sich die Anforderungen nur minimal ändern. Zudem sind solche Leute extrem langsam und ziehen die Produktivität ihres ganzen Teams in den Keller, was sie dann zwar mit ihrer besonderen Sorgfalt zu rechtfertigen versuchen, aber...

Achte darauf das du nicht selbst zu so einem Loser wirst. .-)

Achte vor allem sehr genau darauf, Dich von solchen Losern fernzuhalten.

OP #8007410
Lesenswert?

Ob S. schrieb:

Ich will die HAL benutzen, nicht editieren.

Dann wirst du wohl mit der Codegröße leben müssen.

Sieht so aus.

Rick schrieb:

Noch was zum Thema: Wenn man unbedingt will, kann man USB sicher auch ohne HAL verwenden.

Noch habe ich reichlich STM32F303 Board vorrätig, von denen ich zehre. Sollte ich irgendwann auf neue Modelle (z.B. STM32G4) wechseln müssen, steht mir ja immer noch die von Niklas empfohlene Möglichkeit offen, den Code aus dem Eröffnungsbeitrag zu portieren.

Aber dem TO scheint es wichtiger sein zu lamentieren statt zu implementieren.

Ich wollte eigentlich nur die Frage aus dem Eröffnungsbeitrag klären:

Nemopuk schrieb:

Enthält die USB/CDC Implementierung der HAL vielleicht irgend welche nützlichen Zwangs-Features, die über die minimale CDC Implementierung hinaus gehen?

Lamentiert haben andere, die auf den Optimierungseinstellungen herum geritten habe, obwohl ich ausdrücklich darum bat, das nicht zu tun:

Nemopuk schrieb:

Aber bitte hängt euch nicht an kleinen Unterschieden in den Compiler Optionen und loop() bzw. main() auf. Mir geht es nicht um 1 kB mehr oder weniger

Solange noch nicht alles von jedem gesagt wurde, geht es hier wahrscheinlich noch lange weiter.

#8007464
Lesenswert?

Nemopuk schrieb im Beitrag #8007410: [...]

Noch habe ich reichlich STM32F303 Board vorrätig, von denen ich zehre. Sollte ich irgendwann auf neue Modelle (z.B. STM32G4) wechseln müssen, steht mir ja immer noch die von Niklas empfohlene Möglichkeit offen, den Code aus dem Eröffnungsbeitrag zu portieren.

[...]

Du könntest dir mal http://www.tinyusb.org ansehen. Das ist mit Sicherheit nicht so kompakt wie das Beispiel aus dem Eröffnungsbeitrag, aber schmaler als der HAL-USB-Code.

Gruß, f

Persönliche Seite #8007487
Lesenswert?

Nemopuk schrieb:

Sollte ich irgendwann auf neue Modelle (z.B. STM32G4) wechseln müssen, steht mir ja immer noch die von Niklas empfohlene Möglichkeit offen, den Code aus dem Eröffnungsbeitrag zu portieren.

Also mein USB-Treiber sollte sich sowohl auf den F3 als auch auf den G4 portieren lassen, die haben nahezu identische Hardware wie der F1, für den ich den Treiber ursprünglich geschrieben hatte.

Persönliche Seite #8007494
Lesenswert?

Klaus M. schrieb:

Das ist doch W.S. Implementierung von USB/CDC

Meinst du mich? Ahem, ich habe meine eigene CDC Implementierung, und ich habe eine Meinung zur Codequalität von W.S. ...

Meine Library ist diese: http://github.com/Erlkoenig90/f1usb https://www.mikrocontroller.net/articles/USB-Tutorial_mit_STM32

Klaus M. schrieb:

Gab's da von ihm mal eine Lizenzaussage?

Ja:

Beitrag "Re: USB CDC von Stefan Frings und WS"

Hier die von mir fehlerbereinigte Version der W.S. Library:

https://github.com/Erlkoenig90/WSusb

: Bearbeitet durch User
Persönliche Seite #8007501
Lesenswert?

Nemopuk schrieb:

Ja: Es gibt keine Lizenz, frei für alle.

Wenn es keine Lizenz gibt, ist der Code eben nicht frei - dann darf man ihn lesen, mehr nicht. Alles was nicht explizit erlaubt ist, ist verboten. Daher ist das Angeben von Lizenzen bei OpenSource-Projekten ja so wichtig, weil der Code sonst nicht verwendbar ist. Aber W.S. hat sich nach vielem Murren ja überreden lassen, eine Lizenz in seiner besonderen Ausdrucksweise anzugeben.

#8008433
Lesenswert?

Niklas G. schrieb:

Wenn es keine Lizenz gibt, ist der Code eben nicht frei - dann darf man ihn lesen, mehr nicht. Alles was nicht explizit erlaubt ist, ist verboten. Daher ist das Angeben von Lizenzen bei OpenSource-Projekten ja so wichtig, weil der Code sonst nicht verwendbar ist.

Absolut richtig. Das ist ja gerade der Trick der GPL: man darf den Code nur dann benutzen, wenn man sich an seine Lizenzbedingungen hält.

Es ist aus meiner Sicht extrem erschreckend, daß sich sogar viele erfahrene Entwickler nicht mit Lizenz- und Nutzungsrechten auskennen.

OP #8012639
Lesenswert?

Kurze Rückmeldung:

Ich konnte die oben genannte kompakte USB Implementierung von W.S. auf meinem STM32G431 Board ans Laufen bringen. Wie bereits vermutet wurde, hat der G4 im Prinzip die selbe Peripherie. Nur die Konfiguration der I/O Pins und des Taktes ist (wie üblich) im Detail etwas anders.

Ich habe es dort zum Download bereit gestellt. https://stefanfrings.de/stm32/stm32g4.html#vcpnohal

: Bearbeitet durch User

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