我正在尝试为ATmega328 micro编译一些代码,我想使用Arduino的库和核心。我正在使用CMake。我已经编译了核心库以及我的代码的所有对象和Arduino的库。但是当它链接时,它们会向我显示以下错误。
...“重定位被截断以适合:R_AVR_13_PCREL对 符号” ... “avr5 / libgcc.a的” ...
我found through Google这是一个常见错误,但没有任何解决方案对我有用。我唯一不能做的是在链接器句子的末尾加上“-lm”和“-lc”标志,因为我不知道如何用CMake做到这一点。
编辑:我已尝试使用makefile编译它,但我得到了相同的结果,甚至在链接器句子的末尾加上“-lm”和“-lc”标志。
我把Makefile和CMake文件放在这里:
CMakeList.txt 主CMake文件
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 即可。这是由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核心CMake文件。这是放入libarduinocore
目录的CMakeList.txt文件。
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
)
生成文件
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
答案 0 :(得分:11)
正如错误消息所示,该问题与重定位(代码)有关,导致发生一些截断。消息来自链接器,它试图将代码片段映射到程序存储器中的适当位置。
当代码被放置或移动到某个位置(“重定位”)和时,此代码将通过JMP
或CALL
从另一段代码引用(即函数调用),必须将重定位的地址添加到引用它的JMP
或CALL
指令中。
AVR设备支持两种种跳转/通话指令:JMP
与RJMP
和CALL
与RCALL
。 R
变体使 relative 调用到当前位置,并且在程序存储器的使用和执行时间方面都更有效。这需要付出代价:RJMP
和RCALL
只能用于程序存储器中位置+/- 4kb范围内的地址。对于程序存储器不超过8kb的设备,这绝不是问题,因为整个8kb范围可以通过RCALL
或RJMP
从任何位置进行寻址。
在程序内存超过8kb的设备上,所有可能的位置都不是这样。因此, if RJMP
没有问题,但是如果链接器无法(重新)找到代码在该范围内,RCALL
/ RJMP
不能用于访问代码的新地址,因此地址截断(就像在C中执行RCALL
时一样)并且生成的代码中断。
请注意,对于超过4kb程序内存的任何给定项目(在程序内存大于8kb的设备上),此可能或可能不会发生,因为这取决于所需代码的重新定位,这可能会随着添加或删除的每个新C代码行而变化,每个库都被添加到链接中,甚至是 order 中的库或其他代码片段链接在一起(例如,当链接器找到像“ABC”这样的代码时,从“A”到“B”的调用可能有效,但当链接器决定像“ACB”那样重新定位时失败。
您必须让编译器知道它需要生成uint16_t value = 12345; uint8_t truncatedValue = value;
/ JMP
指令而不是(更有效的)CALL
/ RJMP
指令。在AVR Studio / Atmel Studio中,可以在项目的属性,工具链,AVR / GNU C编译器,优化中完成。相关选项是“在&gt; 8k设备上使用rjmp / rcall(限制范围)(-mshort-calls)”,需要取消选中以防止指定错误。
如标签所示,相关的命令行选项是RCALL
,需要从gcc命令行参数列表中删除,以便在从IDE外部调用gcc时实现相同的目的。
为避免不必要的混淆,此错误可能导致-mshort-calls
在
用户现在应该使用-mshort-calls
来生成具有可能的调用优化的二进制文件,但绝不会产生错误。
答案 1 :(得分:3)
我遇到了avr-gcc重定位截断错误消息并花了一些时间 整理出来的日子。简而言之,链接器中似乎存在一个错误。
要快速修复,请将其放在全局变量区域的代码中。您 可能需要尝试几种不同的数组大小。
#include <avr/pgmspace.h>
const char pad[500] PROGMEM = { 0 };
这是发生了什么。闪存的前224个字节是中断 矢量表。发生中断时(如计时器到期或有一个字节) 等待一些接收缓冲区),这个表告诉处理器代码是什么 执行。此示例不使用许多中断,因此将发送未使用的向量 到例程bad_interrupt()。这是矢量表中的几行。
0000 <__vectors>:
0: 0c 94 08 08 jmp 0x1010 ; 0x1010 <__ctors_end>
4: 0c 94 12 08 jmp 0x1024 ; 0x1024 <__bad_interrupt>
8: 0c 94 12 08 jmp 0x1024 ; 0x1024 <__bad_interrupt>
c: 0c 94 12 08 jmp 0x1024 ; 0x1024 <__bad_interrupt>
10: 0c 94 12 08 jmp 0x1024 ; 0x1024 <__bad_interrupt>
14: 0c 94 12 08 jmp 0x1024 ; 0x1024 <__bad_interrupt>
18: 0c 94 12 08 jmp 0x1024 ; 0x1024 <__bad_interrupt>
1c: 0c 94 12 08 jmp 0x1024 ; 0x1024 <__bad_interrupt>
20: 0c 94 12 08 jmp 0x1024 ; 0x1024 <__bad_interrupt>
24: ff c7 rjmp .+4094 ; 0x1024 <__bad_interrupt>
26: 00 00 nop
28: fd c7 rjmp .+4090 ; 0x1024 <__bad_interrupt>
2a: 00 00 nop
2c: fb c7 rjmp .+4086 ; 0x1024 <__bad_interrupt>
2e: 00 00 nop
30: f9 c7 rjmp .+4082 ; 0x1024 <__bad_interrupt>
要注意的一些事项
使用jmp和rjmp是-mrelax编译器标志的工件。 除此之外,它还告诉编译器使用rjmp指令 当目的地足够接近时(+/- 4k)。除此以外, 编译器应该使用jmp。这不是坏事,rjmp说明 运行时间更快,使用2个字节的数据。
如果没有-mrelax,编译器仅使用向量中的jmp指令 表和问题消失了。顺便说一下,为了我们的目的, - 放松是 与-mrelax相同。
问题是链接器以某种方式卡住了。在上面 例如,当bad_interrupt例程位于地址0x1028时, 地址0x24处的向量应该变成jmp但链接器 由于某种原因不能这样做。相反,它将指令保留为 rjmp的相对偏移量为+4098。由于允许的范围是4096, 偏移量将被截断为+2,这是一个严重的错误。
“pad [500] PROGMEM = {0};”的原因应该工作是否会分配 向量表和移动bad_interrupt()之间的一块闪存 离矢量表足够远,链接器甚至没有诱惑 使用rjmp指令。
在搜索网络时,这似乎是所有人的长期问题 各种有时有效的解决方案。流行使用更多/更少 PSTR(“Hello World”)构造和各种-lm -lc选项。我猜测 这些东西只是在子程序地址和盲目的情况下摇摆不定 幸运的是,他们落在了有效的地方。
以下是我用来隔离此错误的代码。
//
// rjmp vector table relocation truncation bug
//
// works when the -mrelax option is not used
//
// avr-gcc -g -Wall -mrelax pad.c -mmcu=atmega2560 -Wl,-Map -o pad.elf
// avr-objdump -h -S pad.elf > pad.list
//
// avr-gcc --version -> avr-gcc (GCC) 4.7.2
//
#include <avr/pgmspace.h>
// note, there are other bands of works/fails
//
// 3884 works
// 3886 fails
// 3894 fails
// 3896 works
const char pad[3886] PROGMEM = { 0 };
int main() {
int i, j;
for (i = 0; 1; i++)
j += pad[i];
}
答案 2 :(得分:2)
我已经解决了这个问题,我重新组织了代码(我删除了几乎所有的全局变量)并且我在makefile中添加了“-lc -lm -lc”标志。我认为问题是代码结构,由于arduino代码样式的不良适应而导致的全局变量太多(所有源文件都粘贴到同一个文件中) 我把makefile放在这里,我希望它对某人有用:
TARGET = IMU
PORT = /dev/ttyUSB0
BAUD_P = 57600
BAUD_T = 9600
PROGRAMMER = arduino
MCU = atmega328p
F_CPU = 8000000L
CXX_SRCS = ADXL345.cpp \
ApplicationRoutines.cpp \
DCM.cpp \
HMC5883L.cpp \
ITG3200.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 \
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) $(FLAGS_TUNNIG) $(FLAGS_OPT) #-Wall
#ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
END_FLAGS = -lc -lm -lc
all : $(TARGET).hex
$(TARGET).hex : $(TARGET).out
avr-objcopy -O ihex -R .eeprom $(TARGET).out $(TARGET).hex
$(TARGET).out : $(OBJS)
$(CXX) $(ALL_CXXFLAGS) main.cpp $(ALL_OBJS) -o $(TARGET).out $(END_FLAGS)
upload : $(TARGET).hex
avrdude -c$(PROGRAMMER) -p$(MCU) -b$(BAUD_P) -P$(PORT) -U flash:w:$(TARGET).hex
serialmon :
picocom -b$(BAUD_T) $(PORT)
.SUFFIXES: .elf .hex .eep .lss .sym .cpp .o .c .s .S
# Define all listing files.
#LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
# Compile: create object files from C++ source files.
.cpp.o:
$(CXX) -c $(ALL_CXXFLAGS) $< -o $(addprefix build/, $(notdir $@)) $(END_FLAGS)
# Compile: create object files from C source files.
.c.o:
$(CC) -c $(ALL_CFLAGS) $< -o $(addprefix build/, $(notdir $@)) $(END_FLAGS)
# Compile: create assembler files from C source files.
#.c.s:
# $(CC) -S $(ALL_CFLAGS) $< -o build/$@ -lm
# Assemble: create object files from assembler source files.
#.S.o:
# $(CC) -c $(ALL_ASFLAGS) $< -o build/$@
答案 3 :(得分:2)
过去几个小时我一直在研究这个问题,最后解决了这个问题。对我来说,这与avr libm.a必须包含在链接器命令中的事实有关,我使用的是Math.h库,它与libc.a库是分开的,并且没有正确链接
尝试通过在命令开头添加-lc -lm并在结尾处添加-lc来修改链接器命令,如下所示:
${CMD} -lc -lm ${FLAGS} ${OUTPUT_FLAG}${OUTPUT_PREFIX}${OUTPUT} ${INPUTS} -lc
我的参考: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1290294587
答案 4 :(得分:0)
经过长时间的斗争,我摆脱了搬迁错误 通过向SET添加-lm -lc(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS“-lm -lc”) 所以它们最后会被CMke在link.txt中附加 我的CMakeLists.txt
# generated by cmkoder
PROJECT (ermote1.cmk)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
SET(CMAKE_SYSTEM_NAME Generic)
SET(OUT_BINARY_FILE ermote1)
SET(ENV{CROSS_COMPILE} avr-)
SET(ENV{ARCH} arm)
SET(ENV{TC_BASE} /home/arduino-1.0.5)
SET(CROSS_COMPILE avr-)
SET(ARCH arm)
SET(TC_BASE /home/arduino-1.0.5)
SET(TC_SRC_PATH ${TC_BASE}/libraries/)
SET(CMAKE_CXX_COMPILER ${CROSS_COMPILE}c++)
SET(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc)
SET(TC_LIB_LINKER ${CROSS_COMPILE}ar)
SET(TC_GDB ${CROSS_COMPILE}gdb)
SET(HW_MMCU "-mmcu=atmega328p")
SET(HW_DF_CPU "-DF_CPU=16000000L")
SET(HW_VARIANT "eightanaloginputs")
SET (TC_DEFINES "-DARDUINO=105 -DUSB_VID=null -DUSB_PID=null")
SET(CMAKE_CXX_FLAGS "-g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -lm -Wl,-gc-sections ${HW_MMCU} ${HW_DF_CPU} -lc ${TC_DEFINES}")
SET(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}")
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-lm -lc")
SET(CMAKE_FIND_ROOT_PATH ${TC_BASE}/hardware/tools/avr/bin ${TC_BASE}/hardware/tools ${TC_BASE}/hardware/tools/avr/lib/avr/lib)
SET(CMAKE_LIBRARY_PATH "")
INCLUDE_DIRECTORIES (${TC_BASE}/hardware/arduino/cores/arduino/
${TC_BASE}/hardware/arduino/variants/${HW_VARIANT}/
${TC_BASE}/libs/
${TC_BASE}/libraries/
${TC_SRC_PATH}SoftwareSerial
${TC_SRC_PATH}Wire
${TC_SRC_PATH}Wire/utility
${TC_SRC_PATH}Ermote
${TC_SRC_PATH}Adafruit_BMP085)
SET(TC_SOURCES ${TC_BASE}/hardware/arduino/cores/arduino/HardwareSerial.cpp
${TC_BASE}/hardware/arduino/cores/arduino/Print.cpp
${TC_BASE}/hardware/arduino/cores/arduino/WInterrupts.c
${TC_BASE}/hardware/arduino/cores/arduino/wiring_analog.c
${TC_BASE}/hardware/arduino/cores/arduino/wiring.c
${TC_BASE}/hardware/arduino/cores/arduino/wiring_digital.c
${TC_BASE}/hardware/arduino/cores/arduino/wiring_pulse.c
${TC_BASE}/hardware/arduino/cores/arduino/wiring_shift.c
${TC_BASE}/hardware/arduino/cores/arduino/WMath.cpp
${TC_BASE}/hardware/arduino/cores/arduino/WString.cpp
${TC_BASE}/hardware/arduino/cores/arduino/main.cpp
${TC_BASE}/hardware/arduino/cores/arduino/new.cpp)
SET(SDK_SRCS ${TC_SRC_PATH}/SoftwareSerial/SoftwareSerial.cpp
${TC_SRC_PATH}/Wire/Wire.cpp
${TC_SRC_PATH}/Wire/utility/twi.c
${TC_SRC_PATH}/Adafruit_BMP085/Adafruit_BMP085.cpp)
SET(PRJ_SRCS start.cpp)
FIND_PROGRAM(AVROBJCOPY "avr-objcopy")
FIND_PROGRAM(AVRDUDE "avrdude")
FIND_PROGRAM(AVRSIZE "avr-size")
if(AVROBJCOPY)
add_custom_target(hex)
add_dependencies(hex ${OUT_BINARY_FILE})
add_custom_command(TARGET hex POST_BUILD
COMMAND ${AVROBJCOPY} -O ihex -R .eeprom ./${OUT_BINARY_FILE} ./${OUT_BINARY_FILE}.hex
)
add_custom_target(elf)
add_dependencies(elf ${OUT_BINARY_FILE})
add_custom_command(TARGET elf POST_BUILD
COMMAND ${AVROBJCOPY} -O ihex -R .eeprom ./${OUT_BINARY_FILE} ./${OUT_BINARY_FILE}.elf
)
add_custom_target(eep)
add_dependencies(eep ${OUT_BINARY_FILE})
add_custom_command(TARGET eep POST_BUILD
COMMAND ${AVROBJCOPY} -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 ./${OUT_BINARY_FILE} ./${OUT_BINARY_FILE}.eep
)
endif()
ADD_EXECUTABLE ( ${OUT_BINARY_FILE} ${TC_SOURCES} ${SDK_SRCS} ${PRJ_SRCS})
link.txt看起来像。
avr-c++ -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-
sections -lm -Wl,-gc-sections -mmcu=atmega328p -DF_CPU=16000000L -lc
-DARDUINO=105 -DUSB_VID=null -DUSB_PID=null <all the
CMakeFiles/....cpp.o > -o ermote1 -lm -lc
答案 5 :(得分:0)
我通过makefile底部的覆盖规则对其进行了整理:
# (...)
include /usr/share/arduino/Arduino.mk
LDFLAGS += -lc -lm
$(TARGET_ELF): $(LOCAL_OBJS) $(CORE_LIB) $(OTHER_OBJS)
$(CC) $(LDFLAGS) -o $@ $(LOCAL_OBJS) $(CORE_LIB) $(OTHER_OBJS)
答案 6 :(得分:0)
在使用MPLAB X IDE和AVR-Toolchain来为ATtiny861编译简短的C程序时,我遇到了同样的问题。 我还使用了项目属性的链接器菜单中的params -lc -lm,我发现它与-O0一起使用无需编译器优化。 过了一会儿,我认为没有优化可以肯定不是理想的,所以我再次尝试使用-O3-效果很好!没有重定位错误!
也许这有助于进一步检查。我对这一切的了解不是很深,所以希望我不会再遇到此错误。
答案 7 :(得分:0)
-lm
按照其他答案中的建议添加-lm
对于最新版本的avr-gcc(v4.7.2,2012年及更新版本),不是正确的解决方案。
直到版本v4.6的avr工具链发行版都存在libgcc和avr-libc都提供float实现的问题。尽管avr-libc实现效率更高,但它假定浮点仿真函数位于一起,因此RCALL
/ RCALL
甚至在闪存大小更大的设备上也可以达到其他浮点函数。 大于8 KiB。但是,无法保证此类浮点函数的位置彼此靠近,因此avr-libc将wrong assumptions设置为可能导致RJMP
/ RCALL
无法达到其目标的情况(已编码作为重定位R_AVR_13_PCREL
)。
通过从libgcc链接效率低下的浮点代码,使问题变得更糟(实际上并不需要,因为avr-libc也提供了此类功能)。在v4.7.2中已解决此问题:此后从libgcc中排除了相应的功能,并且-lm
被自动 添加到链接器选项中,请参见PR54461。您可以在进行编译和链接时看到此信息,例如avr-gcc simple.c -Wl,-v -mmcu=atmega8
。 avr-gcc传递给链接器的选项为:
<path>/ld ... --start-group -lgcc -lm -lc -latmega8 --end-group
这意味着-lm
已经在正确的位置,您可以从libm和libc引用libgcc函数,反之亦然。
您的libgcc是否带有应该由avr-libc提供的float函数,可以通过以下命令进行检测:
avr-objdump -d <INSTALL>/lib/gcc/avr/<VERSION>/libgcc.a | grep __addsf3
如果未找到__addsf3
,则一切正常。如果找到 ,您可能会{@ {1}}摆弄。 -lm
是工具链分发的位置,<INSTALL>
是您的GCC版本。
<VERSION>
在v8 +中不是优化选项-mshort-calls
的 Recommendation已过时。今天,-mshort-calls
不是优化选项,请参见v8 release notes:
•支持新的命令行选项
-mshort-calls
。此选项在内部用于avrxmega3变体的multilib选择。这不是优化选项。请勿手动设置。
其效果是代码大小较小,这降低了重新定位截断以适应问题的可能性。可以通过-mshort-calls
来达到预期的效果,或者,如果您的版本尚不支持,则可以使用-mrelax
。