将两个 C++ 文件添加到 ARM MCU 项目时,.ELF 太大
Posted
技术标签:
【中文标题】将两个 C++ 文件添加到 ARM MCU 项目时,.ELF 太大【英文标题】:.ELF too big when adding two C++ files to ARM MCU project 【发布时间】:2015-02-24 19:48:47 【问题描述】:我正在尝试为 Atmel SAM3S1 微控制器编写一些 C++ 代码。我正在使用包含 FreeRTOS 库的 ASF 库。我编写了一个简单而小型的 C++ 包装器(3 个 .cpp 文件),因此我可以轻松地在我的设备类中继承它。
Atmel SAM (datasheet) 有 64KB 闪存和 16KB RAM,我认为这已经足够了。虽然当我开始编译时,我得到了消息:
section `.text' will not fit in region `rom'
/usr/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/bin/ld: region `rom' overflowed by 13120 bytes
我使用 arm-none-eabi-g++ 编译和链接所有内容。
当我清除 Main.cpp 中声明的 Class 时,大小很好,所以我认为这与 C++ 有关。有人可以向我解释我在这里做错了什么吗?
Test.elf :
section size addr
.text 0x102c 0x400000
.ARM.exidx 0x8 0x40102c
.relocate 0x844 0x20000000
.bss 0x154 0x20000844
.stack 0x2000 0x20000998
.ARM.attributes 0x29 0x0
.comment 0x70 0x0
.debug_info 0x57d1 0x0
.debug_abbrev 0x1058 0x0
.debug_aranges 0x430 0x0
.debug_ranges 0xb00 0x0
.debug_macro 0xf50a 0x0
.debug_line 0x5024 0x0
.debug_str 0x46ec7 0x0
.debug_frame 0xe04 0x0
.debug_loc 0x31f1 0x0
Total 0x6a5a8
text data bss dec hex filename
0x1034 0x844 0x2154 14796 39cc Test.elf
这些是我的 CPP 文件:
Main.cpp
#include <asf.h>
#include <MMA8652.h>
extern "C"
extern void vApplication***Hook(xTaskHandle *pxTask,
signed char *pcTaskName)
int main(void)
const taskConfig_t AccelTaskConfig = "AccelRx", 3, 100 ;
MMA8652 Accelero(AccelTaskConfig);
return(0);
任务.h
//#ifndef TASK_H
//#define TASK_H
#include <inttypes.h>
typedef struct
char *taskName;
uint8_t priority;
uint16_t stackSize;
taskConfig_t;
class Task
private:
public:
Task(char *taskName, uint8_t priority, uint16_t stackSize);
~Task();
friend void run_helper(void *arg)
return static_cast<Task*>(arg)->run();
virtual void run(void) const = 0;
protected:
;
//#endif
任务.cpp
#include <Task.h>
#include <asf.h>
void run_helper(void *arg);
Task::Task( char *taskName,
uint8_t priority,
uint16_t stackSize )
// check for minimal stacksize
if(stackSize < configMINIMAL_STACK_SIZE)
stackSize = configMINIMAL_STACK_SIZE;
// check priority val
if(priority > configMAX_PRIORITIES)
priority = configMAX_PRIORITIES;
// create a new FreeRTOS task with func ptr to run() member
xTaskCreate( &run_helper, (const signed char *) taskName,
stackSize, (Task*)this, priority, NULL);
MMA8652.h
#ifndef MMA8652_H
#define MMA8652_H
#include <Task.h>
class MMA8652: public Task
private:
public:
void run(void) const;
MMA8652(const taskConfig_t &tConfig);
~MMA8652(void);
;
#endif // MMA8652_H
MMA8652.cpp
#include <asf.h>
#include <MMA8652.h>
MMA8652::MMA8652(const taskConfig_t &tConfig) :
Task(tConfig.taskName, tConfig.priority, tConfig.stackSize)
void MMA8652::run(void) const
pio_set_pin_high(TESTLED_GPIO);
vTaskDelay(1000);
pio_set_pin_low(TESTLED_GPIO);
vTaskDelay(1000);
linker_script.ld
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00010000 /* Flash, 64K */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 /* sram, 16K */
/* The stack size used by the application. NOTE: you need to adjust */
__stack_size__ = DEFINED(__stack_size__) ? __stack_size__ : 0x2000;
__ram_end__ = ORIGIN(ram) + LENGTH(ram) - 4;
/* Section Definitions */
SECTIONS
.text :
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
> rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
> rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
> ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
> ram
/* stack section */
.stack (NOLOAD):
. = ALIGN(8);
_sstack = .;
. = . + __stack_size__;
. = ALIGN(8);
_estack = .;
> ram
. = ALIGN(4);
_end = . ;
config.mk
# Path to top level ASF directory relative to this project directory.
PRJ_PATH = ASF
# Target CPU architecture: cortex-m3, cortex-m4
ARCH = cortex-m3
# Target part: none, sam3n4 or sam4l4aa
PART = sam3s1ab
# Application target name. Given with suffix .a for library and .elf for a
# standalone application.
TARGET_FLASH = $(PRJ_NAME).elf
TARGET_SRAM = $(PRJ_NAME).elf
# List of C source files.
CSRCS = \
Main.cpp \
lib/Task.cpp \
devices/MMA8652.cpp \
sam/boards/Board/init.c \
common/services/clock/sam3s/sysclk.c \
common/utils/interrupt/interrupt_sam_nvic.c \
common/utils/stdio/read.c \
common/utils/stdio/write.c \
sam/drivers/pio/pio.c \
sam/drivers/pio/pio_handler.c \
sam/drivers/pmc/pmc.c \
sam/drivers/pmc/sleep.c \
sam/utils/cmsis/sam3s/source/templates/exceptions.c \
sam/utils/cmsis/sam3s/source/templates/gcc/startup_sam3s.c \
sam/utils/cmsis/sam3s/source/templates/system_sam3s.c \
sam/utils/syscalls/gcc/syscalls.c \
thirdparty/freertos/freertos-7.0.0/source/croutine.c \
thirdparty/freertos/freertos-7.0.0/source/list.c \
thirdparty/freertos/freertos-7.0.0/source/portable/gcc/sam/port.c \
thirdparty/freertos/freertos-7.0.0/source/portable/memmang/heap_3.c \
thirdparty/freertos/freertos-7.0.0/source/queue.c \
thirdparty/freertos/freertos-7.0.0/source/tasks.c \
thirdparty/freertos/freertos-7.0.0/source/timers.c
# List of assembler source files.
As-s-rCS =
# List of include paths.
INC_PATH = \
../lib/include \
../devices/include \
../config \
../ \
common/services/clock \
common/boards \
common/services/gpio \
common/services/ioport \
common/utils \
sam/drivers/pio \
sam/drivers/pmc \
sam/utils \
sam/utils/cmsis/sam3s/include \
sam/utils/cmsis/sam3s/source/templates \
sam/utils/header_files \
sam/utils/preprocessor \
thirdparty/CMSIS/Include \
thirdparty/CMSIS/Lib/GCC \
thirdparty/freertos/freertos-7.0.0/source/include \
thirdparty/freertos/freertos-7.0.0/source/portable/gcc/sam \
# Additional search paths for libraries.
LIB_PATH = \
thirdparty/CMSIS/Lib/GCC
# List of libraries to use during linking.
LIBS =
# Path relative to top level directory pointing to a linker script.
LINKER_SCRIPT_FLASH = sam/utils/linker_scripts/sam3s/sam3s1/gcc/flash.ld
LINKER_SCRIPT_SRAM = sam/utils/linker_scripts/sam3s/sam3s1/gcc/sram.ld
# Project type parameter: all, sram or flash
PROJECT_TYPE = flash
# Additional options for debugging. By default the common Makefile.in will
# add -g3.
DBGFLAGS =
# Application optimization used during compilation and linking:
# -O0, -O1, -O2, -O3 or -Os
OPTIMIZATION = -O3
# Extra flags to use when archiving.
ARFLAGS =
# Extra flags to use when assembling.
ASFLAGS =
# Extra flags to use when compiling.
CFLAGS =
# Extra flags to use when preprocessing.
#
# Preprocessor symbol definitions
# To add a definition use the format "-D name[=definition]".
# To cancel a definition use the format "-U name".
#
# The most relevant symbols to define for the preprocessor are:
# BOARD Target board in use, see boards/board.h for a list.
# EXT_BOARD Optional extension board in use, see boards/board.h for a list.
CPPFLAGS = \
-D __FREERTOS__ \
-D __SAM3S1B__ \
-D BOARD=BOARD \
-D printf=iprintf \
-D scanf=iscanf
# Extra flags to use when linking
LDFLAGS = \
# Pre- and post-build commands
PREBUILD_CMD =
POSTBUILD_CMD =
Makefile.sam.in
include config.mk
# Tool to use to generate documentation from the source code
DOCGEN ?= doxygen
# Look for source files relative to the top-level source directory
VPATH := $(PRJ_PATH)
# Output target file
project_type := $(PROJECT_TYPE)
# Output target file
ifeq ($(project_type),flash)
target := $(TARGET_FLASH)
linker_script := $(PRJ_PATH)/$(LINKER_SCRIPT_FLASH)
debug_script := $(PRJ_PATH)/$(DEBUG_SCRIPT_FLASH)
else
target := $(TARGET_SRAM)
linker_script := $(PRJ_PATH)/$(LINKER_SCRIPT_SRAM)
debug_script := $(PRJ_PATH)/$(DEBUG_SCRIPT_SRAM)
endif
# Output project name (target name minus suffix)
project := $(basename $(target))
# Output target file (typically ELF or static library)
ifeq ($(suffix $(target)),.a)
target_type := lib
else
ifeq ($(suffix $(target)),.elf)
target_type := elf
else
$(error "Target type $(target_type) is not supported")
endif
endif
# Allow override of operating system detection. The user can add OS=Linux or
# OS=Windows on the command line to explicit set the host OS.
#
# This allows to work around broken uname utility on certain systems.
ifdef OS
ifeq ($(strip $(OS)), Linux)
os_type := Linux
endif
ifeq ($(strip $(OS)), Windows)
os_type := windows32_64
endif
endif
os_type ?= $(strip $(shell uname))
ifeq ($(os_type),windows32)
os := Windows
else
ifeq ($(os_type),windows64)
os := Windows
else
ifeq ($(os_type),windows32_64)
os ?= Windows
else
ifeq ($(os_type),)
os := Windows
else
# Default to Linux style operating system. Both Cygwin and mingw are fully
# compatible (for this Makefile) with Linux.
os := Linux
endif
endif
endif
endif
# Output documentation directory and configuration file.
docdir := ../doxygen/html
doccfg := ../doxygen/doxyfile.doxygen
CROSS ?= arm-none-eabi-
AR := $(CROSS)ar
AS := $(CROSS)as
CC := $(CROSS)gcc
CPP := $(CROSS)gcc -E
CXX := $(CROSS)g++
LD := $(CROSS)g++
NM := $(CROSS)nm
OBJCOPY := $(CROSS)objcopy
OBJDUMP := $(CROSS)objdump
SIZE := $(CROSS)size
GDB := $(CROSS)gdb
RM := rm
ifeq ($(os),Windows)
RMDIR := rmdir /S /Q
else
RMDIR := rmdir -p --ignore-fail-on-non-empty
endif
# On Windows, we need to override the shell to force the use of cmd.exe
ifeq ($(os),Windows)
SHELL := cmd
endif
# Strings for beautifying output
MSG_CLEAN_FILES = "RM *.o *.d"
MSG_CLEAN_DIRS = "RMDIR $(strip $(clean-dirs))"
MSG_CLEAN_DOC = "RMDIR $(docdir)"
MSG_MKDIR = "MKDIR $(dir $@)"
MSG_INFO = "INFO "
MSG_PREBUILD = "PREBUILD $(PREBUILD_CMD)"
MSG_POSTBUILD = "POSTBUILD $(POSTBUILD_CMD)"
MSG_ARCHIVING = "AR $@"
MSG_ASSEMBLING = "AS $@"
MSG_BINARY_IMAGE = "OBJCOPY $@"
MSG_COMPILING = "CC $@"
MSG_COMPILING_CXX = "CXX $@"
MSG_EXTENDED_LISTING = "OBJDUMP $@"
MSG_IHEX_IMAGE = "OBJCOPY $@"
MSG_LINKING = "LN $@"
MSG_PREPROCESSING = "CPP $@"
MSG_SIZE = "SIZE $@"
MSG_SYMBOL_TABLE = "NM $@"
MSG_GENERATING_DOC = "DOXYGEN $(docdir)"
# Don't use make's built-in rules and variables
MAKEFLAGS += -rR
# Don't print 'Entering directory ...'
MAKEFLAGS += --no-print-directory
# Function for reversing the order of a list
reverse = $(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
# Hide command output by default, but allow the user to override this
# by adding V=1 on the command line.
#
# This is inspired by the Kbuild system used by the Linux kernel.
ifdef V
ifeq ("$(origin V)", "command line")
VERBOSE = $(V)
endif
endif
ifndef VERBOSE
VERBOSE = 0
endif
ifeq ($(VERBOSE), 1)
Q =
else
Q = @
endif
arflags-gnu-y := $(ARFLAGS)
asflags-gnu-y := $(ASFLAGS)
cflags-gnu-y := $(CFLAGS)
cxxflags-gnu-y := $(CXXFLAGS)
cppflags-gnu-y := $(CPPFLAGS)
cpuflags-gnu-y :=
dbgflags-gnu-y := $(DBGFLAGS)
libflags-gnu-y := $(foreach LIB,$(LIBS),-l$(LIB))
ldflags-gnu-y := $(LDFLAGS)
flashflags-gnu-y :=
clean-files :=
clean-dirs :=
clean-files += $(wildcard $(target) $(project).map)
clean-files += $(wildcard $(project).hex $(project).bin)
clean-files += $(wildcard $(project).lss $(project).sym)
clean-files += $(wildcard $(build))
# Use pipes instead of temporary files for communication between processes
cflags-gnu-y += -pipe
asflags-gnu-y += -pipe
ldflags-gnu-y += -pipe
# Archiver flags.
arflags-gnu-y += rcs
# Always enable warnings. And be very careful about implicit
# declarations.
cflags-gnu-y += -Wall -Wstrict-prototypes -Wmissing-prototypes
cflags-gnu-y += -Werror-implicit-function-declaration
cxxflags-gnu-y += -Wall
# IAR doesn't allow arithmetic on void pointers, so warn about that.
cflags-gnu-y += -Wpointer-arith
cxxflags-gnu-y += -Wpointer-arith
# Preprocessor flags.
cppflags-gnu-y += $(foreach INC,$(addprefix $(PRJ_PATH)/,$(INC_PATH)),-I$(INC))
asflags-gnu-y += $(foreach INC,$(addprefix $(PRJ_PATH)/,$(INC_PATH)),'-Wa,-I$(INC)')
# CPU specific flags.
cpuflags-gnu-y += -mcpu=$(ARCH) -mthumb -D=__$(PART)__
# Dependency file flags.
depflags = -MD -MP -MQ $@
# Debug specific flags.
ifdef BUILD_DEBUG_LEVEL
dbgflags-gnu-y += -g$(BUILD_DEBUG_LEVEL)
else
dbgflags-gnu-y += -g3
endif
# Optimization specific flags.
ifdef BUILD_OPTIMIZATION
optflags-gnu-y = -O$(BUILD_OPTIMIZATION)
else
optflags-gnu-y = $(OPTIMIZATION)
endif
# Always preprocess assembler files.
asflags-gnu-y += -x assembler-with-cpp
# Compile C files using the GNU99 standard.
cflags-gnu-y += -std=gnu99
# Compile C++ files using the GNU++98 standard.
cxxflags-gnu-y += -std=gnu++98
# Don't use strict aliasing (very common in embedded applications).
cflags-gnu-y += -fno-strict-aliasing
cxxflags-gnu-y += -fno-strict-aliasing
# Separate each function and data into its own separate section to allow
# garbage collection of unused sections.
cflags-gnu-y += -ffunction-sections -fdata-sections
cxxflags-gnu-y += -ffunction-sections -fdata-sections
# Various cflags.
cflags-gnu-y += -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int
cflags-gnu-y += -Wmain -Wparentheses
cflags-gnu-y += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused
cflags-gnu-y += -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef
cflags-gnu-y += -Wshadow -Wbad-function-cast -Wwrite-strings
cflags-gnu-y += -Wsign-compare -Waggregate-return
cflags-gnu-y += -Wmissing-declarations
cflags-gnu-y += -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations
cflags-gnu-y += -Wpacked -Wredundant-decls -Wnested-externs -Winline -Wlong-long
cflags-gnu-y += -Wunreachable-code
cflags-gnu-y += -Wcast-align
cflags-gnu-y += --param max-inline-insns-single=500
# Garbage collect unreferred sections when linking.
ldflags-gnu-y += -Wl,--gc-sections
# Use the linker script if provided by the project.
ifneq ($(strip $(linker_script)),)
ldflags-gnu-y += -Wl,-T $(linker_script)
endif
# Output a link map file and a cross reference table
ldflags-gnu-y += -Wl,-Map=$(project).map,--cref
# Add library search paths relative to the top level directory.
ldflags-gnu-y += $(foreach _LIB_PATH,$(addprefix $(PRJ_PATH)/,$(LIB_PATH)),-L$(_LIB_PATH))
a_flags = $(cpuflags-gnu-y) $(depflags) $(cppflags-gnu-y) $(asflags-gnu-y) -D__ASSEMBLY__
c_flags = $(cpuflags-gnu-y) $(dbgflags-gnu-y) $(depflags) $(optflags-gnu-y) $(cppflags-gnu-y) $(cflags-gnu-y)
cxx_flags= $(cpuflags-gnu-y) $(dbgflags-gnu-y) $(depflags) $(optflags-gnu-y) $(cppflags-gnu-y) $(cxxflags-gnu-y)
l_flags = -Wl,--entry=Reset_Handler -Wl,--cref $(cpuflags-gnu-y) $(optflags-gnu-y) $(ldflags-gnu-y)
ar_flags = $(arflags-gnu-y)
# Source files list and part informations must already be included before
# running this makefile
# If a custom build directory is specified, use it -- force trailing / in directory name.
ifdef BUILD_DIR
build-dir := $(dir $(BUILD_DIR))$(if $(notdir $(BUILD_DIR)),$(notdir $(BUILD_DIR))/)
else
build-dir =
endif
# Create object files list from source files list.
obj-y := $(addprefix $(build-dir), $(addsuffix .o,$(basename $(CSRCS) $(As-s-rCS))))
# Create dependency files list from source files list.
dep-files := $(wildcard $(foreach f,$(obj-y),$(basename $(f)).d))
clean-files += $(wildcard $(obj-y))
clean-files += $(dep-files)
clean-dirs += $(call reverse,$(sort $(wildcard $(dir $(obj-y)))))
# Default target.
.PHONY: all
ifeq ($(project_type),all)
all:
$(MAKE) all PROJECT_TYPE=flash
$(MAKE) all PROJECT_TYPE=sram
else
ifeq ($(target_type),lib)
all: $(target) $(project).lss $(project).sym
else
ifeq ($(target_type),elf)
all: prebuild $(target) $(project).lss $(project).sym $(project).hex $(project).bin postbuild
endif
endif
endif
prebuild:
ifneq ($(strip $(PREBUILD_CMD)),)
@echo $(MSG_PREBUILD)
$(Q)$(PREBUILD_CMD)
endif
postbuild:
ifneq ($(strip $(POSTBUILD_CMD)),)
@echo $(MSG_POSTBUILD)
$(Q)$(POSTBUILD_CMD)
endif
# Clean up the project.
.PHONY: clean
clean:
@$(if $(strip $(clean-files)),echo $(MSG_CLEAN_FILES))
$(if $(strip $(clean-files)),$(Q)$(RM) $(clean-files),)
@$(if $(strip $(clean-dirs)),echo $(MSG_CLEAN_DIRS))
# Remove created directories, and make sure we only remove existing
# directories, since recursive rmdir might help us a bit on the way.
ifeq ($(os),Windows)
$(Q)$(if $(strip $(clean-dirs)), \
$(RMDIR) $(strip $(subst /,\,$(clean-dirs))))
else
$(Q)$(if $(strip $(clean-dirs)), \
for directory in $(strip $(clean-dirs)); do \
if [ -d "$$directory" ]; then \
$(RMDIR) $$directory; \
fi \
done \
)
endif
# Rebuild the project.
.PHONY: rebuild
rebuild: clean all
# Debug the project in flash.
.PHONY: debug_flash
debug_flash: all
$(GDB) -x "$(PRJ_PATH)/$(DEBUG_SCRIPT_FLASH)" -ex "reset" -readnow -se $(TARGET_FLASH)
# Debug the project in sram.
.PHONY: debug_sram
debug_sram: all
$(GDB) -x "$(PRJ_PATH)/$(DEBUG_SCRIPT_SRAM)" -ex "reset" -readnow -se $(TARGET_SRAM)
.PHONY: objfiles
objfiles: $(obj-y)
# Create object files from C source files.
$(build-dir)%.o: %.c $(MAKEFILE_PATH) config.mk
$(Q)test -d $(dir $@) || echo $(MSG_MKDIR)
ifeq ($(os),Windows)
$(Q)test -d $(patsubst %/,%,$(dir $@)) || mkdir $(subst /,\,$(dir $@))
else
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
endif
@echo $(MSG_COMPILING)
$(Q)$(CC) $(c_flags) -c $< -o $@
# Create object files from C++ source files.
$(build-dir)%.o: %.cpp $(MAKEFILE_PATH) config.mk
$(Q)test -d $(dir $@) || echo $(MSG_MKDIR)
ifeq ($(os),Windows)
$(Q)test -d $(patsubst %/,%,$(dir $@)) || mkdir $(subst /,\,$(dir $@))
else
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
endif
@echo $(MSG_COMPILING_CXX)
$(Q)$(CXX) $(cxx_flags) -c $< -o $@
# Preprocess and assemble: create object files from assembler source files.
$(build-dir)%.o: %.S $(MAKEFILE_PATH) config.mk
$(Q)test -d $(dir $@) || echo $(MSG_MKDIR)
ifeq ($(os),Windows)
$(Q)test -d $(patsubst %/,%,$(dir $@)) || mkdir $(subst /,\,$(dir $@))
else
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
endif
@echo $(MSG_ASSEMBLING)
$(Q)$(CC) $(a_flags) -c $< -o $@
# Include all dependency files to add depedency to all header files in use.
include $(dep-files)
ifeq ($(target_type),lib)
# Archive object files into an archive
$(target): $(MAKEFILE_PATH) config.mk $(obj-y)
@echo $(MSG_ARCHIVING)
$(Q)$(AR) $(ar_flags) $@ $(obj-y)
@echo $(MSG_SIZE)
$(Q)$(SIZE) -Bxt $@
else
ifeq ($(target_type),elf)
# Link the object files into an ELF file. Also make sure the target is rebuilt
# if the common Makefile.sam.in or project config.mk is changed.
$(target): $(linker_script) $(MAKEFILE_PATH) config.mk $(obj-y)
@echo $(MSG_LINKING)
$(Q)$(LD) $(l_flags) $(obj-y) $(libflags-gnu-y) -o $@
@echo $(MSG_SIZE)
$(Q)$(SIZE) -Ax $@
$(Q)$(SIZE) -Bx $@
endif
endif
# Create extended function listing from target output file.
%.lss: $(target)
@echo $(MSG_EXTENDED_LISTING)
$(Q)$(OBJDUMP) -h -S $< > $@
# Create symbol table from target output file.
%.sym: $(target)
@echo $(MSG_SYMBOL_TABLE)
$(Q)$(NM) -n $< > $@
# Create Intel HEX image from ELF output file.
%.hex: $(target)
@echo $(MSG_IHEX_IMAGE)
$(Q)$(OBJCOPY) -O ihex $(flashflags-gnu-y) $< $@
# Create binary image from ELF output file.
%.bin: $(target)
@echo $(MSG_BINARY_IMAGE)
$(Q)$(OBJCOPY) -O binary $< $@
# Provide information about the detected host operating system.
.SECONDARY: info-os
info-os:
@echo $(MSG_INFO)$(os) build host detected
# Build Doxygen generated documentation.
.PHONY: doc
doc:
@echo $(MSG_GENERATING_DOC)
$(Q)cd $(dir $(doccfg)) && $(DOCGEN) $(notdir $(doccfg))
# Clean Doxygen generated documentation.
.PHONY: cleandoc
cleandoc:
@$(if $(wildcard $(docdir)),echo $(MSG_CLEAN_DOC))
$(Q)$(if $(wildcard $(docdir)),$(RM) --recursive $(docdir))
# Rebuild the Doxygen generated documentation.
.PHONY: rebuilddoc
rebuilddoc: cleandoc doc
【问题讨论】:
您的编译器和链接器命令是什么样的? (即您使用的是哪些编译器/链接器标志? MMA8652.cpp 与 Task.h 相同,Task.cpp 与 Main.cpp 相同。请正确。顺便说一句,我认为您必须使用未注释的 c++ 发布列表文件。如果你使用 c++,其他一些代码会被放入 .text 部分。 @Verax 我已经添加了我的 config.mk 和 Makefile。您可以在 Makefile.sam.in 中找到标志 您是否真的通过拖入 C++ 运行时支持获得了任何您无法在任务结构中使用函数指针/字段的东西? 【参考方案1】:根据我的计算,您的.text
段大约是 4k。
许多嵌入式系统的链接器应用程序都有一个命令或配置文件。配置文件告诉段的起始地址和大小。
您需要找到配置文件并验证 ROM 部分的地址是否正确且容量是否正确。
【讨论】:
你是怎么计算出来的?我已将链接器脚本 (.ld) 添加到由 atmel 创建的主题帖子中,所以我怀疑这是问题所在。我检查了数据表(第 31 页),flash 和 rom 的起始地址都是正确的 @ReinierHasper :嗯,他真的没有计算出来 - 他在你的问题中读到了 .text size = 0x102c。您可能没有明确表示“空”代码的大小?【参考方案2】:尝试在OPTIMIZATION
中使用-Os
而不是-O3
config.mk
中的标志;您也可以在编译和链接时使用-flto -Os
(用于链接时优化)
【讨论】:
好吧,我会试试的。我找到了这个link。他们说不要链接异常库很重要,因为它可能需要大约 50kb。我已将标志添加到 cxx 标志中,但不幸的是我没有看到任何结果 我注意到当我清空我的 Main.cpp 时一切都很好。但是当我使用 new 运算符时它出错了,大小是 15k 到大new
本身不应太大,但只有 16kb 或 RAM,无论如何最好避免动态内存分配。但是,由于您的示例代码不使用new
,因此任何人都很难确定这是一个问题。【参考方案3】:
我终于修好了!我添加了 fno-rtti 和 fno-exceptions 并重载了 new、delete 和 destructor 运算符。 http://www.embedded.com/design/mcus-processors-and-socs/4007134/Building-Bare-Metal-ARM-Systems-with-GNU-Part-4.
不幸的是,我无法重载 Task.h->action_helper() 中使用的 static_cast 运算符。有谁知道如何解决这个问题?
【讨论】:
static_cast
问题是一个完全不同的问题,您应该这样发布它 - 这不是一个讨论论坛。尽管reinterpret_cast
的开销为零,但它几乎没有开销。您可以将 arg 设为 Task*
并在 xTaskCreate
调用中转换为适当的函数指针类型。我并不完全清楚让Task::run_helper()
成为自己班级的朋友是什么;它已经可以访问自己的成员。【参考方案4】:
一般:
fno-exceptions 是一个很好的开始方式,如果您不使用它。 RTTI 也可以关闭,但我认为值得保留。这是一个非常强大的功能,而且成本最低。 不需要重载新/删除。如果您从不使用它并禁用异常,则可以通过 LTO 对其进行优化。只有动态分配时才需要担心。 重载 static_cast?它是“静态的”,因为它是编译时间。没有理由超载它,我不确定这是否可能。 尝试更改调试信息生成设置(gcc 中的 -g 标志) 尽可能优化大小。这让调试变得非常困难。不要忘记您所有的 ASF 源代码都是 C,因此设置 C 工具链也是必要的。
【讨论】:
以上是关于将两个 C++ 文件添加到 ARM MCU 项目时,.ELF 太大的主要内容,如果未能解决你的问题,请参考以下文章
ARM Cortex-M3 MCU的I2C&DMA操作被频繁的中断打挂了