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.