IO_DATA=0x0401E000
FM_DATA=0x0401EA00

TGT_AS_SRC  = preboot_fm.s preboot_io.s
TGT_IO_C_SRC  = upctalk0.c upc_uart.c
TGT_FM_C_SRC  = upctalk1.c upc_wait.c
TGT_C_SRC  = $(TGT_IO_C_SRC) $(TGT_FM_C_SRC)
TGT_C_EXTRA_SRC = dbg_printf.c
TOOL_C_SRC = upc_start_stop.c

ALLASRC = $(TGT_AS_SRC)
ALLCSRC = $(TGT_C_SRC) $(TGT_C_EXTRA_SRC)
ALLCSRC_TOOL = $(TOOL_C_SRC)

TGT_IO_OBJ = $(TGT_IO_C_SRC:.c=.o)
TGT_FM_OBJ = $(TGT_FM_C_SRC:.c=.o)
TGT_OBJ = $(TGT_C_SRC:.c=.o)
TGT_EXTRA_OBJ = $(TGT_C_EXTRA_SRC:.c=.o) $(TGT_AS_SRC:.s=.o)
TOOL_OBJ = $(TOOL_C_SRC:.c=.o)

TGT_IO_BIN  = $(foreach x, $(TGT_IO_C_SRC), $(basename $(x)).elf)
TGT_FM_BIN  = $(foreach x, $(TGT_FM_C_SRC), $(basename $(x)).elf)
TGT_BIN  = $(TGT_IO_BIN) $(TGT_FM_BIN)
TOOL_BIN = $(basename $(TOOL_C_SRC))

TGT_CFLAGS += -g -DCPU_FREQ=529 -DUART -Os
TGT_CFLAGS += -march=armv5 -mlittle-endian
TGT_CFLAGS += -I ../upc-mod/asic -I=/usr/include/assp
TOOL_CFLAGS += -Wall -mlittle-endian
TGT_AFLAGS += -march=armv5 -mlittle-endian

CROSS_COMPILE ?= arm-none-eabi-
CROSS_CFLAGS  ?= $(TGT_CFLAGS)
CROSS_ASFLAGS ?= $(TGT_AFLAGS)
TOOL_LDFLAGS  ?= -lc -lgcc
CROSS_LDFLAGS ?= -entry=0x0 -Ttext 0x0 -EL
CROSS_IO_LDFLAGS = $(CROSS_LDFLAGS) -Tdata $(IO_DATA) -Tbss $(IO_DATA)
CROSS_FM_LDFLAGS = $(CROSS_LDFLAGS) -Tdata $(FM_DATA) -Tbss $(FM_DATA)

# Define toolchain names
CC      := $(CROSS_COMPILE)gcc
HOSTCC  := gcc
CPP     := $(CROSS_COMPILE)g++
HOSTCPP := g++
AS      := $(CROSS_COMPILE)as
LD      := $(CROSS_COMPILE)ld
HOSTLD  := gcc
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
SIZE    := $(CROSS_COMPILE)size
NM      := $(CROSS_COMPILE)nm
STRIP   := $(CROSS_COMPILE)strip


quote   = '
# magic to close the quote above '

MSG_HOST_LD     := ${quote} HOST-LD   ${quote}
MSG_LD          := ${quote} CROSS-LD  ${quote}
MSG_STRIP       := ${quote} STRIP     ${quote}
MSG_OBJDUMP     := ${quote} OBJDUMP   ${quote}
MSG_OBJCPY      := ${quote} OBJCPY    ${quote}
MSG_HOST_CC     := ${quote} HOST-CC   ${quote}
MSG_CC          := ${quote} CROSS-CC  ${quote}
MSG_HOST_CPP    := ${quote} HOST-CXX  ${quote}
MSG_CPP         := ${quote} CXX       ${quote}
MSG_HOST_AS     := ${quote} HOST-AS   ${quote}
MSG_OVR         := ${quote} OVERLAY   ${quote}
MSG_AS          := ${quote} CROSS-AS  ${quote}
MSG_CLEAN       := ${quote} CLEANing  ${quote}
MSG_CF          := ${quote} CFLOW     ${quote}

# Decide on a verbosity level based on the V= parameter
export AT := @

ifndef V
export V0    :=
export V1    := $(AT)
else ifeq ($(V), 0)
export V0    := $(AT)
export V1    := $(AT)
else ifeq ($(V), 1)
endif

# Cross Compile: create .o's from C source files.
define COMPILE_CROSS_CC_MACRO
$(basename $(1)).o : $(1)
	@echo $(MSG_CC) $$<
	$(V1) $(CC) -c $$(CROSS_CFLAGS) $$(CONLYFLAGS) $$< -o $$@
endef

# Cross Assemble: create .o's from asm source files.
define ASSEMBLY_CROSS_MACRO
$(basename $(1)).o : $(1) 
	@echo $(MSG_AS) $$<
	$(V1) $(AS) $$(CROSS_ASFLAGS) $$< -o $$@
endef

# Link IO .o's into an ELF object file
define ELF_IO_PRGM_MACRO
$(1): $(basename $(1)).o $(TGT_EXTRA_OBJ)
	@echo $(MSG_LD) $$@
	$(V1) $(LD) $(CROSS_IO_LDFLAGS) -o $$@ $$^
endef

# Link FM .o's into an ELF object file
define ELF_FM_PRGM_MACRO
$(1): $(basename $(1)).o $(TGT_EXTRA_OBJ)
	@echo $(MSG_LD) $$@
	$(V1) $(LD) $(CROSS_FM_LDFLAGS) -o $$@ $$^
endef

all: $(TGT_BIN) $(TOOL_BIN)
	
# Cross Compile C source files
$(foreach src, $(ALLCSRC), $(eval $(call COMPILE_CROSS_CC_MACRO,$(src))))

# Cross Assemble .s source files
$(foreach src, $(ALLASRC), $(eval $(call ASSEMBLY_CROSS_MACRO,$(src))))

# Link .elf for IO type .obj files
$(foreach bin, $(TGT_IO_BIN), $(eval $(call ELF_IO_PRGM_MACRO,$(bin))))
	
# Link .elf for FM type .obj files
$(foreach bin, $(TGT_FM_BIN), $(eval $(call ELF_FM_PRGM_MACRO,$(bin))))
	
# Build Native Binary Program for host .obj files
$(TOOL_BIN): $(ALLCSRC_TOOL)
	@echo $(MSG_CC) $<
	$(V1) $(CC) $(TOOL_CFLAGS) $< -o $@
	
clean:
	@rm -f *.o $(TGT_BIN) $(TOOL_BIN)

test_vars:
	@echo _$(ALLCSRC)_ _$(ALLCSRC_TOOL)_
	@echo TGT_OBJ: $(TGT_OBJ)
	@echo TGT_EXTRA_OBJ: $(TGT_EXTRA_OBJ)
	@echo TOOL_OBJ: $(TOOL_OBJ)
	@echo TOOL_BIN: $(TOOL_BIN)
	@echo TGT_xx_BIN: $(TGT_IO_BIN):$(foreach x, $(TGT_FM_BIN), $(x))
