#############################################################
#
# Root Level Makefile for STM32F4
#
# (c) by CHERTS <sleuthhound@gmail.com>
# modified for STM32F7 by Dieter Gräf
#############################################################
# name for the target project needs to be the same name as in EMBITZ
TARGET		= DISCOVERY746
# fpu hard 1 oder soft 0
HARDFP = 0
#alles anzeigen 0
VERBOSE	= 0
#Compilerversion
CSTD = gnu89
CXXSTD = gnu++98

# linker script
LD_DIR	= LD
LD_SCR	= STM32F746NG.ld

BUILD_BASE	= build
RES_BASE	= r_build
BIN_BASE_ROOT = bin
LIB_BASE = lib
DEP_BASE    = dep
# Base directory for the compiler
ARM_ROOT	?= C:\EmBitz\0.40\share\em_armgcc\bin


# Flashtool path
FLASH_TOOL	?=C:\EmBitz\0.40\share\em_armgcc\ST-LINK-Utility\ST-LINK_CLI.exe
FLASH_TOOL_WIN	?=C:\EmBitz\0.40\share\em_armgcc\ST-LINK-Utility\STM32_ST-LINK_Utility.exe

#to allow symbol additions in module
C_DEFS	=
CXX_DEFS	=
#system

RES_MODULES =
MODULES = startup
INCDIRS = 

# user modules
include MakeAPP.mk
include MakeUser.mk
include MakeResources.mk

#C-Compiler optimized

C_DEFS	+= -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_STM32F746NG -DTARGET_STM32F746 -DARM_MATH_CM7
C_DEFS	+=  -DTARGET_CORTEX_M -D__CORTEX_M7 -D__FPU_PRESENT=1 -DTARGET_DISCO_F746NG
C_DEFS	+= -DTARGET_STM -DTARGET_M7 -DTARGET_STM32F7 -DMBED_BUILD_TIMESTAMP=1454221876.04 -D__MBED__=1
C_INCLUDES	=

# compiler flags using during compilation of source files
ifeq ($(HARDFP),1)
	FLOAT_ABI = hard
else
	FLOAT_ABI = softfp
endif
CPU = -mthumb -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=$(FLOAT_ABI)

CFLAGS		= -std=$(CSTD) $(CPU) $(C_DEFS) $(C_INCLUDES) $(OPT)
# for searching errors in embed_srcded assembler code
#CFLAGS  += -save-temps
CFLAGS	+= -pipe -Wno-psabi -Wno-unused-parameter -Wno-missing-field-initializers -fmessage-length=0 -fno-builtin -fno-delete-null-pointer-checks  -Wl,-Map=$(BUILD_BASE)/output.map
CFLAGS  +=
#C++ -Compiler optimized

CXX_DEFS	+= -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_STM32F746NG -DTARGET_STM32F746 -DARM_MATH_CM7
CXX_DEFS	+=  -DTARGET_CORTEX_M -D__CORTEX_M7 -D__FPU_PRESENT=1 -DTARGET_DISCO_F746NG
CXX_DEFS	+= -DTARGET_STM -DTARGET_M7 -DTARGET_STM32F7 -DMBED_BUILD_TIMESTAMP=1454221876.04 -D__MBED__=1

CXX_INCLUDES	=

# compiler flags using during compilation of source files
CXXFLAGS		= -std=$(CXXSTD) $(CPU) $(CXX_DEFS) $(CXX_INCLUDES) $(OPT)
# for searching errors in embed_srcded assembler code
#CXXFLAGS  += -save-temps
# libraryuse
CXXFLAGS	+= -pipe -c -g -Wno-psabi -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP  -Wno-unused-parameter -Wno-missing-field-initializers -fmessage-length=0 -fno-builtin -fno-delete-null-pointer-checks  -Wl,-Map=$(BUILD_BASE)/output.map
CFLAGS  +=
#Assembler
AS_DEFS	=
AS_INCLUDES	=
ASFLAGS	= $(CPU) -Wno-psabi -mno-long-calls $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -Wl,-Map=$(BUILD_BASE)/output.map
# linker flags used to generate the main object file
LDFLAGS	 = $(CPU) $(CXX_DEFS) -Wl,-Map=$(BUILD_BASE)/output.map
LDFLAGS	+= -Wl,--gc-sections -specs=nano.specs  -u _printf_float -u _scanf_float -Wno-psabi -static-libgcc -static-libstdc++


#libraries
LIBS	=  m c gcc nosys
LIBDIR	= lib


ifeq	("$(MAKECMDGOALS)","Debug")
BIN_BASE	:= bin/Debug
CFLAGS	 += -g -gdwarf-2
CXXFLAGS += -g -gdwarf-2
ASFLAGS  += -g
# optimization
OPT	= -O0
else
BIN_BASE	:= bin/Release
# optimization
OPT	= -O3
endif

# select which tools to use as compiler, librarian and linker
CXX		:= $(ARM_ROOT)/arm-none-eabi-g++
CC		:= $(ARM_ROOT)/arm-none-eabi-gcc
AS		:= $(ARM_ROOT)/arm-none-eabi-gcc -x assembler-with-cpp
AR		:= $(ARM_ROOT)/arm-none-eabi-ar
LD		:= $(ARM_ROOT)/arm-none-eabi-g++
SZ		:= $(ARM_ROOT)/arm-none-eabi-size
MOV		:= $(ARM_ROOT)/cp
OBJCOPY	:= $(ARM_ROOT)/arm-none-eabi-objcopy
OBJDUMP	:= $(ARM_ROOT)/arm-none-eabi-objdump
READELF := $(ARM_ROOT)/arm-none-eabi-readelf
HEX		:= $(OBJCOPY) -O ihex
BIN		:= $(OBJCOPY) -O binary -S

# no user configurable options below here
SRC_DIR		:= $(MODULES)
RES_DIR		:= $(RES_MODULES)
BUILD_DIR	:= $(addprefix $(BUILD_BASE)/,$(MODULES))
RES_BUILD	:= $(addprefix $(RES_BASE)/,$(RES_MODULES))

INC_DIR		:= $(addprefix -I,$(INCDIRS))

SRC		:= $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.S))
SRC		+= $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c))
SRC		+= $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cpp))

R_SRC	:=$(foreach rdir,$(RES_DIR),$(wildcard $(rdir)/*.c))

OBJ		:= $(patsubst %.S,$(BUILD_BASE)/%.o,$(SRC))
OBJ     += $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC))
OBJ     += $(patsubst %.cpp,$(BUILD_BASE)/%.o,$(SRC))

R_OBJ	:= $(patsubst %.c,$(RES_BASE)/%.o,$(R_SRC))

LIBS		:= $(addprefix -l,$(LIBS))
APP_AR		:= $(addprefix $(BUILD_BASE)/,$(TARGET).a)
RES_AR		:= $(addprefix $(RES_BASE)/,res_$(TARGET).a)

TARGET_OUT	:= $(addprefix $(BUILD_BASE)/,$(TARGET).out)
RES_OUT		:= $(addprefix $(BUILD_BASE)/,res_$(TARGET).out)
OBJ_OUT		:= $(addprefix $(BUILD_BASE)/,$(TARGET).fil)
ELF_OUT		:= $(addprefix $(BIN_BASE)/,$(TARGET).elf)
HEX_OUT		:= $(addprefix $(BIN_BASE)/,$(TARGET).hex)
R_ELF_OUT	:= $(addprefix $(BIN_BASE)/,res_$(TARGET).elf)
R_HEX_OUT	:= $(addprefix $(BIN_BASE)/,res_$(TARGET).hex)
QSPI_OUT	:= $(addprefix $(BIN_BASE)/,$(TARGET)_qspi.hex)
BIN_OUT		:= $(addprefix $(BUILD_BASE)/,$(TARGET).bin)
DMP_OUT		:= $(addprefix $(BUILD_BASE)/,$(TARGET).dmp)

LD_SCRIPT	:= $(addprefix -T$(LD_DIR)/,$(LD_SCR))
LIBDIR		:= $(addprefix -L$(LIB_BASE)/,$(LIBDIR))



V ?= $(VERBOSE)
ifeq	("$(V)","1")
Q	:=
vecho	:= @true
else
Q	:= @
vecho := @echo
endif



VPATH =  $(SRC_DIR)
VPATH += $(RES_DIR)

define assemble-objects
$1/%.o: %.S
	$(vecho) "AS $$<"
	echo "$$<" >> $(OBJ_OUT)
	$(Q) $(AS) $(INC_DIR) $(ASFLAGS)  -MD -MP -MF $(DEP_BASE)/$$(@F).d -c $$< -o $$@
endef

define compile-objects
$1/%.o: %.c
		$(vecho) "CC $$<"
		echo "$$<" >> $(OBJ_OUT)
		$(Q) $(CC) $(INC_DIR) $(CFLAGS) -MD -MP -MF $(DEP_BASE)/$$(@F).d -c $$< -o $$@
endef

define compile-res-objects
$1/%.o: %.c
		$(vecho) "CC $$<"
		echo "$$<" >> $(OBJ_OUT)
		$(Q) $(CC) $(INC_DIR) $(CRFLAGS) -MD -MP -MF $(DEP_BASE)/$$(@F).d -c $$< -o $$@
endef

define cxxcompile-objects
$1/%.o: %.cpp
		$(vecho) "CXX $$<"
		echo "$$<" >> $(OBJ_OUT)
		$(Q) $(CXX) $(INC_DIR) $(CXXFLAGS) -MD -MP -MF $(DEP_BASE)/$$(@F).d -c $$< -o $$@
endef

.PHONY: all Debug Release checkdirs clean

Debug: all

Release: all

all: DOR checkdirs $(TARGET_OUT) $(HEX_OUT) $(BIN_OUT)

Resource:	checkdirs $(RES_OUT)

DOR:
	$(vecho) "Make $(BIN_BASE)"


$(TARGET_OUT): $(APP_AR)
	$(vecho) "create  $@ "
	$(Q) $(LD) $(LD_SCRIPT) $(LDFLAGS) $(LIBDIR) $(LIBS) $(foreach ldir,$(BUILD_DIR),$(wildcard $(ldir)/*.o))  -o $@
	$(vecho) "Memory usage"
	$(Q) $(SZ) $@
	#$(Q) $(READELF) $(TARGET_OUT) -t
	#$(Q) $(OBJCOPY) --only-section=.QSPIFLASH -O ihex $(TARGET_OUT) $(QSPI_OUT)
	#$(Q) $(OBJCOPY) --remove-section=.QSPIFLASH $(TARGET_OUT)
	#$(Q) $(READELF) $(TARGET_OUT) -t
	$(Q) $(MOV) $(TARGET_OUT) $(ELF_OUT)
	$(vecho) "ELF generated in $(ELF_OUT)"

$(RES_OUT): $(RES_AR)
	$(vecho) "Create Resources $@"
	$(vecho) "with  $(R_HEX_OUT)"
	$(Q) $(LD) -o $@  -Wl,--whole-archive $(RES_AR) -Wl,--no-whole-archive $(LD_SCRIPT) $(LDRFLAGS)
	$(vecho) "Resources Memory usage"
	$(Q) $(SZ) $@
	#$(Q) $(READELF) $(RES_OUT) -t
	$(Q) $(OBJCOPY) --only-section=.QSPIFLASH -O ihex $(RES_OUT) $(R_HEX_OUT)
	$(Q) $(MOV) $(RES_OUT) $(R_ELF_OUT)
	$(vecho) "HEX generated in $(R_HEX_OUT)"

$(HEX_OUT): $(TARGET_OUT)
	$(Q) $(HEX) $(TARGET_OUT) $@
	$(vecho) "HEX generated in $(HEX_OUT)"

$(BIN_OUT): $(HEX_OUT)
	$(Q) $(BIN) $(TARGET_OUT) $@
	$(vecho) "BIN generated in $(BIN_OUT)"

$(APP_AR): $(OBJ)
	$(vecho) "AR $@"
	$(Q) $(AR) cru $@ $^

$(RES_AR): $(R_OBJ)
	$(vecho) "AR $@"
	$(Q) $(AR) cru $@ $^

checkdirs: $(BUILD_DIR) $(RES_BUILD) $(FW_BASE) $(DEP_BASE) $(BIN_BASE) $(RES_BASE)

$(BUILD_DIR):
	$(Q) mkdir -p $@
	echo "" > $(OBJ_OUT)
$(RES_BUILD):
	$(Q) mkdir -p $@
$(FW_BASE):
	$(Q) mkdir -p $@
$(DEP_BASE):
	$(Q) mkdir -p $@
$(RES_BASE):
	$(Q) mkdir -p $@
$(BIN_BASE):
	$(Q) mkdir -p $@

rebuild: clean all

dump:
		$(Q) $(OBJDUMP) -t $(TARGET_OUT)

flash:
	$(vecho) "flashing internal Flash file $(HEX_OUT)"
	$(Q)$(FLASH_TOOL) -c SWD -ME -p $(HEX_OUT) -Rst -Run

qspi:
	$(vecho) "QSPI Flash"
	$(FLASH_TOOL_WIN)

cleanDebug: clean

cleanRelease: clean

clean:
	$(Q) rm -f $(APP_AR)
	$(Q) rm -f $(TARGET_OUT)
	$(Q) rm -rf $(BUILD_DIR)
	$(Q) rm -rf $(RES_BUILD)
	$(Q) rm -rf $(BUILD_BASE)
	$(Q) rm -rf $(RES_BASE)
	$(Q) rm -rf $(FW_BASE)
	$(Q) rm -rf $(DEP_BASE)
	$(Q) rm -rf $(BIN_BASE_ROOT)

#######################################
# dependencies
#######################################
#-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)

$(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir))))
$(foreach bdir,$(RES_BUILD),$(eval $(call compile-res-objects,$(bdir))))
$(foreach bdir,$(BUILD_DIR),$(eval $(call cxxcompile-objects,$(bdir))))
$(foreach bdir,$(BUILD_DIR),$(eval $(call assemble-objects,$(bdir))))
