# Copyright 2019, Max Regan # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Tools # TOOL_PREFIX ?= arm-none-eabi- CC = $(TOOL_PREFIX)gcc CXX = $(TOOL_PREFIX)g++ CPP = $(TOOL_PREFIX)cpp AS = $(TOOL_PREFIX)as LD = $(TOOL_PREFIX)g++ OBJCOPY = $(TOOL_PREFIX)objcopy STM32_PROG = STM32_Programmer.sh # # Device Variables # BOARD ?= watch ifeq ($(BOARD), watch) DEVICE_TYPE ?= stm32l010c6 DEVICE_FAMILY = stm32l010xx DEVICE_LINE = stm32l0xx STACK_SIZE ?= 512 HEAP_SIZE ?= 0 else ifeq ($(BOARD), devboard) DEVICE_TYPE ?= stm32l412rb DEVICE_FAMILY = stm32l412xx DEVICE_LINE = stm32l4xx STACK_SIZE ?= 768 HEAP_SIZE ?= 0 else $(error Unsupported board: $(BOARD)) endif # # Filenames and paths # # Ignores dotfiles and other garbage some tools leave behind define find_important $(shell find $(1) -type f -and -name $(2) -and -not -iname "*~" -and -not -iname "*#*" -and -not \( -path "*.cquery_cached_index*" \) -and -not \( -path "*build*" \) -and -not \( -path "*ThirdParty/printf/test/*" \) ) endef FONTS := small large_digits FONT_GEN_DIR := build/gen/fonts FONT_C_FILES := $(patsubst %,$(FONT_GEN_DIR)/%.c,$(FONTS)) FONT_H_FILES := $(patsubst %,$(FONT_GEN_DIR)/%.h,$(FONTS)) BSP_SRC_DIR := ./Bsp/ APP_SRC_DIR := ./Application/ TEST_APP_SRC_DIR := ./Test/Apps/ TEST_COMMON_SRC_DIR:= ./Test/Common/ TEST_BOARD_SRC_DIR := ./Test/Board/ THIRD_PARTY_SRC_DIR := ./ThirdParty/ COMMON_SRC_DIRS := $(BSP_SRC_DIR) $(APP_SRC_DIR) $(TEST_COMMON_SRC_DIR) $(THIRD_PARTY_SRC_DIR) C_SOURCES := $(call find_important, $(COMMON_SRC_DIRS), '*.c') $(FONT_C_FILES) CXX_SOURCES := $(call find_important, $(COMMON_SRC_DIRS), '*.cpp') S_SOURCES := $(call find_important, $(COMMON_SRC_DIRS), '*.s') SPP_SOURCES := Bsp/Mcu/$(DEVICE_TYPE).S SOURCES := $(C_SOURCES) $(S_SOURCES) $(SPP_SOURCES) $(CPP_SOURCES) APPS := ./Application/main TEST_APPS := $(patsubst %.cpp, %, $(call find_important, $(TEST_APP_SRC_DIR), '*.cpp')) APP_ELFS := $(addsuffix .elf, $(APPS)) APP_MAPS := $(addsuffix .map, $(APPS)) APP_BINS := $(addsuffix .bin, $(APPS)) APP_OBJS := $(addsuffix .o, $(APPS)) TEST_APP_ELFS := $(addsuffix .elf, $(TEST_APPS)) TEST_APP_MAPS := $(addsuffix .map, $(TEST_APPS)) TEST_APP_BINS := $(addsuffix .bin, $(TEST_APPS)) TEST_APP_OBJS := $(addsuffix .o, $(TEST_APPS)) C_OBJS := $(patsubst %.c,%.o,$(C_SOURCES)) CXX_OBJS := $(patsubst %.cpp,%.o,$(CXX_SOURCES)) S_OBJS := $(patsubst %.s,%.o,$(S_SOURCES)) SPP_OBJS := $(patsubst %.S,%.o,$(SPP_SOURCES)) ALL_OBJS := $(C_OBJS) $(S_OBJS) $(SPP_OBJS) $(CXX_OBJS) COMMON_OBJS := $(filter-out $(APP_OBJS), $(ALL_OBJS)) TEST_BOARD_OBJ := $(TEST_BOARD_SRC_DIR)$(BOARD).o LINKER_SCRIPT ?= Bsp/Mcu/$(DEVICE_TYPE).ld OUTPUT_NAME ?= Application/main OUTPUT_BIN ?= $(OUTPUT_NAME).bin OUTPUT_ELF ?= $(OUTPUT_NAME).elf OUTPUT_MAP ?= $(OUTPUT_NAME).map # $(info "ALL_OBJS=$(ALL_OBJS)") # $(info "APP_OBJS=$(APP_OBJS)") # $(info "OBJS=$(OBJS)") # # Flags # DEVICE_FAMILY_DEFINE = $(subst XX,xx,$(shell echo $(DEVICE_FAMILY) | tr '[:lower:]' '[:upper:]')) DEVICE_TYPE_DEFINE = $(shell echo $(DEVICE_TYPE) | tr '[:lower:]' '[:upper:]') DEVICE_LINE_DEFINE = $(shell echo $(DEVICE_LINE) | tr '[:lower:]' '[:upper:]') BOARD_DEFINE = BOARD_$(shell echo $(BOARD) | tr '[:lower:]' '[:upper:]') CPU_FLAGS = -mthumb -mcpu=cortex-m0plus -mfloat-abi=soft # C pedantism CFLAGS = -Wall -Wextra -pedantic -Werror -Wcast-align CXX_FLAGS = -Wsuggest-override -Wsuggest-final-methods -Wsuggest-final-types # Debug/optimization CFLAGS += -Os -g3 CFLAGS += -fdata-sections -ffunction-sections # Architecture CFLAGS += $(CPU_FLAGS) CFLAGS += -ffreestanding CFLAGS += -fstack-usage -Wstack-usage=128 # Defines CFLAGS += -D$(DEVICE_FAMILY_DEFINE) -D$(DEVICE_TYPE_DEFINE) -D$(DEVICE_LINE_DEFINE) -D$(BOARD_DEFINE) # CFLAGS += -DPRINTF_DISABLE_SUPPORT_FLOAT -DPRINTF_DISABLE_SUPPORT_EXPONENTIAL -DPRINTF_DISABLE_SUPPORT_PTRDIFF_T # Consider this one if we are running short on flash, it saved about 1K # CFLAGS += -DPRINTF_DISABLE_SUPPORT_LONG_LONG CFLAGS += -D__STDC_FORMAT_MACROS # Includes CFLAGS += -I./Bsp/Mcu/ CFLAGS += -I./ThirdParty/stm32/$(DEVICE_LINE)/Include CFLAGS += -I./ThirdParty/CMSIS/Core/Include CFLAGS += -I./ThirdParty/printf CFLAGS += -I./build/gen/ CFLAGS += -I./Test/Common/ CFLAGS += -I. CXX_FLAGS += -std=c++14 -fno-exceptions -fno-rtti -fno-use-cxa-atexit # Startup Definitions ASFLAGS += $(CPU_FLAGS) ASFLAGS += -D__STARTUP_CLEAR_BSS ASFLAGS += -D__HEAP_SIZE=$(HEAP_SIZE) ASFLAGS += -D__STACK_SIZE=$(STACK_SIZE) LDFLAGS += $(CPU_FLAGS) LDFLAGS += -Wl,--gc-sections -Wl,--build-id=none -static LDFLAGS += -Wl,--wrap=malloc -Wl,--wrap=free # Fail to link if dynamic allocation is sneaking through LDFLAGS += -Wl,-print-memory-usage # LDFLAGS += -lstdc++ -latomic LDFLAGS += -nostartfiles # # Build info # $(info ================================) $(info Build Parameters) $(info Board: $(BOARD)) $(info Device: $(DEVICE_TYPE)) $(info Device define: $(DEVICE_TYPE_DEFINE)) $(info Device type define: $(DEVICE_FAMILY_DEFINE)) $(info Device line define: $(DEVICE_LINE_DEFINE)) $(info Stack size: $(STACK_SIZE)) $(info Heap size: $(HEAP_SIZE)) $(info ================================) # # Default Target # .PHONY: build build: $(APP_BINS) $(TEST_APP_BINS) # # Build Logic # %.o: %.c $(FONT_H_FILES) @echo "CC $@" @$(CC) $(CFLAGS) -c $< -o $@ %.o: %.S $(FONT_H_FILES) @echo "AS $@" @$(CC) $(ASFLAGS) -c $< -o $@ %.o: %.cpp $(FONT_H_FILES) @echo "CXX $@" @$(CXX) $(CXX_FLAGS) $(CFLAGS) -c $< -o $@ SMALL_FONT=ThirdParty/fonts/roboto_mono/RobotoMono-Regular.ttf $(FONT_GEN_DIR)/small.h $(FONT_GEN_DIR)/small.c: Gen/fixedfont-to-c.py Gen/font.py @echo "GEN $@" @mkdir -p $(FONT_GEN_DIR) @Gen/fixedfont-to-c.py $(patsubst .%,%,$(suffix $@)) $(SMALL_FONT) "$@" -s 20 --header-dir "Bsp/" --name font_small LARGE_FONT=ThirdParty/fonts/roboto_mono/RobotoMono-Bold.ttf $(FONT_GEN_DIR)/large_digits.h $(FONT_GEN_DIR)/large_digits.c: Gen/fixedfont-to-c.py Gen/font.py @echo "GEN $@" @mkdir -p $(FONT_GEN_DIR) @Gen/fixedfont-to-c.py $(patsubst .%,%,$(suffix $@)) $(LARGE_FONT) "$@" -s 70 --header-dir "Bsp/" --name font_large_digits -c "01234567890:" %.bin: %.elf @echo "OBJCOPY $@" @$(OBJCOPY) -O binary $^ $@ $(TEST_APP_MAPS) $(TEST_APP_ELFS): $(TEST_APP_OBJS) $(LINKER_SCRIPT) $(COMMON_OBJS) $(TEST_BOARD_OBJ) @echo "LD $@" @$(LD) -T $(LINKER_SCRIPT) $(LDFLAGS) -o $(basename $@).elf $(basename $@).o $(COMMON_OBJS) $(TEST_BOARD_OBJ) -Wl,-Map=$(basename $@).map $(APP_MAPS) $(APP_ELFS): $(APP_OBJS) $(LINKER_SCRIPT) $(COMMON_OBJS) @echo "LD $@" @$(LD) -T $(LINKER_SCRIPT) $(LDFLAGS) -o $(basename $@).elf $(basename $@).o $(COMMON_OBJS) -Wl,-Map=$(basename $@).map # # Utilities # STM32FLASH_DEVICE = /dev/ttyUSB0 FLASH_BIN ?= $(OUTPUT_BIN) .PHONY: flash flash: $(OUTPUT_BIN) @echo "FLASH $(OUTPUT_BIN)" $(STM32_PROG) --connect port=SWD reset=Hwrst -w $(FLASH_BIN) 0x8000000 -v --go .PHONY: jlink jlink: $(OUTPUT_BIN) @echo "FLASH $(OUTPUT_BIN)" ./jlink.sh $(DEVICE_TYPE) $(FLASH_BIN) .PHONY: clean clean: @echo "Cleaning up..." @rm -f $(OBJS) $(OUTPUT_BIN) $(OUTPUT_ELF) $(FONT_C_FILES) $(FONT_H_FILES) $(OUTPUT_MAP) $(APP_ELFS) $(APP_MAPS) $(APP_BINS) $(APP_OBJS) $(TEST_APP_ELFS) $(TEST_APP_MAPS) $(TEST_APP_BINS) $(TEST_APP_OBJS) $(addsuffix .su,$(basename $(ALL_OBJS))) # Please do not delete my files. .SECONDARY: $(ALL_OBJS) $(APP_ELFS)