|  | # Copyright 2012 Olivier Gillet.
#
# Author: Olivier Gillet (ol.gillet@gmail.com)
#
# 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.
# 
# See http://creativecommons.org/licenses/MIT/ for more information.
# ------------------------------------------------------------------------------
# Files and directories
# ------------------------------------------------------------------------------
TOOLCHAIN_PATH ?= /usr/local/arm/
PGM_INTERFACE ?= stlink-v2
# PGM_INTERFACE ?= ftdi/olimex-arm-jtag-swd
# PGM_INTERFACE ?= ftdi/olimex-arm-usb-ocd-h
ifeq ($(PGM_INTERFACE),ftdi/olimex-arm-jtag-swd)
OPENOCD_INTERFACE_SCRIPT ?= interface/ftdi/olimex-arm-usb-ocd-h.cfg -f interface/ftdi/olimex-arm-jtag-swd.cfg
else
OPENOCD_INTERFACE_SCRIPT ?= interface/$(PGM_INTERFACE).cfg
endif
PGM_SERIAL_PORT ?= /dev/ftdi-usbserial
PGM_SERIAL_BAUD_RATE ?= 115200
PGM_SERIAL_VERIFY ?= -v
# --- You should not have to modify these --------------------------------------
TOOLCHAIN_BIN  = $(TOOLCHAIN_PATH)bin/
STM32_PATH     = stmlib/third_party/STM
# --- Do not modify anything below this point ----------------------------------
BUILD_ROOT     = build/
BUILD_DIR      = $(BUILD_ROOT)$(TARGET)/
CC             = $(TOOLCHAIN_BIN)arm-none-eabi-gcc
CXX            = $(TOOLCHAIN_BIN)arm-none-eabi-g++
AS             = $(TOOLCHAIN_BIN)arm-none-eabi-as
OBJCOPY        = $(TOOLCHAIN_BIN)arm-none-eabi-objcopy
DB             = $(TOOLCHAIN_BIN)arm-none-eabi-gdb
OBJDUMP        = $(TOOLCHAIN_BIN)arm-none-eabi-objdump
AR             = $(TOOLCHAIN_BIN)arm-none-eabi-ar
SIZE           = $(TOOLCHAIN_BIN)arm-none-eabi-size
NM             = $(TOOLCHAIN_BIN)arm-none-eabi-nm
REMOVE         = rm -f
CAT            = cat
FORMAT_SIZE    = | figlet | cowsay -n -f moose
FORMAT_RAMSIZE = | figlet | cowsay -n -f small
STM32LOADER_PATH = stmlib/programming/serial/
OPENOCD_SCRIPTS_PATH = stmlib/programming/jtag/
# ------------------------------------------------------------------------------
# Files and directories for the user code
# ------------------------------------------------------------------------------
VPATH          = $(PACKAGES)
CC_FILES       = $(notdir $(wildcard $(patsubst %,%/*.cc,$(PACKAGES))))
C_FILES        = $(notdir $(wildcard $(patsubst %,%/*.c,$(PACKAGES))))
AS_FILES       = $(notdir $(wildcard $(patsubst %,%/*.s,$(PACKAGES))))
TARGET_BIN     = $(BUILD_DIR)$(TARGET).bin
TARGET_ELF     = $(BUILD_DIR)$(TARGET).elf
TARGET_HEX     = $(BUILD_DIR)$(TARGET).hex
COMBO_HEX      = $(BUILD_DIR)$(TARGET)_bootloader_combo.hex
COMBO_BIN      = $(BUILD_DIR)$(TARGET)_bootloader_combo.bin
BOOTLOADER_HEX = $(BUILD_ROOT)$(BOOTLOADER)/$(BOOTLOADER).hex
TARGET_SIZE    = $(BUILD_DIR)$(TARGET).size
TARGETS        = $(BUILD_DIR)$(TARGET).*
DEP_FILE       = $(BUILD_DIR)depends.mk
# ------------------------------------------------------------------------------
# Platform specific flags
# ------------------------------------------------------------------------------
ifeq ($(FAMILY),f4xx)
MODEL_DEFINE = STM32F40_41xxx -DSTM32F4XX -DARM_MATH_CM4 -D__FPU_PRESENT
STARTUP_OBJ   = $(BUILD_DIR)startup_stm32f4xx.o
LINKER_SCRIPT = stmlib/linker_scripts/stm32f4xx_flash$(LD_SUFFIX).ld
FW_STDDRIVER_DIR = $(STM32_PATH)/STM32F4xx_StdPeriph_Driver
ARCHFLAGS = -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb-interwork -funroll-loops
ARCH_DEFINE = GCC_ARMCM4
OPENOCD_TARGET = f4x
else ifeq ($(FAMILY),f37x)
MODEL_DEFINE = STM32F37X -DARM_MATH_CM4 -D__FPU_PRESENT
STARTUP_OBJ   = $(BUILD_DIR)startup_stm32f37x.o
LINKER_SCRIPT = stmlib/linker_scripts/stm32f373x_flash$(LD_SUFFIX).ld
FW_STDDRIVER_DIR = $(STM32_PATH)/STM32F37x_StdPeriph_Driver
ARCHFLAGS = -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb-interwork -funroll-loops
ARCH_DEFINE = GCC_ARMCM4
OPENOCD_TARGET = f3x
else ifeq ($(FAMILY),f0xx)
MODEL_DEFINE = STM32F0XX
STARTUP_OBJ   = $(BUILD_DIR)startup_stm32f0xx.o
LINKER_SCRIPT = stmlib/linker_scripts/stm32f0xx_flash$(LD_SUFFIX).ld
FW_STDDRIVER_DIR = $(STM32_PATH)/STM32F0xx_StdPeriph_Driver
ARCHFLAGS = -mcpu=cortex-m0 -mthumb -mthumb-interwork -funroll-loops
ARCH_DEFINE = GCC_ARMCM0
OPENOCD_TARGET = f0x
else
ifeq ($(DENSITY),hd)
MODEL_DEFINE = STM32F10X_HD
else ifeq ($(DENSITY),md)
MODEL_DEFINE = STM32F10X_MD
else
MODEL_DEFINE = STM32F10X_CL
endif
STARTUP_OBJ   = $(BUILD_DIR)startup_stm32f10x_$(DENSITY).o
LINKER_SCRIPT = stmlib/linker_scripts/stm32f10x_flash_$(DENSITY)$(LD_SUFFIX).ld
FW_STDDRIVER_DIR = $(STM32_PATH)/STM32F10x_StdPeriph_Driver
ARCHFLAGS = -mcpu=cortex-m3 -mthumb -fno-unroll-loops
ARCH_DEFINE = GCC_ARMCM3
OPENOCD_TARGET = f1x
endif
ifeq ($(APPLICATION),TRUE)
APPLICATION_DEFINE = -DAPPLICATION
LD_SUFFIX = _application
BASE_ADDRESS = 0x08004000
else ifeq ($(APPLICATION_SMALL),TRUE)
APPLICATION_DEFINE = -DAPPLICATION
LD_SUFFIX = _application_small
BASE_ADDRESS = 0x08001000
else ifeq ($(APPLICATION_LARGE),TRUE)
APPLICATION_DEFINE = -DAPPLICATION
LD_SUFFIX = _application_large
BASE_ADDRESS = 0x08008000
else
APPLICATION_DEFINE = -DNO_APPLICATION
LD_SUFFIX =
BASE_ADDRESS = 0x08000000
endif
OPENOCD_TARGET_SCRIPT ?= target/stm32$(OPENOCD_TARGET).cfg
# ------------------------------------------------------------------------------
# Flags for gcc/binutils
# ------------------------------------------------------------------------------
INCFLAGS = \
			-I. \
			-D$(ARCH_DEFINE) \
			-D$(MODEL_DEFINE) \
			$(APPLICATION_DEFINE) \
			$(PROJECT_CONFIGURATION) \
			-DF_CPU=$(F_CPU) \
			-DF_CRYSTAL=$(F_CRYSTAL) \
			-DUSE_STDPERIPH_DRIVER \
			-D$(SYSCLOCK)=$(F_CPU)
CCFLAGS = \
			-g -O2 -Wall -Werror -Wno-unused-local-typedefs \
			-fasm \
			-finline \
			-finline-functions-called-once \
			-fdata-sections \
			-ffunction-sections \
			-fshort-enums \
			-fno-move-loop-invariants \
			$(INCFLAGS) \
			$(ARCHFLAGS)
CPPFLAGS = -fno-exceptions -fno-rtti
ASFLAGS = $(ARCHFLAGS)
LDFLAGS = \
			-Wl,-Map=$(BUILD_DIR)$(TARGET).map \
			-Wl,--gc-sections \
			-T $(LINKER_SCRIPT) \
			$(ARCHFLAGS) \
			$(INCFLAGS) \
			-L$(STM32_PATH)
# ------------------------------------------------------------------------------
# Files and directories for the system firmware
# ------------------------------------------------------------------------------
FW_BUILD_DIR = $(BUILD_ROOT)stm_firmware/
FW_CORE_DIR = $(STM32_PATH)/CMSIS/CM3_$(FAMILY)
FW_STARTUP_DIR = $(FW_CORE_DIR)/startup/gcc
FW_STDDRIVER_SRCDIR = $(FW_STDDRIVER_DIR)/src
FW_STDDRIVER_INCDIR = $(FW_STDDRIVER_DIR)/inc
FW_USB_DIR = $(STM32_PATH)/STM32_USB-FS-Device_Driver
FW_USB_SRCDIR = $(FW_USB_DIR)/src
FW_USB_INCDIR = $(FW_USB_DIR)/inc
INCFLAGS += -I$(STM32_PATH) -I$(FW_CORE_DIR) -I$(FW_STARTUP_DIR) -I$(FW_STDDRIVER_INCDIR)
VPATH += $(FW_CORE_DIR) $(FW_STARTUP_DIR) $(FW_STDDRIVER_SRCDIR) $(STM32_PATH) $(FW_BUILD_DIR)
CORE_C_FILES = $(notdir $(wildcard $(patsubst %,%/*.c,$(FW_CORE_DIR))))
DRIVERS_C_FILES = $(notdir $(wildcard $(patsubst %,%/*.c,$(FW_STDDRIVER_SRCDIR))))
USB_C_FILES = $(notdir $(wildcard $(patsubst %,%/*.c,$(FW_USB_SRCDIR))))
C_FILES += $(CORE_C_FILES)
C_FILES += $(DRIVERS_C_FILES)
ifeq ($(USB),enabled)
INCFLAGS += -I$(FW_USB_INCDIR)
VPATH += $(FW_USB_SRCDIR)
C_FILES += $(USB_C_FILES)
endif
# ------------------------------------------------------------------------------
# Source compiling and dependency analysis
# ------------------------------------------------------------------------------
$(BUILD_DIR)%.o: %.s
	$(CC) -c -x assembler-with-cpp $(ASFLAGS) $< -o $@
$(BUILD_DIR)%.o: %.c
	$(CC) -c $(CCFLAGS) -std=c99 $< -o $@
$(BUILD_DIR)%.o: %.cc
	$(CXX) -c $(CCFLAGS) $(CPPFLAGS) $< -o $@
$(BUILD_DIR)%.d: %.s
	$(CC) -c -x assembler-with-cpp -MM $(ASFLAGS) $< -MF $@ -MT $(@:.d=.o)
$(BUILD_DIR)%.d: %.c
	$(CC) -MM $(CCFLAGS) $< -MF $@ -MT $(@:.d=.o)
$(BUILD_DIR)%.d: %.cc
	$(CXX) -MM $(CCFLAGS) $(CPPFLAGS) $< -MF $@ -MT $(@:.d=.o)
# ------------------------------------------------------------------------------
# Object file conversion
# ------------------------------------------------------------------------------
$(BUILD_DIR)%.hex: $(BUILD_DIR)%.elf
	$(OBJCOPY) -O ihex $< $@
$(BUILD_DIR)%.bin: $(BUILD_DIR)%.elf
	$(OBJCOPY) -O binary $< $@
$(BUILD_DIR)%.lss: $(BUILD_DIR)%.elf
	$(OBJDUMP) -d -h -S $< > $@
$(BUILD_DIR)%.sym: $(BUILD_DIR)%.elf
	$(NM) -n $< > $@
# ------------------------------------------------------------------------------
# What to build
# ------------------------------------------------------------------------------
OBJ_FILES      = $(CC_FILES:.cc=.o) $(C_FILES:.c=.o) $(AS_FILES:.s=.o)
OBJS           = $(patsubst %,$(BUILD_DIR)%,$(OBJ_FILES)) $(STARTUP_OBJ)
DEPS           = $(OBJS:.o=.d)
all: $(BUILD_DIR) $(TARGET_HEX)
# ------------------------------------------------------------------------------
# Resources
# ------------------------------------------------------------------------------
RESOURCE_COMPILER = stmlib/tools/resources_compiler.py
resources: $(TARGET)/resources.cc
$(TARGET)/resources.cc: $(wildcard $(RESOURCES)/*.py)
		python $(RESOURCE_COMPILER) $(RESOURCES)/resources.py
# ------------------------------------------------------------------------------
# Main rules
# ------------------------------------------------------------------------------
$(BUILD_DIR):
	mkdir -p $(BUILD_DIR)
$(TARGET_ELF): $(OBJS)
	$(CC) $(LDFLAGS) -o $(TARGET_ELF) $(OBJS)
$(DEP_FILE): $(BUILD_DIR) $(DEPS)
	cat $(DEPS) > $(DEP_FILE)
bin: $(TARGET_BIN)
hex: $(TARGET_HEX)
clean:
	$(REMOVE) $(OBJS) $(TARGETS) $(DEP_FILE) $(DEPS)
depends: $(DEPS)
	cat $(DEPS) > $(DEP_FILE)
$(TARGET_SIZE): $(TARGET_ELF)
	$(SIZE) $(TARGET_ELF) > $(TARGET_SIZE)
$(BUILD_DIR)$(TARGET).top_symbols: $(TARGET_ELF)
	$(NM) $(TARGET_ELF) --size-sort -C -f bsd -r > $@
size: $(TARGET_SIZE)
	cat $(TARGET_SIZE) | awk '{ print $$1+$$2 }' | tail -n1 $(FORMAT_SIZE)
ramsize: $(TARGET_SIZE)
	cat $(TARGET_SIZE) | awk '{ print $$2+$$3 }' | tail -n1 $(FORMAT_RAMSIZE)
disassemble: build/$(TARGET)/$(TARGET).lss build/$(TARGET)/$(TARGET).top_symbols
.PHONY: all bin clean depends resources
include $(DEP_FILE)
# ------------------------------------------------------------------------------
# Bootloader merging
# ------------------------------------------------------------------------------
$(COMBO_BIN): $(TARGET_HEX) $(BOOTLOADER_HEX)
	cat	$(TARGET_HEX) $(BOOTLOADER_HEX) | \
			awk -f stmlib/programming/merge_hex.awk > $(COMBO_HEX)
	$(OBJCOPY) -I ihex -O binary $(COMBO_HEX) $(COMBO_BIN)
# ------------------------------------------------------------------------------
# Firmware flashing
# ------------------------------------------------------------------------------
BASE_JTAG_CMD = openocd \
			-f $(OPENOCD_INTERFACE_SCRIPT) \
			-f $(OPENOCD_TARGET_SCRIPT) \
			-c "init" -c "halt" -c "sleep 200"
POSTLUDE = -c "sleep 200" -c "reset run" -c "shutdown"
upload: $(UPLOAD_COMMAND)
image_serial:
	python $(STM32LOADER_PATH)stm32loader.py \
		-p $(PGM_SERIAL_PORT) \
		-b $(PGM_SERIAL_BAUD_RATE) \
		-r -l 131072 image.bin
upload_serial: $(TARGET_BIN)
	python $(STM32LOADER_PATH)stm32loader.py \
		-p $(PGM_SERIAL_PORT) \
		-b $(PGM_SERIAL_BAUD_RATE) \
		-e $(PGM_SERIAL_VERIFY) \
		-a $(BASE_ADDRESS) \
		-w $(TARGET_BIN)
upload_serial_no_erase: $(TARGET_BIN)
	python $(STM32LOADER_PATH)stm32loader.py \
		-p $(PGM_SERIAL_PORT) \
		-b $(PGM_SERIAL_BAUD_RATE) $(PGM_SERIAL_VERIFY)\
		-a $(BASE_ADDRESS) \
		-w $(TARGET_BIN)
upload_combo_serial: $(COMBO_BIN)
	python $(STM32LOADER_PATH)stm32loader.py \
		-p $(PGM_SERIAL_PORT) \
		-b $(PGM_SERIAL_BAUD_RATE) \
		-e $(PGM_SERIAL_VERIFY) \
		-w $(COMBO_BIN)
upload_combo_serial_no_erase: $(COMBO_BIN)
	python $(STM32LOADER_PATH)stm32loader.py \
		-p $(PGM_SERIAL_PORT) \
		-b $(PGM_SERIAL_BAUD_RATE) $(PGM_SERIAL_VERIFY)\
		-w $(COMBO_BIN)
image_jtag:
	$(BASE_JTAG_CMD) \
		-c "dump_image image.bin 0x08000000 131072" \
		$(POSTLUDE)
image_jtag_256k:
	$(BASE_JTAG_CMD) \
		-c "dump_image image.bin 0x08000000 262144" \
		$(POSTLUDE)
image_jtag_1M:
	$(BASE_JTAG_CMD) \
		-c "dump_image image.bin 0x08000000 1048576" \
		$(POSTLUDE)
debug_server: $(TARGET_BIN)
	openocd \
		-f $(OPENOCD_INTERFACE_SCRIPT) \
		-f $(OPENOCD_TARGET_SCRIPT) \
		-c "init" \
		-c "reset" \
		-c "halt"
debug_client:
	$(DB) --eval-command="target remote localhost:3333" $(TARGET_ELF)
erase_jtag:
	$(BASE_JTAG_CMD) \
        -c "stm32f4x unlock 0" \
				-f $(OPENOCD_SCRIPTS_PATH)erase_$(FAMILY).cfg \
				$(POSTLUDE)
upload_jtag: $(TARGET_BIN)
	$(BASE_JTAG_CMD) \
				-f $(OPENOCD_SCRIPTS_PATH)erase_$(FAMILY).cfg \
				-c "flash write_bank 0 $(TARGET_BIN) 0x0" \
				-c "verify_image $(TARGET_BIN)" \
				$(POSTLUDE)
upload_combo_jtag: $(COMBO_BIN)
	$(BASE_JTAG_CMD) \
				-f $(OPENOCD_SCRIPTS_PATH)erase_$(FAMILY).cfg \
				-c "flash write_bank 0 $(COMBO_BIN) 0x0" \
				-c "verify_image $(COMBO_BIN)" \
				$(POSTLUDE)
upload_jtag_no_erase: $(TARGET_BIN)
	$(BASE_JTAG_CMD) \
				-c "flash write_image erase $(TARGET_BIN) 0x08000000" \
				-c "verify_image $(TARGET_BIN)" \
				$(POSTLUDE)
upload_combo_jtag_no_erase: $(COMBO_BIN)
	$(BASE_JTAG_CMD) \
				-c "flash write_image erase $(COMBO_BIN) 0x08000000" \
				-c "verify_image $(COMBO_BIN)" \
				$(POSTLUDE)
upload_jtag_erase_first: $(TARGET_BIN)
	$(BASE_JTAG_CMD) \
				-c "flash erase_address 0x08000000 32768" \
				-c "reset halt" \
				-c "flash write_image erase $(TARGET_BIN) 0x08000000" \
				-c "verify_image $(TARGET_BIN)" \
				$(POSTLUDE)
upload_combo_jtag_erase_first: $(COMBO_BIN)
	$(BASE_JTAG_CMD) \
				-c "flash erase_address 0x08000000 32768" \
				-c "reset halt" \
				-c "flash write_image erase $(COMBO_BIN) 0x08000000" \
				-c "verify_image $(COMBO_BIN)" \
				$(POSTLUDE)
# Phony target for killing the system FTDI driver on OS X.
kill_ftdi:
	sudo kextunload -b com.FTDI.driver.FTDIUSBSerialDriver
reload_ftdi:
	sudo kextload -b com.FTDI.driver.FTDIUSBSerialDriver
.PHONY: upload
.PHONY: image_serial
.PHONY: upload_serial upload_serial_no_erase
.PHONY: upload_combo_serial upload_combo_serial_no_erase
.PHONY: image_jtag image_jtag_1M
.PHONY: erase_jtag
.PHONY: upload_jtag upload_jtag_no_erase upload_jtag_erase_first
.PHONY: upload_combo_jtag upload_combo_jtag_no_erase upload_combo_jtag_erase_first
.PHONY: kill_ftdi reload_ftdi
.PHONY: debug_client debug_server
 |