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
voidsetup(){
2
pinMode(PC13,OUTPUT);
3
}
4
5
voidloop(){
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/Incl
ude
-
.arduino15/packages/STMicroelectronics/hardware/stm32/2.12.0/system/Driv
ers/CMSIS/Device/ST/STM32F3xx/Include
Oder aus dem STM32CubeF3 Paket nehmen
- https://www.st.com/en/embedded-software/stm32cubef3.html
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.
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
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.
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.
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.
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.
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.
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.
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.
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.
Niklas G. schrieb:> Ganz simpler Ansatz: die ELF Datei disassemblisieren, und> durchschscrollen. Da sieht man recht schnell, welche Funktionen> ... groß sind.
So richtig groß ist keine, aber es sind sehr viele.
Jürgen schrieb:> Nach dem MAP Fils ist alles mit drin> I2C, ADC, SPI ...
Kann es sein, dass du dich in die "Discarded input sections" verlaufen
hast? Ich sehe im Output von nm und objdump nur ungenutzte IRQ Vektoren
für die von dir genannte Peripherie.
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 ? :-)
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...
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.
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:
1)
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.
2)
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.
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.
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.
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.
Nick schrieb:> Das ist eine dünne Schicht die Zugriffe auf die Hardware vereinfacht> und vereinheitlicht
So dünn ist die nicht. Das mit den structs stimmt schon.
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:
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.
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.
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.
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".
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.
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.
Niklas G. schrieb:> trotzdem blöde dass man nicht die selbe Codebase für beides nutzen kann.
Ja, finde ich auch schade. Wenn ich wie du imstande wäre, die USB
Schnittstelle selbst zu programmieren, würde ich die HAL (und damit auch
STM32duino) komplett ablehnen.
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?
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.
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.
Nemopuk schrieb:> Erkläre du es mir! Was habe ich übersehen?
Hab ich zwar schon mal, aber ich probier es nochmal anders:
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?
Manuel H. schrieb:> o 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
Vielen Dank für deine Analyse.
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
voidsetup(){}
2
voidloop(){}
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.
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.
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)?
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.
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.
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.
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.
Nemopuk schrieb:> Aber die STM32G haben schon wieder andere USB Peripherie.
Also auf den ersten Blick sieht es ziemlich ähnlich aus. Die haben auch
die EPnR-Register. Vermutlich muss man nur ein paar Details anpassen,
z.B. das jetzt verfügbare Handling des Pull-Up Widerstands auf D+ (enorm
praktisch).
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.
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...
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.
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.
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...
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.
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?
Ob S. schrieb:> Zahlst du mir dann auch deinen Lohn für die Zeit aus, die ich dafür> brauche?
Du bist jetzt schon der zweite, der behauptet, ich müsse nur die
Optimierungen richtig einstellen, ohne konkret zu werden.
Heiße Luft bringt mich nicht weiter.
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).
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.
Ich habe mich spaßeshalber noch mal etwas in STM32 Frameworks
eingelesen:
http://jeelabs.org/202x/compare/
Da schneidet LibOpenCM3 recht gut ab. Wäre vielleicht einen Versuch
wert.
Wirf den Cube in die Tonne und schluck das als Lehrgeld.
Evtl. kommst Du mit Keil MDK
(https://developer.arm.com/Tools%20and%20Software/Keil%20MDK) weiter.
K.A. was das kostet. Von Keil gibts glaub ich eine freie (und
eingeschränkte) Version. Das musst du aber selber rausfinden.
Sicherlich gibts auch eine komplett freie Toolchain. Der gcc sollte ja
wohl arm können.
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...
Nick schrieb:> Wirf den Cube in die Tonne und schluck das als Lehrgeld.> Evtl. kommst Du mit Keil MDK
Und der macht die CubeHAL kleiner?
Nick schrieb:> Sicherlich gibts auch eine komplett freie Toolchain. Der gcc sollte ja> wohl arm können.
Also der GCC kann die CubeHAL kleiner kompilieren als der GCC der bei
Arduino oder STM32CubeIDE mitgeliefert ist?
Ob S. schrieb:> Der Trick ist: Funktionalität aus ISRs entfernen.
Ich will die HAL benutzen, nicht editieren. Andernfalls geht der Sinn
des Frameworks verloren.
Manuel H. schrieb:> Es gibt da auch noch LibOpenCM3Manuel H. schrieb:> Da schneidet LibOpenCM3 recht gut ab.
Das Projekt scheint vor vielen Jahren gestorben zu sein. Das es die
neuen STM32 Modelle nicht (bzw. nur unvollständig) unterstützt, ist es
für mich uninteressant.
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.
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.
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.
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.
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:
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
Niklas G. schrieb:>> Ist das dein starrköpfiger thread?>> Es ist nicht mein Thread.
Da hätte ich besser nach dem Autor sehen müssen. Nein, nicht Dein
Thread.
Gesagtes gilt aber nach wie vor für den TO.
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.
Ein T. schrieb:> Jeder Quatsch wird extra manuell implementiert, jedes Mal neu und nach> ganz eigenen "Standards",
Was wenn man Dinge nach etablierten Standards neu implementiert, aber
nach neumodischen Standards - z.B. OOP aus den 80ern statt
strukturierter Programmierung aus den 60ern?
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.
Niklas G. schrieb:> Was wenn man Dinge nach etablierten Standards neu implementiert, aber> nach neumodischen Standards - z.B. OOP aus den 80ern statt> strukturierter Programmierung aus den 60ern?
Darum ging es nicht, aber das weißt Du ja selbst. Wenn Du das
diskutieren möchtest, dann mach dazu bitte einen eigenen Thread auf.
Nemopuk schrieb:
[...]
> 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
Ich habe mir gerade zwei STM32G431CBT6 Boards für sagenhafte 9 Euro
(incl. Versand) bestellt. Im nächsten Urlaub werde ich versuchen, den
USB Code aus dem Eröffnungsbeitrag darauf zu portieren.
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.
Das ist doch W.S. Implementierung von USB/CDC. Gab's da von ihm mal eine
Lizenzaussage? Wie groß ist denn der Unterschied zwischen der 103
Version von deiner Seite
https://stefanfrings.de/stm32/stm32f1.html#vcpnohal und der 303 in
diesem Thread?
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.
Klaus M. schrieb:> Wie groß ist denn der Unterschied zwischen der 103 Version von deiner> Seite https://stefanfrings.de/stm32/stm32f1.html#vcpnohal und der 303 in> diesem Thread?
Die kommen beide von dieser Webseite und unterscheiden sich lediglich in
Konfigurationsparametern in der usb.c, sowie uC spezifische
Konfiguration der Taktquellen und I/O Pins in main c.
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.
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