From 0d2ee72d25321a191a6e93501df5eab8336458a4 Mon Sep 17 00:00:00 2001 From: buha Date: Mon, 14 Dec 2020 09:42:51 +0200 Subject: [PATCH] stm32 (stm32f4) support in makefiles This adds the possibility to build a project for the STM32 microcontrollers using: make PLATFORM=stm32 The family is detected automatically from file names. The build/ directory is used only to store the .o, .elf and other build artifacts and, unlike for xilinx and intel projects, it is not used to store an SDK project. The reason behind this is that STM32CubeIDE does not support project creation from command line. Therefore the build is entirely maintained by us using our build system. A new rule was added specifically for this platform, which is: make PLATORM=stm32 debug This rule has as prerequisite that the shell PATH contains OPENOCD_BIN OPENOCD_SCRIPTS environment variables. If they are properly configured, the rule creates an .openocd and a .gdb config script, starts an openocd server and starts a gdb debug session with the .elf. Additionaly, like for other platforms, one can flash the chip and run execution by make PLATFORM=stm32 run Signed-off-by: Darius Berghe --- .gitmodules | 3 + tools/scripts/generic.mk | 62 +++++++++++-------- tools/scripts/generic_variables.mk | 7 ++- tools/scripts/stm32.mk | 95 ++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 26 deletions(-) create mode 100644 tools/scripts/stm32.mk diff --git a/.gitmodules b/.gitmodules index 43b38197885..6c57ce80026 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "libraries/iio/libtinyiiod"] path = libraries/iio/libtinyiiod url = https://github.com/analogdevicesinc/libtinyiiod +[submodule "libraries/STM32CubeF4"] + path = libraries/stm32/STM32CubeF4 + url = https://github.com/STMicroelectronics/STM32CubeF4.git diff --git a/tools/scripts/generic.mk b/tools/scripts/generic.mk index 10cf9f3239f..949619f5b6c 100644 --- a/tools/scripts/generic.mk +++ b/tools/scripts/generic.mk @@ -35,18 +35,16 @@ INCS := $(filter-out $(ALL_IGNORED_FILES),$(INCS)) #------------------------------------------------------------------------------ ifeq (aducm3029,$(strip $(PLATFORM))) -#Aducm3029 makefile -include $(NO-OS)/tools/scripts/aducm.mk - -else -#Xilnx and altera makefiles -ifeq ($(OS), Windows_NT) -include $(NO-OS)/tools/scripts/windows.mk + include $(NO-OS)/tools/scripts/aducm.mk +else ifeq (stm32,$(strip $(PLATFORM))) + include $(NO-OS)/tools/scripts/stm32.mk else -include $(NO-OS)/tools/scripts/linux.mk -endif #($(OS), Windows_NT) - -endif #(aducm3029,$(strip $(PLATFORM))) + ifeq ($(OS), Windows_NT) + include $(NO-OS)/tools/scripts/windows.mk + else + include $(NO-OS)/tools/scripts/linux.mk + endif +endif list: ifeq ($(OS), Windows_NT) @@ -153,11 +151,12 @@ INCLUDE ?= $(NO-OS)/include PLATFORM_DRIVERS ?= $(NO-OS)/drivers/platform/$(PLATFORM) #USED IN MAKEFILE -PROJECT_NAME = $(notdir $(PROJECT)) -BUILD_DIR ?= $(PROJECT)/build +PROJECT_NAME = $(notdir $(PROJECT)) +BUILD_DIR_NAME ?= build +BUILD_DIR ?= $(PROJECT)/$(BUILD_DIR_NAME) OBJECTS_DIR = $(BUILD_DIR)/objs WORKSPACE ?= $(BUILD_DIR) -PLATFORM_TOOLS = $(NO-OS)/tools/scripts/platform/$(PLATFORM) +PLATFORM_TOOLS = $(NO-OS)/tools/scripts/platform/$(PLATFORM) BINARY = $(BUILD_DIR)/$(PROJECT_NAME).elf ifneq ($(words $(NO-OS)), 1) @@ -195,6 +194,10 @@ endif include $(NO-OS)/tools/scripts/aducm.mk endif +ifeq 'stm32' '$(PLATFORM)' +include $(NO-OS)/tools/scripts/stm32.mk +endif + #------------------------------------------------------------------------------ # COMMON COMPILER FLAGS #------------------------------------------------------------------------------ @@ -250,7 +253,14 @@ REL_SRCS = $(addprefix $(OBJECTS_DIR)/,$(call get_relative_path,$(SRCS))) OBJS = $(REL_SRCS:.c=.o) REL_ASM_SRCS = $(addprefix $(OBJECTS_DIR)/,$(call get_relative_path,$(ASM_SRCS))) -ASM_OBJS = $(REL_ASM_SRCS:.S=.o) +ASM_OBJS_s = $(REL_ASM_SRCS:.s=.o) +ifneq ($(REL_ASM_SRCS),$(ASM_OBJS_s)) + ASM_OBJS += $(ASM_OBJS_s) +endif +ASM_OBJS_S = $(REL_ASM_SRCS:.S=.o) +ifneq ($(REL_ASM_SRCS),$(ASM_OBJS_S)) + ASM_OBJS += $(ASM_OBJS_S) +endif #Add to include all directories containing a .h file EXTRA_INC_PATHS += $(sort $(foreach dir, $(INCS),$(dir $(dir)))) @@ -273,18 +283,18 @@ PHONY += all # else the project will be build first. This will allow to run make with -j . ifneq ($(wildcard $(BUILD_DIR)),) all: print_build_type $(BINARY) - $(call print,Done ($(notdir $(BINARY)))) + $(call print,Done ($(BUILD_DIR_NAME)/$(notdir $(BINARY)))) else all: print_build_type #Remove -j flag for running project target. (It doesn't work on xilinx on this target) $(MUTE) $(MAKE) --no-print-directory project MAKEFLAGS=$(MAKEOVERRIDES) $(MUTE) $(MAKE) --no-print-directory $(BINARY) - $(call print,Done ($(notdir $(BINARY)))) + $(call print,Done ($(BUILD_DIR_NAME)/$(notdir $(BINARY)))) endif PHONY += print_build_type print_build_type: - $(call print,Building for $(call green,$(PLATFORM)) (using $(call green, $(HARDWARE)))) + $(call print,Building for $(call green,$(PLATFORM))) #This is used to keep directory targets between makefile executions #More details: http://ismail.badawi.io/blog/2017/03/28/automatic-directory-creation-in-make/ @@ -305,13 +315,17 @@ $(OBJECTS_DIR)/%.o: $$(call get_full_path, %).c | $$(@D)/. @$(call print,[CC] $(notdir $<)) $(MUTE) $(CC) -c $(CFLAGS) $< -o $@ -$(OBJECTS_DIR)/%.o: $$(call get_full_path, %).S | $$(@D)/. +$(OBJECTS_DIR)/%.o: $$(call get_full_path, %).s | $$(@D)/. + @$(call print,[AS] $(notdir $<)) + $(MUTE) $(AS) -c $(ASFLAGS) $< -o $@ + +$(OBJECTS_DIR)/%.o: $$(call get_full_path, %).S | $$(@D)/. @$(call print,[AS] $(notdir $<)) - $(MUTE) @$(AS) -c $(ASFLAGS) $< -o $@ + $(MUTE) $(AS) -c $(ASFLAGS) $< -o $@ $(BINARY): $(LIB_TARGETS) $(OBJS) $(ASM_OBJS) $(LSCRIPT) - @$(call print,[LD] $(notdir $(OBJS)) -o $(notdir $@)) - $(MUTE) @$(CC) -T$(LSCRIPT) $(LDFLAGS) $(LIB_PATHS) -o $(BINARY) $(OBJS) \ + @$(call print,[LD] $(notdir $(OBJS))) + $(MUTE) $(CC) -T$(LSCRIPT) $(LDFLAGS) $(LIB_PATHS) -o $(BINARY) $(OBJS) \ $(ASM_OBJS) $(LIB_FLAGS) PHONY += run @@ -332,7 +346,7 @@ endif # Build project using SDK project_build: $(PLATFORM)_project_build -# Remove project binaries +# Remove build artefacts PHONY += clean clean: $(call print,[Delete] $(notdir $(OBJS) $(BINARY) $(ASM_OBJS))) @@ -340,7 +354,7 @@ clean: -$(MUTE)$(call remove_fun,$(OBJS)) $(HIDE) -$(MUTE)$(call remove_fun,$(ASM_OBJS)) $(HIDE) -# Remove workspace data and project directory +# Remove the whole build directory PHONY += clean_all clean_all: clean_libs @$(call print,[Delete] $(BUILD_DIR)) diff --git a/tools/scripts/generic_variables.mk b/tools/scripts/generic_variables.mk index ca7e5a1b8ac..7870afc5c0f 100644 --- a/tools/scripts/generic_variables.mk +++ b/tools/scripts/generic_variables.mk @@ -3,11 +3,14 @@ # This variables will be set to their default value if not set by the user # It assumes that the makefile is invoked from No-OS/project/some_project -# User must set PLATFORM variable between: +# For these platforms, the user may optionally pass the PLATFORM variable: # PLATFORM = xilinx # PLATFORM = altera # PLATFORM = aducm3029 +# For these platforms, the user must set the PLATFORM variable: +# PLATFORM = stm32 + ifeq '$(LOCAL_BUILD)' 'y' include local_variables.mk @@ -52,4 +55,4 @@ endif endif endif -endif \ No newline at end of file +endif diff --git a/tools/scripts/stm32.mk b/tools/scripts/stm32.mk new file mode 100644 index 00000000000..df666a39bfa --- /dev/null +++ b/tools/scripts/stm32.mk @@ -0,0 +1,95 @@ +CFLAGS += -std=gnu11 \ + -g3 \ + -DUSE_HAL_DRIVER \ + -DDEBUG \ + -O0 \ + -ffunction-sections \ + -fdata-sections \ + --specs=nano.specs \ + -mfpu=fpv4-sp-d16 \ + -mfloat-abi=hard \ + -mthumb \ + -mcpu=cortex-m4 + +LDFLAGS = -mcpu=cortex-m4 \ + --specs=nosys.specs \ + -Wl,--gc-sections \ + -static \ + --specs=nano.specs \ + -mfpu=fpv4-sp-d16 \ + -mfloat-abi=hard \ + -mthumb \ + -Wl,--start-group \ + -lc \ + -lm \ + -Wl,--end-group + +CC = arm-none-eabi-gcc +AS = arm-none-eabi-gcc +AR = arm-none-eabi-ar + +rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d)) +ifneq '' '$(call rwildcard,src,stm32f4*)' +SUBPLATFORM = stm32f4 +CFLAGS += -I$(NO-OS)/libraries/stm32/STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Inc \ + -I$(NO-OS)/libraries/stm32/STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Inc/Legacy \ + -I$(NO-OS)/libraries/stm32/STM32CubeF4/Drivers/CMSIS/Device/ST/STM32F4xx/Include \ + -I$(NO-OS)/libraries/stm32/STM32CubeF4/Drivers/CMSIS/Include +TARGETCFG = target/stm32f4x.cfg +else +$(error Couldn't detect stm32 family.$(ENDL)) +endif + +openocd_paths: +ifndef OPENOCD_SCRIPTS + $(error OPENOCD_SCRIPTS not found in shell environment.$(ENDL)) +endif + +ifndef OPENOCD_BIN + $(error OPENOCD_BIN not found in shell environment.$(ENDL)) +endif + +.PHONY: $(BINARY).openocd +$(BINARY).openocd: + @echo source [find interface/stlink-dap.cfg] > $(BINARY).openocd + @echo set WORKAREASIZE 0x8000 >> $(BINARY).openocd + @echo transport select "dapdirect_swd" >> $(BINARY).openocd + @echo set CHIPNAME $(CHIPNAME) >> $(BINARY).openocd + @echo set ENABLE_LOW_POWER 1 >> $(BINARY).openocd + @echo set STOP_WATCHDOG 1 >> $(BINARY).openocd + @echo set CLOCK_FREQ 8000 >> $(BINARY).openocd + @echo reset_config srst_only srst_nogate connect_assert_srst >> $(BINARY).openocd + @echo set CONNECT_UNDER_RESET 1 >> $(BINARY).openocd + @echo set CORE_RESET 0 >> $(BINARY).openocd + @echo set AP_NUM 0 >> $(BINARY).openocd + @echo set GDB_PORT 3333 >> $(BINARY).openocd + @echo source [find $(TARGETCFG)] >> $(BINARY).openocd + @echo tpiu config disable >> $(BINARY).openocd + +.PHONY: $(BINARY).gdb +$(BINARY).gdb: + @echo target remote localhost:3333 > $(BINARY).gdb + @echo load $(BINARY) >> $(BINARY).gdb + @echo file $(BINARY) >> $(BINARY).gdb + @echo monitor reset init >> $(BINARY).gdb + @echo monitor halt >> $(BINARY).gdb + @echo tb main >> $(BINARY).gdb + @echo tb HardFault_Handler >> $(BINARY).gdb + # These may be helpful but are disabled due to + # limited number of breakpoints: + # @echo tb UsageFault_Handler >> $(BINARY).gdb + # @echo tb MemManage_Handler >> $(BINARY).gdb + # @echo tb BusFault_Handler >> $(BINARY).gdb + +.PHONY: stm32_run +stm32_run: all openocd_paths $(BINARY).openocd + $(OPENOCD_BIN)/openocd -s "$(OPENOCD_SCRIPTS)" -f $(BINARY).openocd \ + -c "program $(BINARY) verify reset exit" + +.PHONY: debug +debug: all openocd_paths $(BINARY).openocd $(BINARY).gdb + ($(OPENOCD_BIN)/openocd -s "$(OPENOCD_SCRIPTS)" -f $(BINARY).openocd \ + -c "init" &); + arm-none-eabi-gdb --command=$(BINARY).gdb + +stm32_project: ; \ No newline at end of file