将两个 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 太大的主要内容,如果未能解决你的问题,请参考以下文章

Qt Creator 将文件添加到 C++ 项目问题

如何在arm keil中使用.a库文件

ARM Cortex-M 系列 MCU 错误追踪库 心得

ARM Cortex-M3 MCU的I2C&DMA操作被频繁的中断打挂了

将 Objective-C++ 文件添加到 C++ Xcode 5 项目

如何使用 Qt Creator 将 C++ 头文件添加到 Qt 项目