AVR-linker-Fehlermeldung "relocation truncated to fit"
Ich versuche zu kompilieren, einige-code für ein ATmega328 micro, und ich möchte, dass die Nutzung der Bibliotheken und der Kern des Arduino. Ich bin mit CMake. Ich habe zum kompilieren der core-library und alle Objekte, die von meinem code und die Bibliotheken von Arduino. Aber wenn es zu verknüpfen, zeigen Sie mir die folgende Fehlermeldung.
..."relocation truncated to fit: R_AVR_13_PCREL gegen
symbol"..."avr5/libgcc.ein"...
Habe ich gefunden über Google, dass dies ist ein häufiger Fehler, aber keine Lösung hat für mich gearbeitet. Das einzige, was ich nicht kann, ist Sie "-lm" und "lc" - flags am Ende der linker Satz, weil ich nicht weiß wie ich es machen kann, mit CMake.
BEARBEITEN: ich habe versucht zu kompilieren mit makefile auch, aber ich habe das gleiche Ergebnis, selbst setzen "-lm" und "lc" - flags am Ende der linker-Satz.
Ich mein Makefile und die CMake-Dateien hier:
CMakeList.txt Die wichtigsten CMake-Datei
cmake_minimum_required(VERSION 2.6)
Project(IMU)
set(ARDUINO_PROCESSOR atmega328p)
set(ARDUINO_PROCESSOR_FREQ 1600000L)
include(./arduino.cmake)
add_library(ardlib
libraries/EEPROM/EEPROM.cpp
libraries/Wire/utility/twi.c
libraries/Wire/Wire.cpp
libraries/HMC58X3/HMC58X3
)
LINK_DIRECTORIES(${IMU_SRC_DIR}/libarduinocore
${IMU_SRC_DIR}/libraries/EEPROM
${IMU_SRC_DIR}/libraries/Wire
${IMU_SRC_DIR}/libraries/HMC58X3
)
link_libraries(arduinocore ardlib)
include_directories(
libarduinocore
libraries/EEPROM
libraries/Wire
libraries/Wire/utility
libraries/HMC58X3
)
set(C_SRCS
ADXL345.cpp
ApplicationRoutines.cpp
DCM.cpp
HMC5883L.cpp
ITG3200.cpp
matrix.cpp
output.cpp
timing.cpp
vector.cpp
)
set(C_HDRS
ADXL345.h
ApplicationRoutines.h
DCM.h
HMC5883L.h
ITG3200.h
matrix.h
output.h
timing.h
vector.h
declarations.h
)
add_executable(IMU.elf main.cpp ${C_SRCS} ${C_HDRS})
add_subdirectory(libarduinocore)
arduino.cmake. Importierte CMakeList.txt:
set(ARDUINO_PROCESSOR atmega328p)
set(ARDUINO_PROCESSOR_FREQ 16000000L)
# This module defines macros intended for use by cross-compiling toolchain files when
# CMake is not able to automatically detect the compiler identification.
include (CMakeForceCompiler)
# Set this for cross compiling. Otherwise it is set to CMAKE_HOST_SYSTEM_NAME,
# which is the system we are developing on.
set (CMAKE_SYSTEM_NAME Generic)
# It sets CMAKE_<lang>_COMPILER to the given compiler and the cmake internal variable
# CMAKE_<lang>_COMPILER_ID to the given compiler-id. It also bypasses the check for
# working compiler and basic compiler information tests.
SET(CMAKE_C_COMPILER avr-gcc)
SET(CMAKE_CXX_COMPILER avr-g++)
cmake_force_cxx_compiler (avr-g++ CrossAVR)
cmake_force_c_compiler (avr-gcc CrossAVR)
# Appparently we want to use the gnuc99 standard.
#set (CSTANDARD "-std=gnu99")
# Generate .stabs debugging symbols for assembler source lines. This enables avr-gdb to
# trace through assembler source files.
#set (CDEBUG "-gstabs")
# Warn for functions declared or defined without specified argument types.
set (CWARN "-Wall -Wstrict-prototypes")
# -funsigned-char - Make any unqualfied char type an unsigned char. Without this option,
# they default to a signed char.
# -funsigned-bitfields - Make any unqualified bitfield type unsigned. By default,
# they are signed.
# -fpack-struct - Pack all structure members together without holes.
# -fshort-enums - Allocate to an enum type only as many bytes as it needs for the declared
# range of possible values. Specifically, the enum type will be equivalent to the
# smallest integer type which has enough room.
set (CTUNING_FLAGS "-ffunction-sections -fdata-sections -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums")
# Optimize for size. The special option -Os is meant to turn on all -O2 optimizations
# that are not expected to increase code size.
set (COPT "-Os")
SET(CINCS "-I${ArduinoCode_SOURCE_DIR}/libarduinocore")
# Finally the compilation flags are now configured.
set(CMAKE_CXX_FLAGS "-lc -lm -mmcu=${ARDUINO_PROCESSOR} -DF_CPU=${ARDUINO_PROCESSOR_FREQ} ${CTUNING_FLAGS} ${CWARN} ${CSTANDARD} ${CDEBUG} ${COPT} ${CINCS} -lc")
set(CMAKE_C_FLAGS "-lc -lm ${CMAKE_CXX_FLAGS} ${CTUNING_FLAGS} ${CWARN} ${CSTANDARD} ${CDEBUG} ${CINCS} -lc")
# On gentoo, -rdynamic is passed to the compiler. The avr compiler does not recognize this
# option. Also, we are not building shared libraries.
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS ""
Arduino-core CMake-Datei. Dies ist ein CMakeList.txt Datei in libarduinocore
Verzeichnis.
include(../arduino.cmake)
add_library (arduinocore
HardwareSerial.cpp
pins_arduino.c
Print.cpp
Tone.cpp
WInterrupts.c
wiring_analog.c
wiring.c
wiring_digital.c
wiring_pulse.c
wiring_shift.c
WMath.cpp
WString.cpp
)
Makefile
TARGET = IMU
PORT = /dev/ttyACM0
BAUD = 57600
PROGRAMMER = arduino
MCU = atmega328p
F_CPU = 8000000L
CXX_SRCS = ADXL345.cpp \
ApplicationRoutines.cpp \
DCM.cpp \
HMC5883L.cpp \
ITG3200.cpp \
matrix.cpp \
output.cpp \
timing.cpp \
vector.cpp
CXX_OBJ = $(CXX_SRCS:.cpp=.o)
CXX_HDRS = ADXL345.h \
ApplicationRoutines.h \
DCM.h \
declarations.h \
HMC5883L.h \
ITG3200.h \
matrix.h \
output.h \
timing.h \
vector.h
CORE_DIR = libarduinocore
CORE_CXX_SRCS = $(CORE_DIR)/HardwareSerial.cpp \
$(CORE_DIR)/Print.cpp \
$(CORE_DIR)/Tone.cpp \
$(CORE_DIR)/WMath.cpp \
$(CORE_DIR)/WString.cpp
CORE_CXX_OBJ = $(CORE_CXX_SRCS:.cpp=.o)
CORE_CC_SRCS = $(CORE_DIR)/pins_arduino.c \
$(CORE_DIR)/WInterrupts.c \
$(CORE_DIR)/wiring_analog.c \
$(CORE_DIR)/wiring.c \
$(CORE_DIR)/wiring_digital.c \
$(CORE_DIR)/wiring_pulse.c \
$(CORE_DIR)/wiring_shift.c
CORE_CC_OBJ = $(CORE_CC_SRCS:.c=.o)
CORE_HDRS = $(CORE_DIR)/binary.h \
$(CORE_DIR)/HardwareSerial.h \
$(CORE_DIR)/pins_arduino.h \
$(CORE_DIR)/Print.h \
$(CORE_DIR)/Stream.h \
$(CORE_DIR)/WCharacter.h \
$(CORE_DIR)/WConstants.h \
$(CORE_DIR)/wiring.h \
$(CORE_DIR)/wiring_private.h \
$(CORE_DIR)/WProgram.h \
$(CORE_DIR)/WString.h
ARD_LIB_DIR = libraries
ARD_LIB_CXX_SRCS = $(ARD_LIB_DIR)/EEPROM/EEPROM.cpp \
$(ARD_LIB_DIR)/Wire/Wire.cpp \
$(ARD_LIB_DIR)/HMC58X3/HMC58X3.cpp
ARD_LIB_CC_SRCS = $(ARD_LIB_DIR)/Wire/utility/twi.c
ARD_LIB_CXX_OBJ = $(ARD_LIB_CXX_SRCS:.cpp=.o)
ARD_LIB_CC_OBJ = $(ARD_LIB_CC_SRCS:.c=.o)
CC = avr-gcc
CXX = avr-g++
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AR = avr-ar
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
ARD_LIB_INC = -I$(ARD_LIB_DIR) -I$(ARD_LIB_DIR)/EEPROM -I$(ARD_LIB_DIR)/Wire -I$(ARD_LIB_DIR)/HMC58X3 -I$(ARD_LIB_DIR)/Wire/utility
FLAGS_WARN = -Wall -Wstrict-prototypes
FLAGS_TUNING = -ffunction-sections -fdata-sections -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
FLAGS_OPT = -Os
ALL_INC = -I. $(ARD_LIB_INC) -I$(CORE_DIR)
OBJS = $(CXX_OBJ) $(CORE_CXX_OBJ) $(CORE_CC_OBJ) $(ARD_LIB_CC_OBJ) $(ARD_LIB_CXX_OBJ)
ALL_OBJS := $(addprefix build/, $(notdir $(OBJS)))
ALL_CFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) $(ALL_INC) $(FLAGS_WARN) $(FLAGS_TUNNIG) $(FLAGS_OPT)
ALL_CXXFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) $(ALL_INC) -Wall $(FLAGS_TUNNIG) $(FLAGS_OPT)
#ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
all : $(TARGET).hex
avr-objcopy -O ihex -R .eeprom $(TARGET).out $(TARGET).hex
$(TARGET).out : $(OBJS)
$(CXX) $(ALL_CXXFLAGS) main.cpp $(ALL_OBJS) -o $(TARGET).out -lc -lm
upload : $(TARGET).hex
avrdude -c$(PROGRAMMER) -p$(MCU) -P$(PORT) -U flash:w:$(TARGET).hex
serialmon :
picocom -b$(BAUD) $(PORT)
.SUFFIXES: .hex .cpp .o .c
# Compile: create object files from C++ source files.
.cpp.o:
$(CXX) -c $(ALL_CXXFLAGS) $< -o $(addprefix build/, $(notdir $@)) -lc -lm
# Compile: create object files from C source files.
.c.o:
$(CC) -c $(ALL_CFLAGS) $< -o $(addprefix build/, $(notdir $@)) -lc -lm
# Compile: create assembler files from C source files.
.c.s:
$(CC) -S $(ALL_CFLAGS) $< -o build/$@ -lc -lm
- Können Sie zeigen, zu welchen Leistungen Sie bekommen, wenn mit dem Makefile? Ich hatte gerade das exakt gleiche problem und löste es durch hinzufügen der-lm (aber keine -lc) an. Ich habe es nur bis zum Ende der Zeile für die .elf-target im Makefile.
- Sind y ' all wissen, du bist nicht nur der Speicherplatz aus? Der 328p hat eine satte 32KB Speicherplatz, und einige, die von den boot-loader.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Erklärung:
Wie die Fehlermeldung schon sagt, das Problem hat zu tun mit der Umzug (code), die bewirkt, dass einige abschneiden auftreten. Die Fehlermeldung kommt vom linker, die versucht, die Karte code-Stücken, die an geeigneten stellen in den Programm-Speicher.
Wenn der code platziert oder verschoben werden, um einen Ort ("relocation") und dieser code bezeichnet wird, aus einem anderen Stück code, über
JMP
oderCALL
(z.B. einen Funktionsaufruf), der verlegt-Adresse Hinzugefügt werden, um dieJMP
oderCALL
Anweisung darauf zu verweisen.Die AVR-Geräte unterstützen zwei Arten von jump/call-Anweisungen:
JMP
vs.RJMP
, undCALL
vs.RCALL
. DieR
Varianten telefonieren relative um die aktuelle Lage und effizienter sind sowohl bei der Nutzung der Programm-Speicher und Ausführungszeit. Dies kommt zu einem Preis allerdings:RJMP
undRCALL
können nur verwendet werden, für die Adressen im Bereich von +/-4kb von Ihrer Position im Programm-Speicher. Dies ist nie ein problem auf Geräten mit nicht mehr als 8 Kb Programm-Speicher, da das ganze 8kb Bandbreite angesprochen werden können von jedem Standort aus überRCALL
oderRJMP
.Auf Geräten mit mehr als 8 Kb Programm-Speicher, jedoch gilt dies nicht für alle möglichen Standorten. Daher wenn die linker entscheidet, kann er den code aufgerufen werden innerhalb die +/-4kb reichen von der
RJMP
/RCALL
wird es kein problem sein, aber wenn der linker schlägt zu (re-)suchen Sie den code in diesem BereichRJMP
/RCALL
nicht verwendet werden, um erreichen die code ' s neue Adresse, die Adresse ist so abgeschnitten (nur wie, wenn dabeiuint16_t value = 12345; uint8_t truncatedValue = value;
in C) und den generierten code bricht.Beachten Sie, dass diese kann oder kann nicht geschehen für ein Projekt in überschreitung 4 Kb Programm-Speicher (auf Geräten mit >8 Kb Programm-Speicher) an einem gewissen Punkt, denn es hängt von der Verlagerung der code benötigt, der kann im Grunde ändern sich mit jeder neuen Zeile C-code Hinzugefügt oder entfernt werden, mit der jede Bibliothek, die Hinzugefügt werden, linked in, oder auch die um, in dem die Bibliotheken oder anderen code-Stücken, die miteinander verbunden sind (z.B. Aufruf von "A" bis "B" kann funktionieren, wenn der linker sucht den code, der wie "A B C" aber nicht, wenn der linker entscheidet, zu verlagern, wie "A C B").
Lösung:
Teilen Sie der compiler weiß, dass es braucht, um zu generieren
JMP
/CALL
Anweisungen anstelle der (effizienteren)RJMP
/RCALL
Anweisungen. Im AVR Studio/Atmel Studio diese kann getan werden, in der die Eigenschaften des Projekts, toolchain-AVR/GNU C compiler-Optimierung. Die entsprechende option ist "Use rjmp/rcall (begrenzte Reichweite) auf >8k-Geräte (-mshort-Aufrufe)" werden muss deaktiviert um zu verhindern, dass die genannten Fehler.Wie auf dem Etikett angegeben ist, die entsprechenden Kommandozeilen-option ist
-mshort-calls
werden muss entfernt aus den gcc-Befehlszeile-parameter-Liste, um das gleiche zu erreichen, dass beim Aufruf von gcc, die von außerhalb der IDE.Update:
Vermeiden Sie die unnötige Verwirrung, die diesen Fehler verursachen können
-mshort-calls
war deprecated in avr-gcc 4.7 und entfernt werden, vom 4.8. Quelle: GCC 4.8 Änderungen.Benutzer nun
-mrelax
statt zu generieren binäre, haben die call-Optimierungen, wo möglich aber nie produzieren den Fehler.Lief ich ins avr-gcc-Umzug abschneiden Fehlermeldung und verbrachte ein paar
Tage Sortieren Sie es aus. Kurz gesagt, es scheint ein bug in den linker.
Für eine schnelle Lösung, setzen Sie diese in Ihren code in den globalen Variablen Bereich. Sie
möglicherweise versuchen Sie ein paar verschiedene array-Größen.
Hier ist was Los. Die ersten 224 bytes flash-Speicher sind die interrupt -
Vektor-Tabelle. Wenn ein interrupt Auftritt (wie ein timer abläuft, oder es ist ein byte
warten in einigen Empfangspuffer), diese Tabelle teilt dem Prozessor mit, welcher code
ausführen. In diesem Beispiel verwenden nicht viele interrupts, so dass nicht verwendete Vektoren geschickt bekommen
die routine bad_interrupt(). Hier ein paar Zeilen aus der Vektor-Tabelle.
Ein paar Dinge zu beachten
Verwendung von jmp und rjmp ist ein Artefakt der -mrelax compiler-flag.
Unter anderem, es teilt dem compiler zu verwenden rjmp Anweisungen
wenn das Ziel nahe genug ist (das ist +/- 4k). Ansonsten
der compiler jmp verwenden. Dies ist nicht eine schlechte Sache, rjmp Anweisungen
run 1 Uhr schneller und mit 2 bytes weniger Daten.
Ohne -mrelax, verwendet der compiler nur jmp Anweisungen in den Vektor
Tabelle und das problem geht Weg. BTW, für unsere Zwecke, --entspannen ist
das gleiche wie -mrelax.
Das problem ist, dass der linker immer verklemmt sich irgendwie. In der oben
Beispiel, wenn die bad_interrupt routine befindet sich an der Adresse 0x1028,
der Vektor sollte bei der Adresse 0x24 sollten wiederum in einer jmp-aber der linker
kann es nicht aus irgendeinem Grund. Stattdessen verlässt es die Anweisung, wie ein
rjmp mit einer relativen offset von +4098. Als der zulässige Bereich ist 4096,
das offset abgeschnitten, an +2, das ist ein schwerer Fehler.
Der Grund, warum "pad[500] PROGMEM = { 0 };" sollte funktionieren, ist es zuordnen
ein Stück des flash-Speichers zwischen die Vektor-Tabelle und bewegt sich bad_interrupt()
weit genug Weg von der vector-Tabelle, dass der linker gar nicht in Versuchung
verwenden Sie eine rjmp-Instruktion.
In die Suche im web, das scheint ein chronisches problem bei allen
Arten von Lösungen, die manchmal funktioniert. Beliebt sind Sie mit mehr/weniger
PSTR("Hallo Welt") konstruiert und verschiedene -lm -lc-Optionen. Ich vermute
diese Dinge sind nur ein wackeln um Unterroutine Adressen und blind
Glück fallen Sie in Orten, die funktionieren.
Unten ist der code, den ich verwendet, um zu isolieren, dieser bug.
Ich habe das problem gelöst, ich habe umstrukturiert code (habe ich gelöscht fast alle globals-Variablen), und ich habe Hinzugefügt '-lc -lm -lc' - flags an makefile. Ich nehme an, das problem war der code-Struktur, zu viele Globale Variablen aufgrund der schlechten Anpassung von einem arduino-code-Stil (Alle source-Dateien sind eingefügt in der gleichen Datei)
Ich legte das makefile hier, ich hoffe, es ist nützlich, um jemanden:
Ich habe mit diesem problem für die letzten paar Stunden, und schließlich gelöst. Für mich hatte es mit der Tatsache zu tun, dass der avr libm.ein muss einbezogen werden in den linker-Befehl, und ich war mit dem Math.h-Bibliothek, die getrennt von der libc.eine Bibliothek, und das war nicht korrekt verlinkt.
Versuchen Modifikation der linker-Befehl zu suchen, wie Sie dies, indem Sie -lc -lm am Anfang des Befehls und lc am Ende:
Meine Referenz:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1290294587
Entledigte ich mich der Umzug Fehler nach einem langen Kampf
durch das hinzufügen von -lm -lc-SATZ(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-lm -Lz")
so werden Sie an das Ende von CMke in link.txt
Meine CMakeLists.txt
link.txt Aussehen würde.
Ich es aussortiert von overring Regeln auf der Unterseite von meinem makefile :