Arm GCC mit Option -flto erzeugt Fehler

Gast #5779840
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
Gast #5780367
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.
Gast #5780384
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
Gast #5780402
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.
Gast #5780419
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
Gast #5780657
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.
(Firma: fritzler-avr.de) #5794004
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?
1
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
2
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
3
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
4
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
5
//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
6
RCC_OscInitStruct.PLL.PLLN = 10;
7
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
8
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
9
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 ;)
Beitrag #7410353 wurde von einem Moderator gelöscht.
Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.