#=============================================================================
# external tools
#-----------------------------------------------------------------------------

# GNU Toolchain Path
#GCCPATH  = M:/Development/GCC-Toolchains/YAGARTO/toolchain-4.4.2/bin/
#GCCPATH  = M:/Development/GCC-Toolchains/WinARM/bin/

# GNU Toolchain Binaries
CC       = $(GCCPATH)arm-elf-gcc
ASM      = $(GCCPATH)arm-elf-gcc -x assembler-with-cpp
OBJCOPY  = $(GCCPATH)arm-elf-objcopy
OBJDUMP  = $(GCCPATH)arm-elf-objdump
NM       = $(GCCPATH)arm-elf-nm

# OpenOCD
OOCD     = openocd

# General Utilities path
#UTILPATH = M:/Development/YAGARTO/tools/bin/
#UTILPATH = M:/Development/GCC-Toolchains/WinARM/utils/

# General Utilities commands
RM       = $(UTILPATH)rm
MKDIR    = $(UTILPATH)mkdir


#=============================================================================
# config
#-----------------------------------------------------------------------------

# Specify the name of the target ARM processor
ARM_CPU = arm7tdmi

# Define linker target name here
TARGET = sam7s256

CDEFS =

ADEFS =


#=============================================================================
# define input/output folders
#-----------------------------------------------------------------------------

ROOTDIR    = ./
BUILDDIR   = $(ROOTDIR)build
OBJDIR     = $(BUILDDIR)/obj
DEPSDIR    = $(BUILDDIR)/dep
INCDIR     = $(ROOTDIR)include
SCRIPTSDIR = $(ROOTDIR)scripts
SRCDIR     = $(ROOTDIR)source


#=============================================================================
# define source files
#-----------------------------------------------------------------------------

# source folders
SRCDIRS = \
	startup \
	misc

# C source files for 32bit ARM code
C_SRC_ARM = \
	startup/low_level_init.c \
	misc/syscalls.c \
	misc/systimer.c \
	isr.c \
	main.c

# C source files for 16bit Thumb code
C_SRC_THUMB = \

# ASM source files for 32bit ARM code
ASM_SRC_ARM = \
	startup/startup.S \
	arm_exceptions.S

# ASM source files for 16bit Thumb code
ASM_SRC_THUMB = \

# include other source lists
include $(SRCDIR)/at91lib/_makefile.mk
include $(SRCDIR)/driver/_makefile.mk

# generate obj-list and folder-list ------------------------------------------
C_OBJ_ARM     = $(C_SRC_ARM:%.c=%.o)
C_OBJ_THUMB   = $(C_SRC_THUMB:%.c=%.o)
ASM_OBJ_ARM   = $(ASM_SRC_ARM:%.S=%.o)
ASM_OBJ_THUMB = $(ASM_SRC_THUMB:%.S=%.o)
ALL_OBJ       = $(C_OBJ_ARM) $(ASM_OBJ_ARM) $(C_OBJ_THUMB) $(ASM_OBJ_THUMB)
OBJDIRS       = $(OBJDIR) $(addprefix $(OBJDIR)/, $(SRCDIRS))

# path for the obj files:
vpath %.o ${OBJDIRS}


#=============================================================================
# compiler flags
#-----------------------------------------------------------------------------

INCDIR += $(addprefix $(SRCDIR)/, $(SRCDIRS)) $(SRCDIR)
CCINC = $(patsubst %,-I%,$(INCDIR))

# --- COMPILER ---------------------------------------------------------------

# Optimization level, can be [0, 1, 2, 3, s] 
ifeq ($(MAKECMDGOALS), release)
OPT = -Os
else
OPT = -O0
endif

# Debugging format
ifeq ($(MAKECMDGOALS), release)
DEBUG =
else
DEBUG = -gdwarf-2
endif

# Compiler flag to set the C Standard level.
#   c89   - "ANSI" C
#   gnu89 - c89 plus GCC extensions
#   c99   - ISO C99 standard (not yet fully implemented)
#   gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99

# C/C++ flags
CXXFLAGS  = $(DEBUG) -mcpu=$(ARM_CPU) $(OPT) $(CDEFS)
CXXFLAGS += -mthumb-interwork
CXXFLAGS += -mlong-calls
CXXFLAGS += -ffunction-sections
CXXFLAGS += -fomit-frame-pointer
CXXFLAGS += -fverbose-asm
CXXFLAGS += -MD -MP -MF $(DEPSDIR)/$(notdir $@).d
CXXFLAGS += -Wall
CXXFLAGS += -Wcast-align
CXXFLAGS += -Wimplicit 
CXXFLAGS += -Wpointer-arith
CXXFLAGS += -Wswitch
CXXFLAGS += -Wredundant-decls
CXXFLAGS += -Wreturn-type
CXXFLAGS += -Wshadow
CXXFLAGS += -Wunused
CXXFLAGS += -Wa,-ahlms=$(OBJDIR)/$(@:.o=.lst)
# AT91-lib warnings with:
CXXFLAGS += -Wcast-qual

# C only flags
CFLAGS    = $(CXXFLAGS)
CFLAGS   += $(CSTANDARD)
# AT91-lib warnings with:
CFLAGS += -Wmissing-prototypes 
CFLAGS += -Wstrict-prototypes
CFLAGS += -Wmissing-declarations

# C++ flags
CPPFLAGS  = $(CXXFLAGS)
CPPFLAGS += -fno-rtti
CPPFLAGS += -fno-exceptions

# --- ASSEMBLER --------------------------------------------------------------

ASMFLAGS  = $(DEBUG) -mcpu=$(ARM_CPU) $(ADEFS)
ASMFLAGS += -mthumb-interwork
ASMFLAGS += -Wa,-amhls=$(OBJDIR)/$(@:.o=.lst)

# --- LINKER -----------------------------------------------------------------

# Additional libraries
#LIB_MATH = -lm
#LIB_CPP  = -lstdc++

LDFLAGS = -mcpu=$(ARM_CPU) -nostartfiles \
	-T $(SCRIPTSDIR)/$(TARGET).ld -o $@ \
	-Wl,-Map,$(@:.elf=.map),--cref,--no-warn-mismatch $(LIB_MATH) $(LIB_CPP) $(LIBDIR)


#=============================================================================
# make rules
#-----------------------------------------------------------------------------

# default rule .. just build the binary
default all: build_dirs $(BUILDDIR)/$(TARGET).bin

# build the release target
release: rebuild

# rebuild all targets
rebuild: clean default

# create build folders -------------------------------------------------------
build_dirs: $(BUILDDIR) $(OBJDIRS) $(DEPSDIR)
$(BUILDDIR) $(OBJDIRS) $(DEPSDIR):
	@echo " "
	$(MKDIR) $@

# build the main targets -----------------------------------------------------

$(BUILDDIR)/$(TARGET).bin: $(BUILDDIR)/$(TARGET).elf
	@echo " "
	@echo "---[OBJCOPY]------------------------------------------------------------------"
	$(OBJCOPY) -O binary $< $@

$(BUILDDIR)/$(TARGET).elf: $(ALL_OBJ) $(SCRIPTSDIR)/$(TARGET).ld
	@echo " "
	@echo "---[LINKER]-------------------------------------------------------------------"
	$(CC) $(addprefix $(OBJDIR)/, $(ALL_OBJ)) $(LDFLAGS) $(LIBS) -o $@
	
# compile source -------------------------------------------------------------

# C source files (16bit Thumb code)
$(C_OBJ_THUMB): %.o: ${SRCDIR}/%.c
	@echo " "
	@echo "---[COMPILER/THUMB]-----------------------------------------------------------"
	$(CC) -c -mthumb $(CFLAGS) $(CCINC) $< -o $(OBJDIR)/$@

# C source files (32bit ARM code)
${C_OBJ_ARM}: %.o: ${SRCDIR}/%.c
	@echo " "
	@echo "---[COMPILER/ARM]-------------------------------------------------------------"
	$(CC) -c -marm $(CFLAGS) $(CCINC) $< -o $(OBJDIR)/$@ 

# ASM source files (16bit Thumb code)
$(ASM_OBJ_THUMB): %.o: ${SRCDIR}/%.S
	@echo " "
	@echo "---[ASSEMBLER/THUMB]----------------------------------------------------------"
	$(ASM) -c -mthumb $(ASMFLAGS) $< -o $(OBJDIR)/$@

# ASM source files (32bit ARM code)
$(ASM_OBJ_ARM): %.o: ${SRCDIR}/%.S
	@echo " "
	@echo "---[ASSEMBLER/ARM]------------------------------------------------------------"
	$(ASM) -c -marm $(ASMFLAGS) $< -o $(OBJDIR)/$@

# include the dependency files -----------------------------------------------
-include $(wildcard $(DEPSDIR)/*.d)

# remove all build targets ---------------------------------------------------
clean:
	@echo " "
	@echo "---[CLEANUP]------------------------------------------------------------------"
	-$(RM) -fR $(BUILDDIR)\*.* $(BUILDDIR)

# flash binary into the C ---------------------------------------------------
flash:
	@echo " "
	@echo "---[FLASH DEVICE]-------------------------------------------------------------"
	$(OOCD) -f $(SCRIPTSDIR)/openocd.cfg -f $(SCRIPTSDIR)/openocd_flash.script -c shutdown

.PHONY: all default release flash rebuild clean build_dirs
