mikrocontroller.net

Forum: Compiler & IDEs Arm GCC mit Option -flto erzeugt Fehler


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Reiner S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich die Option -flto einsetze wird folgender Fehler vom Linker 
geworfen:
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'

Es ist ein kurzes Testprogramm in dem keine printf oder scanf Funktionen 
aufgerufen werden. Nur ein GPIO-Pin und CDC wird von von HAL verwendet. 
Wenn ich ohne -flto compeliere läuft es durch.
Ich habe es mit Atollic TrueStudio gcc 6.x und Swstm32 gcc 7.x getestet, 
bei beiden das gleiche Problem.

Danke

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Reiner S. schrieb:
> Wenn ich ohne -flto compeliere läuft es durch.

Dann mach mal ein objdump auf das erstellte ELF und schaue wo malloc 
aufgerufen wird. Vermutlich ist irgendwo in der HAL noch ein printf () 
Aufruf.

Autor: rµ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
soweit ich mich erinnere ist für LTO ein plugin nötig, selbiges teilt 
man ar, ld und co über gcc/g++ mittels
-r --plugin /usr/lib/gcc/arm-none-eabi/7.3.1/liblto_plugin.so.0

mit. Pfad je nach Version und Betriebssytem anpassen.

Autor: Reiner S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Dann mach mal ein objdump auf das erstellte ELF und schaue wo malloc
> aufgerufen wird. Vermutlich ist irgendwo in der HAL noch ein printf ()
> Aufruf.

Ja malloc wird aufgerufen aber ohne -flto wird des Programm übersetzt 
und USB funktioniert. Ist die Reihenfolge der Module beim übersetzen 
wichtig?

Autor: Reiner S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo rµ
Ich arbeite unter Windows und es gib eine liblto.dll. Ich gehe aber 
davon aus das der gcc mit der Option -flto die liblto.dll automatisch 
aufruft.

Autor: x^y (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Bist du sicher, dass das Projekt vollständig neugebaut wurde und keine 
alten Objekt Dateien überlebt haben? -flto erzeugt speziell 
instrumentierte Objektdateien. malloc() in MCU Firmware ist ein bißchen 
wie der Papst auf der Reeperbahn. Sollte man unabhängig davon aus dem 
Projekt eliminieren. Ist dir aber sicher bekannt :)

Autor: Reine S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
x^y schrieb:
> Bist du sicher, dass das Projekt vollständig neugebaut wurde und
> keine
> alten Objekt Dateien überlebt haben? -flto erzeugt speziell
> instrumentierte Objektdateien.
Ich denke schon. Habe aber noch mal alle *.o und *.su Dateien gelöscht.
Leider keine Besserung.

> malloc() in MCU Firmware ist ein bißchen
> wie der Papst auf der Reeperbahn. Sollte man unabhängig davon aus dem
> Projekt eliminieren. Ist dir aber sicher bekannt :)
Bei kleinen 8 Bitern ist schon richtig, aber bei einem STM32F407 sehe 
ich kein Problem sich einen Puffer per malloc zu beschaffen.
Außerdem ist das malloc im USB-Treiber von HAL eingebaut.

Autor: Reine S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe mir mal die map-Files mit und ohne lto angesehen. Der Fehler mit 
lto
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
Im map-File ist _sbrk nicht zu finden.

Beim compelieren ohne lto findet sich _sbrk im map-File

OTG_FS_IRQHandler
                0x08004014       0x10 Src\stm32f4xx_it.o
                0x08004014                OTG_FS_IRQHandler
 .text._sbrk    0x08004024       0x3c Src\syscalls.o
                0x08004024                _sbrk

und das Programm rennt.

MfG

Autor: Vincent H. (vinci)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Markier sbrk mal testweise als "used" via
__attribute__((__used__))

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Bindest du das USB-Zeug (also das welches malloc aufruft) über eine 
statische Library ein?

Dann versuch mal per -Wl,--start-group -lblabla -Wl,--end-group zu 
linken.

Autor: A. B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eventuell hilft ein

__attribute__((used)) void *dummy(void) {
  return _sbrk(0);
}

irgendwo, um den Compler/Linker zu überzeugen, dass _sbrk tatsächlich 
gebraucht wird und nicht wegoptimiert werden darf. Man könnte das 
__attribute__((used)) auch einfach vor die Definition vom _sbrk setzen, 
aber das wäre mit mehr Aufwand verbunden.

Autor: Olaf (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
> Bei kleinen 8 Bitern ist schon richtig, aber bei einem STM32F407 sehe
> ich kein Problem sich einen Puffer per malloc zu beschaffen.

Die groesse des Microcontrollers ist vollkommen irrelevant und ausserdem 
auch nur relativ zu deinen Speicheranforderungen.

Du solltest dich aber fragen was macht dein Programm wenn malloc 
zurueckliefert das kein Speicher mehr da ist. Hast du dann eine 
Out-of-Memory BlinkLED? Oder stuerzt dein Programm einmal im Jahr ab?

Olaf

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Reine S. schrieb:
> Bei kleinen 8 Bitern ist schon richtig, aber bei einem STM32F407 sehe
> ich kein Problem sich einen Puffer per malloc zu beschaffen

Hoffentlich nicht in einer Interrupt-Routine (lief die ST-USB-Library 
nicht ausschließlich in Interrupts...?). Das gibt sonst lustige Race 
Conditions und Delays.

Autor: DPA (Gast)
Datum:

Bewertung
-5 lesenswert
nicht lesenswert
Ich würde von LTO generell abraten. Das zeug macht nur Probleme. Ich hab 
schon schlechte Erfahrungen damit gemacht, z.B. bei Projekten mit weak 
Symbols und ähnlichem.

Autor: Oliver S. (oliverso)
Datum:

Bewertung
3 lesenswert
nicht lesenswert
Pauschale Urteile sind meistens pauschal falsch.

Oliver

Autor: Reiner S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Malloc wird nur beim init aufgerufen und sollte somit kein Problem 
seien.
Die anderen Tips werde ich ausprobieren und mich dann melden.

Danke an alle.

Autor: Reiner S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch mal Danke.
Cube MX generiert ein Modul syscalls.c in der _sbrk definiert ist.
Ich habe wie von Vincent H. vorgeschlagen __attribute__((_used_)) 
eingefügt und das war die Lösung.
Bleibt die Frage warum zur Höllen der GCC _sbrk mit -flto weg optimiert.

MfG
Reiner

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Reiner S. schrieb:
> Malloc wird nur beim init aufgerufen und sollte somit kein Problem
> seien.

D.h. die Speicheraufteilung ist gar nicht dynamisch, und du weißt von 
Anfang an wofür wieviel gebraucht  wird? Dann kannst du auch eine 
globale Variable machen. Dadurch sparst du dir den Programmspeicher für 
malloc, und der Linker kann besser den Verbrauch prüfen. Schneller 
starten tut es auch.

Reiner S. schrieb:
> Bleibt die Frage warum zur Höllen der GCC _sbrk mit -flto weg optimiert.

Weil sbrk indirekt über die libc referenziert wird und der Linker das 
nicht auflöst.

Autor: Reiner S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der ganze malloc Kram sitzt in der HAL von STM und das möchte ich nicht 
ändern. Ich denke STM hat sich für malloc entschieden damit es möglichst 
universel ist und mit CubeMX harmoniert. Wider was dazu gelernt mit der 
Libc.
MfG

Autor: Mw E. (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieder ein weiterer Grund die HAL nicht zu nutzen ;)

Autor: Le X. (lex_91)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Mw E. schrieb:
> Wieder ein weiterer Grund die HAL nicht zu nutzen ;)

Genau, weil die Anfänger von STM machen ständig nur so Mist, die haben 
ja keine Ahnung.
Das kriegst du bestimmt schneller selbstgeschrieben hin. Natürlich 
hochwertiger und sicherer.

Autor: fsdf (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Le X. schrieb:
> Genau, weil die Anfänger von STM machen ständig nur so Mist, die haben
> ja keine Ahnung.

Was die ST HAL angeht, so ist sie definitiv stinkender Mist. Sie ist 
ganz nett, um eine Übersicht über die notwendigen Register zu kriegen, 
mehr aber nicht.

Die libopencm3 oder direkt Barebone auf die Register ist deutlich 
aufgeräumter.

Autor: Mw E. (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Le X. schrieb:
> Genau, weil die Anfänger von STM machen ständig nur so Mist, die haben
> ja keine Ahnung.
Leider ist es aber so.

Also was ich beim USB Host mir RTOS erlebt habe geht auf keine Kuhaut 
mehr.
(Son USB Host schreibt eben nicht mal eben selber)

Die config structs nutzen meist uint32_t oä statt enums.
Somit funktionieren keine Vorschaufunktionen von IDEs für mögliche 
Werte.
Eine suche über rechtsklick "go to definition of xyz" geht so auch nicht 
und man muss im Headerfile rumscrollen bis mans findet.
Weiterhin kann man so ausversehen falsche Bitmasken reinwerfen ohne, 
dass der Compiler meckert (vertipper).

Netter UART/PLL Bug beim L431 im Zusammenhang mit dem GammelMX:

Im UART wird eine Baudrate falsch gesetzt, weil der APB Takt falsch 
zurückgerehcnet wird.
uint32_t clk = HAL_RCC_GetPCLK2Freq(); // CLK = 31750000 statt 80000000
usartdiv = (uint16_t)(UART_DIV_SAMPLING16(clk, huart->Init.BaudRate));
Dadurch stimmt die Baudrate nicht mehr (div = 276)

Woran liegts?
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
//RCC_OscInitStruct.PLL.PLLM = 1;                    << wird von CubeMX nicht inited und steht daher auf 0 -> HAL nimmt defaultwert von 2, aber die PLL bekommt 1 im Reg
RCC_OscInitStruct.PLL.PLLN = 10;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

Leider muss ich auf Arbeit den Schrott nutzen, aber somit kann ich 
wenigstens Kompromat in meinem Redmine sammeln ;)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.