I’m currently trying to recreate the blinky example using low-level C++ using vscode for the STM32F446RE Nucleo-64 board. I took the linkerscript and startup code from dwelch67’s stm32 sample code and modified it to fit my needs. Shown below are the linkerscript, startup code, and makefile:
Linkerscript:
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 512K
ram : ORIGIN = 0x20000000, LENGTH = 128K
}
SECTIONS
{
.text : {
*(.text*)
*(.rodata*)
} > rom
.data : {
_data = .;
*(.data*)
*(.ramtext*)
} > rom
.bss : {
*(.bss*)
} > ram
}
Startup.s:
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
.word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.thumb_func
reset:
bl notmain
b hang
.thumb_func
hang: b .
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.thumb_func
.globl GET32
GET32:
ldr r0,[r0]
bx lr
Makefile:
{ifneq ($(V),1)
Q := @
NULL := 2>/dev/null
endif
#####################################################################################
# Executables
PREFIX ?= arm-none-eabi-
CC := $(PREFIX)gcc
CXX := $(PREFIX)g++
LD := $(PREFIX)gcc
AR := $(PREFIX)ar
AS := $(PREFIX)as
OBJCOPY := $(PREFIX)objcopy
OBJDUMP := $(PREFIX)objdump
GDB := $(PREFIX)gdb
STFLASH = $(shell which st-flash)
OPT := -Os
DEBUG := -ggdb3
CSTD ?= -std=c99
#####################################################################################
# C flags
TGT_CFLAGS += $(OPT) $(CSTD) $(DEBUG)
TGT_CFLAGS += $(ARCH_FLAGS)
TGT_CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration
TGT_CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
TGT_CFLAGS += -fno-common -ffunction-sections -fdata-sections
###############################################################################
# C++ flags
TGT_CXXFLAGS += $(OPT) $(CXXSTD) $(DEBUG)
TGT_CXXFLAGS += $(ARCH_FLAGS)
TGT_CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++
TGT_CXXFLAGS += -fno-common -ffunction-sections -fdata-sections
###############################################################################
# C & C++ preprocessor common flags
TGT_CPPFLAGS += -MD
TGT_CPPFLAGS += -Wall -Wundef
TGT_CPPFLAGS += $(DEFS)
###############################################################################
# Linker flags
TGT_LDFLAGS += --static -nostartfiles
TGT_LDFLAGS += -T$(LDSCRIPT)
TGT_LDFLAGS += $(ARCH_FLAGS) $(DEBUG)
TGT_LDFLAGS += -Wl,-Map=$(*).map -Wl,--cref
TGT_LDFLAGS += -Wl,--gc-sections
ifeq ($(V),99)
TGT_LDFLAGS += -Wl,--print-gc-sections
endif
###############################################################################
# Directories, Linkerscript, Object files, Includes
SRC_DIR = ./src
INC_DIR = ./inc
START_DIR =./startup
LDSCRIPT = linkerscript.ld
AFILES += startup.S
OBJS += $(SRC_DIR)/$(BINARY).o
OBJS += $(START_DIR)/$(AFILES:%.S=%.o)
DEFS += -I$(INC_DIR)
BINARY = firmware
# Used libraries
LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
#####################################################################################
all: elf bin
elf: $(BINARY).elf
bin: $(BINARY).bin
hex: $(BINARY).hex
srec: $(BINARY).srec
list: $(BINARY).list
GENERATED_BINARIES=$(BINARY).elf $(BINARY).bin $(BINARY).hex $(BINARY).srec $(BINARY).list $(BINARY).map
images: $(BINARY).images
flash: $(BINARY).flash
print-%:
@echo $*=$($*)
%.images: %.bin %.hex %.srec %.list %.map
@#printf "*** $* images generated ***n"
%.bin: %.elf
@#printf " OBJCOPY $(*).binn"
$(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin
%.hex: %.elf
@#printf " OBJCOPY $(*).hexn"
$(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex
%.srec: %.elf
@#printf " OBJCOPY $(*).srecn"
$(Q)$(OBJCOPY) -Osrec $(*).elf $(*).srec
%.list: %.elf
@#printf " OBJDUMP $(*).listn"
$(Q)$(OBJDUMP) -S $(*).elf > $(*).list
%.elf %.map: $(OBJS)
@#printf " LD $(*).elfn"
$(Q)$(LD) $(TGT_LDFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(*).elf
%.o: %.c
@#printf " CC $(*).cn"
$(Q)$(CC) $(TGT_CFLAGS) $(CFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).c
%.o: %.S
@#printf " CC $(*).Sn"
$(Q)$(CC) $(TGT_CFLAGS) $(CFLAGS) -o $(*).o -c $(*).S
%.o: %.cxx
@#printf " CXX $(*).cxxn"
$(Q)$(CXX) $(TGT_CXXFLAGS) $(CXXFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).cxx
%.o: %.cpp
@#printf " CXX $(*).cppn"
$(Q)$(CXX) $(TGT_CXXFLAGS) $(CXXFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).cpp
clean:
@#printf " CLEANn"
$(Q)$(RM) $(GENERATED_BINARIES) generated.* $(OBJS) $(OBJS:%.o=%.d)
When I try to build the project using arm-none-eabi, I get the following error:
C:arm-none-eabibinarm-none-eabi-objcopy.exe: error: the input file 'firmware.elf' has no sections
I tried using the STM32CubeMX to generate a makefile project from which I took the startup and linkerscript files, but that method forced me to add a bunch of other files that I didn’t know where to locate. Greatly appreaciate the help!