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
:
Gesperrt durch Moderator
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.
soweit ich mich erinnere ist für LTO ein plugin nötig, selbiges teilt man ar, ld und co über gcc/g++ mittels
1 | -r --plugin /usr/lib/gcc/arm-none-eabi/7.3.1/liblto_plugin.so.0 |
mit. Pfad je nach Version und Betriebssytem anpassen.
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?
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.
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 :)
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.
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
Markier sbrk mal testweise als "used" via
1 | __attribute__((__used__)) |
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.
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.
> 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
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.
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.
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.
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
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.
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
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.
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.
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.