【问题标题】:set up linker for stm32f4 discovery and g++为 stm32f4 发现和 g++ 设置链接器
【发布时间】:2014-01-14 16:52:27
【问题描述】:

我正在尝试编译一些使用 USART 和 std 函数的代码,例如 printf() 用于 stm32f4 发现。首先,我使用 g++ 将所有代码文件编译成一个目标文件,但是当我使用链接器创建可执行文件时,链接器会抛出错误,描述它找不到在 startup_stm32f4xx.s 汇编文件中实现的任何函数。

我能否有一个 Makefile 模板表单,将所有源代码编译成目标文件,然后将其链接到 *.elf 可执行文件中?

另外,我将如何设置链接器以查看 newlib_stubs.c 以便我可以在源代码中使用 printf()?

【问题讨论】:

  • 这里是一个我无法编译的示例 makefile 项目的链接:link

标签: c++ makefile ld stm32 stm32f4discovery


【解决方案1】:

这是您项目的通用 Makefile(经过编译测试,但未测试是否可以在 MCU 上运行)

此脚本可以处理 C/C++ 和 S (gas asm) 文件。所以不需要使用 coocox 的 C-startup 文件

# ELF target name
TARGET=testmode09.elf

# C source files
SRC=src/system_stm32f4xx.c

# C++ source files
CXXSRC=src/main.cpp

# ASM source files
ASRC=lib/startup_stm32f4xx.s

# include directories
INCDIRS=inc lib/inc lib/inc/core lib/inc/peripherals

# search path for .so and .a
LIBDIRS=lib

# libraries to link
LIBS=libstm32f4.a

# Linker script
LDSCRIPT=stm32_flash.ld

# Tool configuration
CROSS=arm-none-eabi-
CC=$(CROSS)gcc
CXX=$(CROSS)g++
AS=$(CROSS)gcc
LD=$(CROSS)gcc
OBJCOPY=$(CROSS)objcopy

# Architecture configuration
ARCH_FLAGS=-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 

# Flags for gcc
CFLAGS+=-O0 -ggdb3
CFLAGS+=$(ARCH_FLAGS)
CFLAGS+=-flto
CFLAGS+=-ffunction-sections
CFLAGS+=-fdata-sections
CFLAGS+=$(foreach i, $(INCDIRS), -I$(i))

# Flags for g++
CXXFLAGS=$(CFLAGS)
CXXFLAGS+=-fno-rtti -fno-exceptions
CXXFLAGS+=-std=c++11

# Flags for gcc as linker
LDFLAGS=$(ARCH_FLAGS)
LDFLAGS+=-Wl,--gc-sections
LDFLAGS+=$(foreach i, $(LIBDIRS), -L$(i))
LDFLAGS+=-T $(LDSCRIPT)

# No man land! Enter at your risk

OBJS=$(SRC:.c=.o) $(ASRC:.s=.o) $(CXXSRC:.cpp=.o)
DEPS=$(OBJS:.o=.d)

# Default make target (first target)
all: $(TARGET) bins

# include dependency files (*.d)
-include $(DEPS)

# Rules to build c/cpp/s files
%.o: %.c
    @echo " CC $<"
    @$(CC) -MMD $(CFLAGS) -o $@ -c $<

%.o: %.cpp
    @echo " CXX $<"
    @$(CXX) -MMD $(CXXFLAGS) -o $@ -c $<

%.o: %.s
    @echo " AS $<"
    @$(AS) $(CFLAGS) -o $@ -c $<

# Linker rule
$(TARGET): libs $(OBJS)
    @echo " LINK $@"
    @$(LD) -o $@ $(LDFLAGS) $(OBJS)

# Phony rules (not file-asociated)
.PHONY: clean all libs clean_lib bins

libs:
    @$(MAKE) -C lib

clean_lib:
    @$(MAKE) -C lib clean

clean:
    @echo " CLEAN"
    @rm -fR $(OBJS) $(DEPS) $(TARGET) $(TARGET:.elf=hex) $(TARGET:.elf=.bin)

bins: $(TARGET)
    @echo " BUILD HEX & BIN"
    @$(OBJCOPY) -O ihex $(TARGET) $(TARGET:.elf=.hex)
    @$(OBJCOPY) -O binary $(TARGET) $(TARGET:.elf=.bin)

make的核心参考在官方手册中:http://www.gnu.org/software/make/manual/make.html 但是你需要一些破解时间来理解它;-)

建议,将系统调用代码放入名为 syscall.c/cpp 或类似文件的单独 C/C++ 文件中。

【讨论】:

  • 我已经更改了一些内容以适应您的 make 文件。更新的测试项目可以在以下位置下载:dl.dropboxusercontent.com/u/32204435/testmodel09.2.zip 我仍然收到诸如/usr/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/lib/armv7e-m/fpu/libc.a(lib_a-sbrkr.o): In function '_sbrk_r': sbrkr.c:(.text._sbrk_r+0xc): undefined reference to '_sbrk' for _sbrk、_write、_read、_close、_fstats、_isatty 和 _lseek 之类的错误。但是这个make文件已经接近实现目标了。那就是创建和编译目标文件。本地编译成功了吗?
  • 您好,看到问题了;-) 您将系统调用存根放入 .cpp 文件中,而没有 extern "C" 声明。在 C++ 函数中,链接器看到的名称类似于 pv_sbrkEui(void 的损坏名称 _sbrk(unsigned int))instread of _sbrk。将 extern "C" 添加到任何函数声明或 extern "C" { &lt;...file body...&gt; } 以解决它
  • 或者将你的文件 src/newlib_stubs.cpp 重命名为 src/newlib_stubs.c
  • @martinribelotta 这是关于 mangling 的有用信息。你是怎么知道的?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多