Forum: Mikrocontroller und Digitale Elektronik STM32 GCC Compilereinstellungen für Minimum Size -Os


von hochsitzcola (Gast)


Lesenswert?

In meinem OpenSource Projekt für EBike-Controller geht mir so langsam 
der Flash-Speicher aus. Der Hersteller des Controllers nutzt einen 
STM32F103C6, der hat nur 32k Flash. Er nutzt einen Bootloader der sich 
schon mal 4k nimmt und den ich Kompatibilitätsgründen beibehalten will. 
Dann brauche ich noch 2k für ein virtuelles EEPROM, es bleiben also nur 
noch 26k für den eigentlichen Code. Ich compiliere schon mit der Option 
-Os. Arbeiten tue ich mit der STM32 Workbench, die das Makefile 
automatisch erzeugt. Da github ja inzwischen auch automatisch über ein 
Actionscript auf einer virtuellen Maschine compilieren kann, habe ich 
noch ein eigenes Makefile angelegt, das vom Actionscript bei github 
genutzt wird, aber natürlich auch lokal auf dem Rechner nutzbar ist.
Jetzt stehe ich vor dem Phänomen, daß das von der STM32 Workbench 
erzeugte bin file deutlich kleiner ist, als das über mein eigenes 
Makefile (das ich mir Copy Paste aus einem anderen Projekt aus dem 
Internet zusammengebaut habe, ohne wirklich Ahnung davon zu haben) 
erzeugte. Beides lokal auf meinem Rechner mit dem gleichen Compiler 
erzeugt.
Wie kann man das automatisiert erzeugte Makefile der Workbench (das 
Inhalte aus verschiedenen Unterordnern includiert) in ein einzelnes 
Makefile zusammenfassen, das nicht die Unterordnerstruktur benötigt, 
sondern nur ein einziges Build-Verzeichnis benötigt, wie es mein 
selbstgestricktes Makefile macht?!
Oder kann man herausfinden warum mein Selbstgestricktes ein größeres 
Bin-File erzeugt?

Selbstgestrickt:
https://github.com/EBiCS/EBiCS_Firmware/blob/NCTE/Makefile

STM32 Workbench:
https://github.com/EBiCS/EBiCS_Firmware/tree/NCTE/make

Actions bei github:
https://github.com/EBiCS/EBiCS_Firmware/actions

Gruß
hochsitzcola

von Oliver S. (oliverso)


Lesenswert?

Ohne jetzt da groß den Filehaufen durchzuwühlen, findet sich im 
GitHub-makefile ein -Og, und kein -Os.

Oliver

von Vincent H. (vinci)


Lesenswert?

Am besten mal via
1
make VERBOSE=1

vergleichen was letztendlich wirklich an den Compiler übergeben wird.

von das (Gast)


Lesenswert?

Stimmt nicht.

von hochsitzcola (Gast)


Lesenswert?


von das (Gast)


Lesenswert?

ich sag ja: stimmt nicht.

von Bauform B. (bauformb)


Lesenswert?

schon mal $(TARGET).map angeschaut?

von hochsitzcola (Gast)


Angehängte Dateien:

Lesenswert?

Hab ich mir jetzt angeschaut, sind aber böhmische Dörfer für mich. Ich 
habe die beiden Versionen mal angehangen....

Gruß
hochsitzcola

von Bauform B. (bauformb)


Lesenswert?

EBiCS_Firmware.map:
1
.isr_vector     0x08001000      0x10c
2
.text           0x0800110c     0x5aec

output.map:
1
.isr_vector     0x08000000      0x10c
2
.text           0x0800010c     0x591c

.text ist das eigentliche Programm, einmal 23276 Byte groß und einmal 
22812. Ist das "deutlich kleiner"? Oder kommt der große Unterschied von 
der unterschiedlichen Methode:
stat "build/EBiCS_Firmware.bin"
vs.
arm-none-eabi-size "LishuiFOC_01.elf"
Und überhaupt: warum .bin? In den diversen hex-Formaten stehen die 
Adressen mit drin. Das ist durchaus vorteilhaft wenn es einen Offset für 
den Bootloader gibt.

Außerdem fängt das obere erst 4K später an und entsprechend fehlen am 
Ende 4K. Da ist wohl der Bootloader versteckt? Dann funktioniert das so 
wie in output.map doch nicht?

von hochsitzcola (Gast)


Lesenswert?

ich lasse die bin Dateien nur erzeugen, um die tatsächliche Größe des 
Codes im Flash ausgeben zu lassen, darum auch der stat Befehl. Beim 
compilieren auf github habe ich ja keinen direkten Zugriff auf die bin 
Datei, da gleich die verschlüsselte Datei für den Bootloader als 
Artifakt ausgegeben wird.
Da ist es auch ein Vorteil, daß die bin Datei keine Adress-Information 
beinhaltet, da kann ich gleich die Dateigrößen vergleichen und muß nicht 
den Offset von der Startadresse rausrechnen...
Das was arm-none-eabi-size als txt ausgibt, ist ja nicht die 
tatsächliche Größe im Flash.
Die 400 Byte unterschied mag einem nicht viel erscheinen, wenn es aber 
darum geht, ein Feature noch in den Code reinzubekommen oder nicht, 
können sie entscheidend sein ;-)

Gruß
hochsitzcola

https://github.com/EBiCS/EBiCS_Firmware/runs/5962771990?check_suite_focus=true
1
arm-none-eabi-size build/EBiCS_Firmware.elf
2
   text     data      bss      dec      hex  filename
3
  25752       72     2760    28584     6fa8  build/EBiCS_Firmware.elf
4
arm-none-eabi-objcopy -O ihex build/EBiCS_Firmware.elf build/EBiCS_Firmware.hex
5
arm-none-eabi-objcopy -O binary -S build/EBiCS_Firmware.elf build/EBiCS_Firmware.bin  
6
make --no-print-directory post-build
7
code size in flash:
8
stat "build/EBiCS_Firmware.bin"
9
  File: build/EBiCS_Firmware.bin
10
  Size: 25824       Blocks: 56         IO Block: 4096   regular file
11
Device: 801h/2049d  Inode: 1317766     Links: 1

von Stefan F. (Gast)


Lesenswert?

Der Parameter -Os beeinflusst nur einige Optimierungsschritte. Im 
Extremfall kann es sogar passieren, dass dein Programm mit diesem 
Parameter kein einziges Byte kleiner Wird.

Ich habe das Gefühl, dass du einen viel größeren Effekt erwartest, wie 
bei einer ZIP Kompression. Darauf kannst du aber lange warten.

von Oliver S. (oliverso)


Lesenswert?

Stefan ⛄ F. schrieb:
> Der Parameter -Os beeinflusst nur einige Optimierungsschritte. Im
> Extremfall kann es sogar passieren, dass dein Programm mit diesem
> Parameter kein einziges Byte kleiner Wird.

Abgesehen davon, daß das eher nicht stimmt, ist die eigentlich Frage des 
TO ja, warum es trotz angeblich identischer makefiles Unterschiede gibt.

Da gibts eigentlich nur eine Lösung: Compiler- und Linkeraufrufe 
vergleichen. Eventuell vorher noch ein -v spendieren.

Oliver

von Stefan F. (Gast)


Lesenswert?

hochsitzcola schrieb:
> Das was arm-none-eabi-size als txt ausgibt, ist ja nicht die
> tatsächliche Größe im Flash.

Soweit ich weis ergibt sich der Flash Bedarf aus "text" (Programmcode) 
plus "data" (Startwerte für Variablen).

https://mcuoneclipse.com/2013/04/14/text-data-and-bss-code-and-data-size-explained/

von hochsitzcola (Gast)


Lesenswert?

Ich habe nicht behauptet, das die makefiles identisch sind, sie sind 
deutlich unterschiedlich. Was ich nicht weiss, welche Option oder 
welcher Befehl im Makefile den Unterschied in der erzeugten Codegrösse 
verursacht, bzw. wie man das STM Makefile mit den includes zu einem 
zusammenfasst.

Gruß
hochsitzcola

von Bauform B. (bauformb)


Lesenswert?

hochsitzcola schrieb:
> Da ist es auch ein Vorteil, daß die bin Datei keine Adress-Information
> beinhaltet, da kann ich gleich die Dateigrößen vergleichen und muß nicht
> den Offset von der Startadresse rausrechnen...
> Das was arm-none-eabi-size als txt ausgibt, ist ja nicht die
> tatsächliche Größe im Flash.

Nicht die Startadresse raus rechnen, sondern text und data 
zusammenzählen, dann kommt das ungefähr hin ;)

Die meisten Funktionen sind gleich groß, hier mal die unterschiedlich 
großen. Vielleicht sieht jemand einen Zusammenhang.
1
 EBiCS_Firmware.map                        output.map
2
 ------------------------------------      --------------------------
3
4
 FOC.o                           0x90      FOC.o                 0x90
5
 FOC.o                           0xb8      FOC.o                 0xb8
6
 FOC.o                          0x1a4   |  FOC.o                0x198
7
8
 display_kingmeter.o             0x18   |  display_kingmeter.o   0x1b
9
 display_kingmeter.o             0x40      display_kingmeter.o   0x40
10
 display_kingmeter.o             0xac   |  display_kingmeter.o   0xa0
11
 display_kingmeter.o            0x448   |  display_kingmeter.o  0x3e4
12
13
 print.o                         0x20   |  print.o               0x2c
14
 print.o                         0x24   |  print.o               0x24
15
 print.o                         0x88   |  print.o               0xbe
16
 print.o                         0xfe   |  print.o              0x126
17
18
 stm32f1xx_hal_msp.o             0x18   |  stm32f1xx_hal_msp.o   0x1b
19
 stm32f1xx_hal_msp.o             0x40      stm32f1xx_hal_msp.o   0x40
20
 stm32f1xx_hal_msp.o             0xb4      stm32f1xx_hal_msp.o   0xb4
21
 stm32f1xx_hal_msp.o             0xb8      stm32f1xx_hal_msp.o   0xb8
22
 stm32f1xx_hal_msp.o             0xd8      stm32f1xx_hal_msp.o   0xd8
23
 stm32f1xx_hal_msp.o            0x104      stm32f1xx_hal_msp.o  0x104
24
25
 system_stm32f1xx_Bootloader.o    0x8   |  system_stm32f1xx.o    0x18
26
 system_stm32f1xx_Bootloader.o   0x10   |  system_stm32f1xx.o    0x4c
27
 system_stm32f1xx_Bootloader.o   0x4c
28
29
30
31
 main.o                           0x2      main.o                 0x2
32
 main.o                           0xc      main.o                 0xc
33
 main.o                           0xc      main.o                 0xc
34
 main.o                           0xc      main.o                 0xc
35
 main.o                           0xc   |  main.o                0x10
36
 main.o                          0x20   |  main.o                0x24
37
 main.o                          0x20
38
 main.o                          0x29      main.o                0x29
39
 main.o                          0x2e      main.o                0x2e
40
 main.o                          0x64      main.o                0x64
41
                                           main.o                0x70
42
                                           main.o                0x78
43
 main.o                          0x7c      main.o                0x7c
44
 main.o                          0x80   |  main.o                0x84
45
 main.o                          0xa8   |  main.o                0xb8
46
 main.o                          0xac   |  main.o               0x138
47
 main.o                         0x150   |  main.o               0x1c8
48
 main.o                         0x1fc   |  main.o               0x1dc
49
 main.o                         0x268   |  main.o               0x27c
50
 main.o                         0x2dc   |  main.o               0xa8c
51
 main.o                         0xb48

von Oliver S. (oliverso)


Lesenswert?

hochsitzcola schrieb:
> bzw. wie man das STM Makefile mit den includes zu einem
> zusammenfasst.

Mit etwas Verständnis, was include macht, und einem Texteditor. Bleibt 
die Frage, warum? Das löst dein Problem auch nicht.

Es hilft alles nichts, du wirst vergleichen müssen, wie und was da 
jeweils compiliert und gelinkt wird.

Oliver

von hochsitzcola (Gast)


Lesenswert?

Oliver S. schrieb:
> Mit etwas Verständnis, was include macht, und einem Texteditor.

Ich habe schon versucht, mit einem Texteditor einfach den Inhalt der 
includierten Files in das Makefile rüberzukopieren, aber dann gibt es 
immer Fehlermeldungen beim compilieren. Die erforderliche Syntax in 
makefiles gibt mir immer Rätsel auf. Die tausenden Zeilen C-Code habe 
ich hinbekommen, am Makefile scheitere ich ...😉

Oliver S. schrieb:
> Bleibt die Frage, warum? Das löst dein Problem auch nicht.

Doch, dann würde ich ja das kleinere bin File bei git erzeugen 
können....

Gruß
hochsitzcola

von Stefan F. (Gast)


Lesenswert?

hochsitzcola schrieb:
> am Makefile scheitere ich

Ist auch nicht einfach. Nun sind normale Desktop Computer inzwischen so 
schnell, dass die Haupt-Funktion von Make (für die µC Projekte) 
überflüssig geworden ist: Nur die geänderten Dateien (und was davon 
abhängt) zu compilieren.

Meine Meinung nach ist es keine Schande, wenn man einfach ein Batch File 
(Shell Script) benutzt, wo die nötigen gcc Aufrufe untereinander 
aufgelistet sind.

von W.S. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Meine Meinung nach ist es keine Schande, wenn man einfach ein Batch File
> (Shell Script) benutzt, wo die nötigen gcc Aufrufe untereinander
> aufgelistet sind.

Das mache ich schon seit langen Jahren so.

Aber mal was anderes: wenn man tatsächlich knapp an Flash ist, dann 
wären 2 Maßnahmen zu bedenken:

1. Änderungen in den Quellen. Also z.B. keine ausschweifenden 
HAL-Routinen oder so, sondern dem Projekt angepaßte eigene Routinen.

2. nicht den GCC benutzen, sondern stattdessen den Keil. Der hat nach 
meiner Erfahrung schon vor 10 Jahren einen deutlich besseren und 
kürzeren Maschinencode als der GCC gemacht. Da dieses Projekt nicht über 
32K geht, sollte das überhaupt kein Problem sein. Allerdings nehme ich 
mal an, daß der GCC mittlerweile etwas aufgeholt hat. Da darf man keine 
Wunder erwarten.

W.S.

von Stefan F. (Gast)


Lesenswert?

Irgendwo habe ich mal gelesen, dass der gcc kompakteren Code erzeugt, 
wenn man nicht jede *.c Datei einzeln compiliert, sondern alle zusammen 
in einem einzigen Aufruf.

Ob das stimmt, weiß ich allerdings nicht.

von Oliver S. (oliverso)


Lesenswert?

Der gcc kann’s ja problemlos. Der TO rätselt nur, wie.

Oliver

von Stefan F. (Gast)


Lesenswert?

Mir fallen da noch diese Flags ein:

-ffunction-sections -fdata-sections -flto -Wl,--gc-sections

Ich weiß nicht genau, was sie bewirken. Es ging wohl primär darum, dass 
unbenutzte Funktionen weg optimiert werden.

von hochsitzcola (Gast)


Lesenswert?

Oh, das -flto scheint ein scharfes Schwert zu sein :-)

stat "build/EBiCS_Firmware.bin"
  File: build/EBiCS_Firmware.bin
  Size: 14556           Blocks: 32         IO Block: 4096   regular file
Device: 0h/0d   Inode: 0           Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/gaswerke)   Gid: ( 1000/gaswerke)
Access: 2022-04-24 20:20:54.000000000
Modify: 2022-04-24 20:20:54.000000000
Change: 2022-04-10 17:14:12.000000000

Ob der Code damit noch läuft habe ich aber nicht ausprobiert :-)

Gruß
hochsitzcola

von Oliver S. (oliverso)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ob das stimmt, weiß ich allerdings nicht.

Stefan ⛄ F. schrieb:
> Ich weiß nicht genau, was sie bewirken.

So ganz scheinst du da nicht im Thema zu sein, oder?

Oliver

von Malte _. (malte) Benutzerseite


Lesenswert?

Stefan ⛄ F. schrieb:
> Ist auch nicht einfach. Nun sind normale Desktop Computer inzwischen so
> schnell, dass die Haupt-Funktion von Make (für die µC Projekte)
> überflüssig geworden ist: Nur die geänderten Dateien (und was davon
> abhängt) zu compilieren.
>
> Meine Meinung nach ist es keine Schande, wenn man einfach ein Batch File
> (Shell Script) benutzt, wo die nötigen gcc Aufrufe untereinander
> aufgelistet sind.
Fürs Testen darf man das gerne tun. Aber Den Vorteil durch 
Parallelisierung merkt man recht schnell, vor allem wenn man die ST 
Bibliothek nutzt und die immer mit baut.
Rebuild eines kleinen STM32 Projekts (64KiB Binary, 53 Quelltextdateien) 
auf einem Ryzen 1600: 7.7s Single Core, 1.6s mit Parallelisierung. 0.26s 
bei partiellem Rebuild einer Datei. Und ja, 7.6s bei jedem Syntaxfehler 
kommt einem lang vor.

Stefan ⛄ F. schrieb:
> Irgendwo habe ich mal gelesen, dass der gcc kompakteren Code erzeugt,
> wenn man nicht jede *.c Datei einzeln compiliert, sondern alle zusammen
> in einem einzigen Aufruf.
Das lässt sich recht einfach erklären: Ist sämtlicher Code in einer 
Datei, kann der Compiler Funktionen leicht Inlinen, was bei Funktionen, 
die nur einmal verwendet werden, immer von Vorteil ist, da mindestens 
Prolog und Epilog eingespart werden. Ist der Code hingegen in einer 
anderen Datei, geht das nicht - der Linker macht nie ein Inline. Man 
kann natürlich mogeln und das in einen Header als Inline auslagern, aber 
dann geht der Speicherverbrauch um so stärker nach oben, sobald die 
Funktion aus zwei Dateien verwendet wird. Alternativ kann man auch noch 
bei einem einzigen gcc Aufruf direkt alle Quelltextdateien übergeben.

Aber ansonsten:
1. Vergleich die Compileraufrufe, die werden bei Make ja normalerweise 
vollständig mit ausgegeben.
2. Schau, ob newlib und gcc die gleiche Version haben.
3. Mit readelf --all *.elf lassen sich auch alle Symbole und deren 
Platzverbrauch in dem Binary anzeigen.
4. Nicht printf aus der newlib verwenden. Das braucht im Gegensatz zur 
Implementierung in der avr-libc leider malloc und free und wenn man die 
eigentlich nicht braucht, wird das Binary dadurch unnötig groß.
5. Die ST Bibliothek nimmt einem zwar eine Menge Arbeit ab und ist ein 
passables how-to bei komplexerer Peripherie. Selber schreiben erzeugt 
aber dann meist doch kompakteren Code.

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Malte _. schrieb:
> Ist der Code hingegen in einer
> anderen Datei, geht das nicht - der Linker macht nie ein Inline.

Und deshalb wurde vor inzwischen doch schon längerer Zeit Link time 
optimization erfunden, kurz lto.

Ist zwar im Falle vom gcc/clang nicht ganz zutreffend, weil die 
Optimierung trotzdem vom Compiler durchgeführt werden, der ist aber 
sozusagen in den Linker gerutscht, und sieht dort den gesamtem Code.

Oliver

von Stefan F. (Gast)


Lesenswert?

Oliver S. schrieb:
> So ganz scheinst du da nicht im Thema zu sein, oder?

Das ist wahr. C nutze ich nur gelegentlich im Rahmen meines Hobbies. Es 
freut mich aber, dass ich dem TO dennoch helfen konnte.

> Den Vorteil durch Parallelisierung merkt man recht schnell
> 7.6s bei jedem Syntaxfehler kommt einem lang vor.

Du bist ja verwöhnt. Compiliere mal SAP E-Commerce, dabei stirbst du vor 
Langeweile. 15 Minuten sind da ganz normal (mit clean mehr als 45 
Minuten).

von Bauform B. (bauformb)


Lesenswert?

Meinten Sie: 15 Stunden? Das kommt ungefähr hin, für das offizielle 
GCC/binutils/newlib Paket von ARM :( Sollte ich eigentlich mal wieder 
einplanen.

von hochsitzcola (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Es freut mich aber, dass ich dem TO dennoch helfen konnte.

Hat leider nicht geholfen, die bin Datei ist zwar klein, läuft aber auch 
nicht :-(

Gruß
hochsitzcola

von Alex E. (tecnologic) Benutzerseite


Lesenswert?

-flto ist die Link time optimisation. Die schmeißt Recht viel unnützes 
raus ist aber je nach gcc Version problematisch gerade wenn sich 
Adressen während des linkens verschieben und sich externer Code auf 
diese Adressen verlässt.

Was geht denn mit lto nicht? Bootet nicht oder verbindet sich nicht mit 
deinem Java Tool?

-ffunction-sections -fdata-sections
Bringt nix für Code size bestimmt nur das Daten und Institutionen von 
Funktionen nicht wahllos verteilt werden.

-Wl,--gc-sections
Das entfernt toten Code. Also Funktionen die nicht verwendet werden.

Ansonsten musst du das map file durch gehen.
Ggf lohnt es sich das Projekt in der stmcubeide zu importieren dort gibt 
es einen Recht brauchbaren Screen der das map file in einem GUI auf 
drösselt. Dann kannst dir große Funktionen ansehen und ggf. Optimieren.

von Alex D. (Gast)


Lesenswert?

hochsitzcola schrieb:
> Stefan ⛄ F. schrieb:
>> Es freut mich aber, dass ich dem TO dennoch helfen konnte.
>
> Hat leider nicht geholfen, die bin Datei ist zwar klein, läuft aber auch
> nicht :-(
>
> Gruß
> hochsitzcola

Es kann sein, dass der gcc mit -flto Interruptroutinen wegoptimiert, 
wenn diese in einem Assembler File als weak deklariert werden.

https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966

Bin da auch schon mal drüber gestolpert, anscheinend sollte es 
funktionieren, entweder die deklarationen der Interruptfunktionen und 
Vektortabelle generell in C zu machen, oder die Reihenfolge der Objekte 
beim Linken zu ändern.

von g457 (Gast)


Lesenswert?

> Meinten Sie: 15 Stunden? Das kommt ungefähr hin, für das offizielle
> GCC/binutils/newlib Paket von ARM :(

Das klingt irgendwie nach angezogener Handbremse. Ich baute ein 
komplettes Linux inklusive X11, Qt und diverser Tools (bash, xterm, 
systemd, python, ..), inklusive Host-Toolchain, Host-Cross-Toolchain und 
Canadian-Cross-SDK (inklusive Qt) in gut 3 Stunden Realzeit (ohne 
vorcompilierte Binaries, alles direkt aus den Sourcecodes). Auf einem 
Quadcore+Hyperthreading, zugegeben, aber doch um ein paar 
Größenordnungen umfangreicher als gcc/binutils/newlib für ARM kommt mir 
vor.

von Bauform B. (bauformb)


Lesenswert?

g457 schrieb:
>> Meinten Sie: 15 Stunden? Das kommt ungefähr hin, für das offizielle
>> GCC/binutils/newlib Paket von ARM :(
>
> Das klingt irgendwie nach angezogener Handbremse.
> ... 3 Stunden ... auf einem Quadcore+Hyperthreading...

4 Kerne hätte ich auch, aber auch eine langsame Notebook-Platte. Dank 
newlib produziert der build nämlich 18GB (acht zehn Giga Byte) -- wenn 
man alles abwählt, was offiziell abzuwählen ist. Vollkommen krank das. 
Hat evt. jemand einen Tipp, wie man verhindern kann, dass newlib gebaut 
wird?

Noch eine Anekdote, nicht ganz so OT:

Alex D. schrieb:
> anscheinend sollte es funktionieren, entweder die deklarationen
> der Interruptfunktionen und Vektortabelle generell in C zu machen

Hier habe ich ein Beispiel wo ungefähr das Gegenteil passiert, obwohl 
praktisch alles C ist, auch die Vektortabelle und die crt0. Im ersten 
Versuch mit -flto -Os blieb kein einziges Byte C übrig, nur ein paar 
winzige Assembler Funktionen.

Dagegen hilft ein attribute used für jede spezielle section (wie z.B. 
die Vektortabelle). Dann "optimiert" der GCC mit -flto -Os von 19360 auf 
19448 Byte :)

Ein anderes Programm wird tatsächlich kleiner, ca. 8K auf 7K. Allerdings 
kann man unmöglich feststellen, was fehlt. objdump ist nutzlos, es gibt 
keine Ähnlichkeit mit einem "normalen" Programm.

Und ein paar Kleinigkeiten gehen verloren, z.B. align 8 aus dem Linker 
Script. Oder Daten, die nachträglich ins Hex-File eingetragen werden, 
z.B. CRC oder Datum. Anscheinend merkt der lto, dass konstante Daten aus 
der struct geladen werden und ändert das in ein immediate. Das ist aber 
auch von den Daten selbst abhängig.

lto optimiert scheinbar vor allem auf Geschwindigkeit, dass es manchmal 
kleiner wird, ist ein Nebenprodukt. Aber warum sollte man das für ein 
komplettes Programm machen? Und wie passt das schlechtere alignment der 
text section dazu?

Ist evt. -Wl,--gc-sections die bessere Lösung? Hat -ffunction-sections 
etwas damit zu tun?

von hochsitzcola (Gast)


Lesenswert?

Alex E. schrieb:
> Was geht denn mit lto nicht?

Es geht schlichtweg garnichts, keinerlei Lebenszeichen vom Controller. 
Ich habe es aber auch nicht weiter analysiert.

Mir würde es ja vollkommen reichen, wenn ich das Makefile mit den 
includes aus der STM32 Workbench so umschreiben könnte, daß es in der 
obersten Ebene des Projektverzeichnisses liegt und funktioniert. Dann 
wäre ich ja schon glücklich ;-)

Gruß
hochsitzcola

von Oliver S. (oliverso)


Lesenswert?

Anfrage der Art "ich habe zwar keine Ahnung, aber irgendwo irgend eine 
Software heruntergeladen, die irgendwie für irgendwas kompiliert, Hilfe, 
es funzt nicht" bekommen halt selten sinnvolle Antworten. Ist so.

Oliver

von Stefan F. (Gast)


Lesenswert?

Oliver S. schrieb:
>> Ich weiß nicht genau, was sie bewirken.
> So ganz scheinst du da nicht im Thema zu sein, oder?

Oliver, ich denke du kannst die jüngsten Fragen des TO beantworten. 
Schau sie dir mal an.

von Oliver S. (oliverso)


Lesenswert?

Stefan ⛄ F. schrieb:
> jüngsten Fragen

Welche denn genau?
Und nein, ich schreibe für das Projekt keine neues makefile.

Oliver

von hochsitzcola (Gast)


Lesenswert?

Oliver S. schrieb:
> Und nein, ich schreibe für das Projekt keine neues makefile.

Sollst du ja auch nicht :-) Das mache ich schon selber. Ich werde 
zunächst versuchen, die vom Makefile inkludierten Dateien aus dem 
Debug-Verzeichnis in die zugehörigen Projektverzeichnisse zu kopieren 
und die Pfade im Makefile entsprechend anzupassen....

Gruß
hochsitzcola

von Oliver S. (oliverso)


Lesenswert?

Vincent H. schrieb:
> Am besten mal via
> make VERBOSE=1
>
> vergleichen was letztendlich wirklich an den Compiler übergeben wird.

Machen.
Und dann vergleichen.

Oliver

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Bauform B. schrieb:
> lto optimiert scheinbar vor allem auf Geschwindigkeit, dass es manchmal
> kleiner wird, ist ein Nebenprodukt.

Das kann ich so nicht nachvollziehen. LTO ansich optimiert ja auch 
garnix. Es sorgt nur dafür das die Optimierungen nicht zur Compilezeit 
sondern erst zur Linkzeit erfolgen. Dazu wird in die einzelnen 
Objektdateien kein Binärcode sondern ein Zwischencode geschrieben. Je 
nach GCC-Version und Optionen wird der Zwischencode auch zusätzlich in 
die Objekte geschrieben. Die Optimierung findet dann erst beim Linken 
statt. Deshalb muss auch beim Linken die Optimierungsoption (z.B. -Os) 
angegeben werden genauso wie -flto. Wird -flto nur beim Compilieren 
angegeben kann LTO evtl. garnicht greifen wenn die Objekte auch 
Binärcode enthalten.

> Ist evt. -Wl,--gc-sections die bessere Lösung? Hat -ffunction-sections
> etwas damit zu tun?

Beide Optionen werden bei korrekter Verwendung von LTO keinen Vorteil 
bringen. Wenn doch stimmt was nicht.

Wir haben die Erfahrung gemacht das LTO grundsätzlich zu besserem 
(kleiner, schneller) Code führt, verdeckte Bugs an die Oberfläche bringt 
und kaum noch debugbare ELF-Dateien erzeugt (zumindest mit -Os)

YMMV :-)

von Oliver S. (oliverso)


Lesenswert?

Μαtthias W. schrieb:
> Die Optimierung findet dann erst beim Linken
> statt.

Die Optimierung findet schon beim Compilieren statt, nur wird der 
Compiler halt im "link-Schritt" vor dem linker nochmals aufgerufen.

> Deshalb muss auch beim Linken die Optimierungsoption (z.B. -Os)
> angegeben werden genauso wie -flto. Wird -flto nur beim Compilieren
> angegeben kann LTO evtl. garnicht greifen wenn die Objekte auch
> Binärcode enthalten.

Das war nur bei den allerersten gcc's mit lto der Fall. Seit gcc 4.9 
klappt das alles, ohne dem "linker" die Optimierungsflags nochmals 
mitgeben zu müssen (und seit gcc 5 ignoriert der eventuell doch 
mitgegebene einfach)

Oliver

: Bearbeitet durch User
von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Oliver S. schrieb:
> Μαtthias W. schrieb:
>> Die Optimierung findet dann erst beim Linken
>> statt.
>
> Die Optimierung findet schon beim Compilieren statt, nur wird der
> Compiler halt im "link-Schritt" vor dem linker nochmals aufgerufen.

Erbsenzählerei :-)
$ gcc -o test a.o b.o
ist jetzt aus meiner Sicht schon das Linken. Aber lassen wir das

>> Deshalb muss auch beim Linken die Optimierungsoption (z.B. -Os)
>> angegeben werden genauso wie -flto. Wird -flto nur beim Compilieren
>> angegeben kann LTO evtl. garnicht greifen wenn die Objekte auch
>> Binärcode enthalten.
>
> Das war nur bei den allerersten gcc's mit lto der Fall. Seit gcc 4.9
> klappt das alles, ohne dem "linker" die Optimierungsflags nochmals
> mitgeben zu müssen (und seit gcc 5 ignoriert der eventuell doch
> mitgegebene einfach)

In der Tat. Auch -flto kann beim Linken entfallen. Da kann ich meine 
Makefiles wohl etwas entschlacken.

Matthias

von Oliver S. (oliverso)


Lesenswert?

Μαtthias W. schrieb:
> Erbsenzählerei :-)
> $ gcc -o test a.o b.o
> ist jetzt aus meiner Sicht schon das Linken.

Aus meiner auch - wenn ohne lto ;)

mit lto ruft das gcc-frontend da collect2 auf, und das ist letztendlich 
der Compiler. ld kommt dann danach.

Oliver

: Bearbeitet durch User
von Cyblord -. (cyblord)


Lesenswert?

Oliver S. schrieb:
> Stefan ⛄ F. schrieb:
>> Ob das stimmt, weiß ich allerdings nicht.
>
> Stefan ⛄ F. schrieb:
>> Ich weiß nicht genau, was sie bewirken.
>
> So ganz scheinst du da nicht im Thema zu sein, oder?
>
> Oliver

JA!
Mich wundert immer wieder wie wenig Stefan weiß, aber trotzdem immer 
ganz vorne mit quatschen muss bei allem.
Es ist ja ok wenn man sich mit manchen Sachen nicht auskennt, aber dann 
halt doch mal den Rand Stefan.

von hochsitzcola (Gast)


Lesenswert?

Hm, ich habe es soweit hinbekommen, das es lokal auf dem Windowsrechner 
läuft, auf der virtuellen Linux-Maschine bei github mag es nicht. :-(
https://github.com/EBiCS/EBiCS_Firmware/runs/6179455665?check_suite_focus=true
[c]Building target: LishuiFOC_01.elf
Invoking: MCU GCC Linker
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -mfloat-abi=soft -L 
Drivers/CMSIS -specs=nosys.specs -specs=nano.specs 
-T"STM32F103C6Tx_FLASH_Bootloader.ld" -Wl,-Map=output.map 
-Wl,--gc-sections -o "build/EBiCS_Firmware.elf" @"objects.list" 
-larm_cortexM3l_math -lm
arm-none-eabi-gcc: error: build/startup_stm32f103x6.o: No such file or 
directory
make: *** [makefile:39: LishuiFOC_01.elf] Error 1
Error: Process completed with exit code 2.[/]

Das wird wohl irgendwas mit den Pfaden auf der virtuellen Maschine zu 
tun haben....

Gruß
hochsitzcola

von Alex E. (tecnologic) Benutzerseite


Lesenswert?

Die startup_stm32f103x6.s ist ein Assembler File und das wird nicht 
gebaut da hat make schon Recht. Was er dir da sagt ist zum linken 
brauche ich
build/startup_stm32f103x6.o

Aber ich weiß nicht wie ich dahin komme.

Wie ist denn die rule im makefile für %.s?

von hochsitzcola (Gast)


Lesenswert?

Ah, ich sehe jetzt schon einen Unterschied, auf dem Windowsrechner ist 
das der erste Schritt beim Compilieren:
1
Building file: Startup/startup_stm32f103x6.s
2
Invoking: MCU GCC Assembler
3
4
arm-none-eabi-as -mcpu=cortex-m3 -mthumb -mfloat-abi=soft -g -o "build/startup_stm32f103x6.o" "Startup/startup_stm32f103x6.s"
5
Finished building: Startup/startup_stm32f103x6.s

in dem Output des Actionscripts bei github fehlt dieser Schritt :-(

Gruß
hochsitzcola

von Alex E. (tecnologic) Benutzerseite


Lesenswert?

OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))

Dieser Bereich ist ggf. Ungünstig. Ich hätte beide in einer Zuweisung 
gemacht.

von hochsitzcola (Gast)


Lesenswert?

Fehler gefunden :-)
ein Ordnername war im makefile klein geschrieben, Windows ist das egal, 
Linux mag das natürlich nicht...

Die bei github genutzte Compiler-Version erzeugt sogar noch kleineren 
Code als die auf meinem Windowsrechner
1
stat "build/EBiCS_Firmware.bin"
2
  File: build/EBiCS_Firmware.bin
3
  Size: 25292       Blocks: 56         IO Block: 4096   regular file
4
5
stat "build/EBiCS_Firmware.bin"
6
  File: build/EBiCS_Firmware.bin
7
  Size: 25508           Blocks: 56         IO Block: 4096   regular file

jetzt habe ich wieder 1k Luft für weitere Features in der Firmware ;-)

Gruß
hochsitzcola

von Oliver S. (oliverso)


Lesenswert?

Jetzt hast du es immerhin geschafft, uns die Aufrufe vom Linker und 
Assembler zu zeigen, dem eigentlich relevanten Aufruf des Compilers aber 
immer noch nicht.

Olivet

von Alex E. (tecnologic) Benutzerseite


Lesenswert?

Über kurz oder lang muss die Hal von ST da raus die Frist nur Code und 
Laufzeit.

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.