Search code examples
c++makefileldstm32stm32f4discovery

set up linker for stm32f4 discovery and g++


I am trying compile some code that uses USART and std functions from such as printf() for the stm32f4 discovery. First I compile all code files into a object file using g++ but when I use the linker to create the executable the linker throws errors describing that it can't find any functions implemented in the startup_stm32f4xx.s assembly file.

Could I have a Makefile template form that compiles all source into object files then links it into a *.elf executable?

Also how would I set up the linker to see newlib_stubs.c so I can use printf() in my source code?


Solution

  • This is a generic Makefile for your proyect (compilation tested, but not tested if it will run on MCU)

    This script can handle C/C++ and S (gas asm) files. So no need to use C-startup file from coocox

    # 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)
    

    The core reference for make is in the official manual: http://www.gnu.org/software/make/manual/make.html but you need some hacking time to understand it ;-)

    Suggestion, put syscalls code into separate C/C++ file called syscall.c/cpp or something like that.