Der einfachste Weg, um __clz_tab in winavr-kompiliertem Code loszuwerden?

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?

Welche Version von avr-gcc und avr-libc verwenden Sie in beiden Fällen? Arduino wird mit einer eigenen Kopie der Toolkette ausgeliefert und mit verschiedenen gesetzten Flags kompiliert, was Sie beobachten können, indem Sie mit ausführlicher Ausgabe in der Arduino IDE kompilieren (halten Sie die Umschalttaste gedrückt, während Sie in der < 1.0 IDE auf Kompilieren klicken, oder wählen Sie es in den Einstellungen aus Dialog in der >= 1.0 IDE).

Antworten (1)

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 intoder uintin a floatoder 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.omit 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 -lmzur Linker-Befehlszeile.

-lmDie 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 Makefilesieht 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 LIBSist, -lmwodurch 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:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29524

@vicatcu werde ich, sobald das System es zulässt. Es gibt eine zweitägige Wartezeit für die Annahme der eigenen Antwort auf Stack Exchange.