Ich habe ein Programm aus der Arduino-Umgebung in ein Makefile-Build mit winavr portiert, das wiederum auf avr-gcc basiert (genau wie Arduino).
Mein Programm fing jedoch an abzustürzen, und nach einigen Nachforschungen stellte ich fest, dass mir aufgrund einer Erhöhung des Heapspeichers um 256 Byte der Datenspeicher ausging, obwohl ich das Programm überhaupt nicht geändert hatte.
Wenn ich mir die Map-Datei ansehe, sehe ich, dass eine neue Tabelle enthalten ist, __clz_tab
, die 256 Bytes groß ist und sich im RAM befindet.
Wie werde ich diese Tabelle los und bekomme meinen RAM zurück?
libc, die in gcc und avr-gcc enthalten ist, hat eine Funktion, die verwendet wird, um führende Nullen zu zählen, wenn von an int
oder uint
in a float
oder a konvertiert wird double
. Diese Funktion verwendet eine 256-Byte-Tabelle, um die Nullzählung zu beschleunigen, was gut für Computer mit viel Speicher ist, aber nicht so gut für Mikrocontroller, bei denen 256 Bytes 1/4 oder 1/8 des gesamten verfügbaren Arbeitsspeichers ausmachen.
avr-gcc enthält eine Bibliothek libm.o
mit alternativen Definitionen für einige Funktionen, einschließlich der Funktion, die __clz_tab
. Diese Definition benötigt weniger Speicher, daher müssen Sie den Linker anweisen, gegen libm zu linken.
Dies erfolgt durch Hinzufügen -lm
zur Linker-Befehlszeile.
-lm
Die Position dieses Befehlsparameters spielt jedoch eine Rolle - er löst nur Links zu Symbolen vor diesem Parameter auf, daher sollte der Parameter so nahe wie möglich am Ende der Befehlszeile stehen, um das Beste daraus zu machen .
Bei mir Makefile
sieht es so aus:
CXX=avr-gcc
CFLAGS=$(MCU) $(CPU_SPEED) -g -Os -w -Wl,--gc-sections -ffunction-sections -fdata-sections
LFLAGS= -Wl,--section-start=.text=0x0000,-Map=program.map
INCLUDE=-I ../include/arduino/
LIBS=-L ../lib -larduino -lm
default: program.hex
program.hex: program.elf
avr-objcopy -O ihex $< $@
program.elf: bcu_usb.cpp main.cpp programmer.cpp
$(CXX) $(CFLAGS) $(LFLAGS) $(INCLUDE) $^ -o $@ $(LIBS)
Beachten Sie, dass das letzte Element in der Compiler-Befehlszeile $(LIBS)
und das letzte Element darin LIBS
ist, -lm
wodurch sichergestellt wird, dass der Compiler den Definitionen in libm Vorrang gibt, wenn mehrere Definitionen verfügbar sind.
Neuere Versionen von avr-gcc haben dieses Problem behoben, sodass dies nicht einmal ohne die auftritt -lm
, die Arduino-IDE installiert und verwendet jedoch immer noch die älteren Versionen von avr-gcc, und winavr wurde nicht aktualisiert, seit dieser Fehler behoben wurde.
Den Fehlerbericht können Sie hier lesen:
Vicatcu