Forum: Mikrocontroller und Digitale Elektronik Warum ist die USB/CDC Implementierung der Cube HAL so groẞ?


von Nemopuk (nemopuk)


Angehängte Dateien:

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/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.

: Bearbeitet durch User
von Vanye R. (vanye_rijan)


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

von Nemopuk (nemopuk)


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
von Manuel H. (Firma: Universität Tartu) (xenos1984)


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.

von Nick (b620ys)


Lesenswert?

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

von Niklas G. (erlkoenig) Benutzerseite


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.

von Nemopuk (nemopuk)


Angehängte Dateien:

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.

: Bearbeitet durch User
Beitrag #8005681 wurde vom Autor gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.