STM32 GCC Compilereinstellungen für Minimum Size -Os

Gast #7034704
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
#7034991
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?
Gast #7035301
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
#7035429
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
#7035467
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
Gast #7035531
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
Gast #7035539
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.
Gast #7035725
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.
Gast #7045045
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
Persönliche Seite #7045113
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.
#7045119
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
Gast #7045351
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).
Persönliche Seite #7046228
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.
Gast #7046237
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.
Gast #7046399
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.
#7046516
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?
Gast #7046518
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
Gast #7046564
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
Persönliche Seite #7046630
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 :-)
#7046642
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
Persönliche Seite #7046743
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
#7046817
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.
Gast #7047082
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
Gast #7047181
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
Persönliche Seite #7047192
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.
Gast #7047198
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren