# The name for the project
TARGET:=mmdvm

# The CPU architecture (will be used for -mcpu)
MCPU:=cortex-m3
MCU:=STM32F105xC

# The source files of the project
CSRC:=
CXXSRC:=$(wildcard *.cpp)

# Include directory for the system include files and system source file
SYSDIR:=system_stm32f1xx
SYSSRC:=$(SYSDIR)/system_stm32f1xx.c

# Other include directories
INCDIR:=

# Definitions
CDEFS:=
CXXDEFS:=

# The name of the startup file which matches to the architecture (MCPU)
STARTUP:=$(SYSDIR)/startup_stm32f105xc.S
STARTUP_DEFS=

# Include directory for CMSIS
CMSISDIR:=/opt/STM32Cube_FW_F1_V1.4.0/Drivers/CMSIS

# Libraries
LIBDIR:=
LIBS:=-larm_cortexM3l_math

# Name of the linker script
LDSCRIPT:=$(SYSDIR)/gcc.ld

# Target objects and binaries directory
OBJDIR:=obj
BINDIR:=bin

# Port definition for programming via bootloader (using stm32flash)
BL_PORT:=ttyUSB0



# Internal Variables
ELF:=$(BINDIR)/$(TARGET).elf
HEX:=$(BINDIR)/$(TARGET).hex
DIS:=$(BINDIR)/$(TARGET).dis
MAP:=$(BINDIR)/$(TARGET).map
OBJ:=$(CSRC:%.c=$(OBJDIR)/%.o) $(CXXSRC:%.cpp=$(OBJDIR)/%.o)
OBJ+=$(SYSSRC:$(SYSDIR)/%.c=$(OBJDIR)/%.o) $(STARTUP:$(SYSDIR)/%.S=$(OBJDIR)/%.o)

# Replace standard build tools by arm tools
CC:=arm-none-eabi-gcc
CXX:=arm-none-eabi-g++
AS:=arm-none-eabi-gcc
LD:=arm-none-eabi-g++
OBJCOPY:=arm-none-eabi-objcopy
OBJDUMP:=arm-none-eabi-objdump
SIZE:=arm-none-eabi-size

# Common flags
COMMON_FLAGS =-mthumb -mlittle-endian -mcpu=$(MCPU)
COMMON_FLAGS+= -Wall
COMMON_FLAGS+= -I. -I$(CMSISDIR)/Include -I$(CMSISDIR)/Device/ST/STM32F1xx/Include -I$(SYSDIR)
COMMON_FLAGS+=  $(addprefix -I,$(INCDIR))
COMMON_FLAGS+= -D$(MCU)
COMMON_FLAGS+= -Os -flto -ffunction-sections -fdata-sections
COMMON_FLAGS+= -g
# Assembler flags
ASFLAGS:=$(COMMON_FLAGS)
# C flags
CFLAGS:=$(COMMON_FLAGS) $(addprefix -D,$(CDEFS))
CFLAGS+= -std=gnu11 -nostdlib
# CXX flags
CXXFLAGS:=$(COMMON_FLAGS) $(addprefix -D,$(CXXDEFS))
CXXFLAGS+= -nostdlib -fno-exceptions -fno-rtti
# LD flags
LDFLAGS:=$(COMMON_FLAGS) -Wl,--gc-sections -Wl,-Map=$(MAP) -Wl,--no-wchar-size-warning
LDFLAGS+= --specs=nosys.specs --specs=nano.specs
LDFLAGS+= -L$(CMSISDIR)/Lib/GCC/ $(addprefix -L,$(LIBDIR))
LDLIBS:=-T$(LDSCRIPT) $(LIBS)

# Dependecies
DEPENDS:=$(CSRC:%.c=$(OBJDIR)/%.d) $(CXXSRC:%.cpp=$(OBJDIR)/%.d)


# Additional Suffixes
.SUFFIXES: .elf .hex

# Targets
.PHONY: all
all: $(DIS) $(HEX)
	$(SIZE) $(ELF)

.PHONY: program
program: $(HEX) $(ELF)
	openocd -f openocd.cfg \
					-c "program $(HEX) verify reset exit"
	$(SIZE) $(ELF)

.PHONY: program_bl
program_bl: $(HEX) $(ELF)
	stm32flash -w $(HEX) -v /dev/$(BL_PORT)
	$(SIZE) $(ELF)

.PHONY: run
run: $(HEX) $(ELF)
	openocd -f openocd.cfg \
					-c "init" -c "reset" -c "exit"

.PHONY: debug
debug: $(ELF)
	./debug.sh $(ELF)

.PHONY: clean
clean:
	$(RM) $(OBJ) $(HEX) $(ELF) $(DIS) $(MAP) $(DEPENDS)

# implicit rules
.elf.hex:
	$(OBJCOPY) -O ihex $< $@

$(OBJDIR)/%.o: %.c
	$(CC) -MMD $(CFLAGS) -c $< -o $@

$(OBJDIR)/%.o: %.cpp
	$(CXX) -MMD $(CXXFLAGS) -c $< -o $@

$(OBJDIR)/%.o: $(SYSDIR)/%.c
	$(CC) $(CFLAGS) -c $< -o $@

$(OBJDIR)/%.o: $(SYSDIR)/%.S
	$(AS) $(ASFLAGS) -c $< -o $@

# explicit rules
$(OBJDIR):
	mkdir -p $(OBJDIR)

$(BINDIR):
	mkdir -p $(BINDIR)

$(ELF): $(OBJDIR) $(BINDIR) $(OBJ)
	$(LD) $(OBJ) $(LDFLAGS) $(LDLIBS) -o $@

$(DIS): $(ELF)
	$(OBJDUMP) -S $< > $@

# include dependecies
-include $(DEPENDS)
