stm32f1/Makefile

228 lines
8.5 KiB
Makefile

## This library is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This library is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this library. If not, see <http://www.gnu.org/licenses/>.
##
## the make file provide rule to compile and flash firmware for STM32F1 micro-controllers
## it uses libopencm3
# be silent per default, but 'make V=1' will show all compiler calls.
ifneq ($(V),1)
Q := @
NULL := 1> /dev/null 2> /dev/null
endif
# main names (without extension, for input source file and output binary)
APPLICATION = application
BOOTLOADER = bootloader
FIRMWARE = $(APPLICATION) $(BOOTLOADER)
# which development board is used
# supported are: SYSTEM_BOARD, MAPLE_MINI, BLUE_PILL, CORE_BOARD
BOARD = CORE_BOARD
# opencm3 libraries
OPENCM3_DIR := libopencm3
OPENCM3_INC = $(OPENCM3_DIR)/include
OPENCM3_LIB = $(OPENCM3_DIR)/lib
# library for the STM32F1 (provided by opencm3)
STM32F1_LIB = opencm3_stm32f1
# libraries with source code used (also to be compiled)
SRCLIBS = . lib
# source files (this will be populated using includes based DEPENDENCIES)
CSRC =
# headers (unique, and if existing) corresponding to source files
CHDR = $(sort $(patsubst %.c,%.h,$(wildcard $(CSRC))))
# objects (unique, and if existing) compiled from source files
OBJ = $(sort $(patsubst %.c,%.o,$(wildcard $(CSRC))))
# figure out based on the main sources files which library files are used
DEPENDENCIES = $(patsubst %,%.inc,$(FIRMWARE))
# populates CSRC based on the library files used
-include $(DEPENDENCIES)
# executables for linking, compiling, debugging, ...
# use clang to compile, GNU ARM toolchain for the rest
PREFIX ?= arm-none-eabi
# use ELLCC as compile
CC := clang -target $(PREFIX)
LD := $(PREFIX)-ld
LD := $(PREFIX)-ld
AR := $(PREFIX)-ar
AS := $(PREFIX)-as
OBJCOPY := $(PREFIX)-objcopy
OBJDUMP := $(PREFIX)-objdump
GDB := $(PREFIX)-gdb
# device micro-controller and board
DEFS += -DSTM32F1 -D$(BOARD)
# C flags
# optimize for size
CFLAGS += -Os
# add debug symbols (remove for smaller release)
CFLAGS += -ggdb
# use C99 (supported by most an sufficient)
CFLAGS += -std=c99
# have strict warning (for better code)
CFLAGS += -Wpedantic -Wall -Werror -Wundef -Wextra -Wshadow -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes -Wstrict-overflow=5
# add options for better code optimization
CFLAGS += -fno-common -ffunction-sections -fdata-sections
# use variable size enum (clang doesn't but opencm3, and gcc do)
CFLAGS += -fshort-enums
# use no variable size enum (ELLCC/musl does not)
#CFLAGS += -fno-short-enums
# don't use system main definition (the starting point)
CFLAGS += -ffreestanding
# don't use the standard library (only if you provide an alternative libc library)
#CFLAGS += -nostdlib -nostdinc
# include own libraries
CFLAGS += $(foreach lib,$(SRCLIBS),-I $(lib))
# include opencm3 libraries
CFLAGS += -I $(OPENCM3_INC)
# add defines for micro-controller and board
CFLAGS += $(DEFS)
# linker flags
# build static binary (no shared libraries on the micro-controller)
LDFLAGS += -static
# don's include the system start files
LDFLAGS += -nostartfiles
# only keep used sections
LDFLAGS += --gc-sections
# don't use system libraries (only if you provide an alternative libc library)
#LDFLAGS += -nostdlib -nostdinc
# add standard libraries (for libc, libm, libnosys, libgcc)
LDFLAGS += --library-path /usr/arm-none-eabi/lib/armv7-m/
LDFLAGS += --library-path /usr/lib/gcc/arm-none-eabi/*/armv7-m/
# opencm3 libraries
LDFLAGS += --library-path $(OPENCM3_LIB)
# used libraries (gcc provides the ARM ABI)
LDLIBS += --library $(STM32F1_LIB) --library c --library m --library nosys --library gcc
# target micro-controller information (ARM Cortex-M3 supports thumb and thumb2, but does not include a floating point unit)
ARCH_FLAGS = -mthumb -mcpu=cortex-m3 -msoft-float
# SWD adapter used
# supported are : st-link v2 (STLINKV2), black magic probe (BMP)
SWD_ADAPTER ?= BMP
ifeq ($(SWD_ADAPTER),STLINKV2)
# OpenOCD configuration
OOCD ?= openocd
OOCD_INTERFACE ?= stlink-v2
OOCD_TARGET ?= stm32f1x
else ifeq ($(SWD_ADAPTER),BMP)
# the black magic probe has a SWD controller built in
BMP_PORT ?= /dev/ttyACM0
endif
# compile target rules
all: elf hex bin
elf: $(patsubst %,%.elf,$(FIRMWARE))
bin: $(patsubst %,%.bin,$(FIRMWARE))
hex: $(patsubst %,%.hex,$(FIRMWARE))
%.hex: %.elf
$(Q)$(OBJCOPY) --strip-all --strip-debug --output-target ihex $(<) $(@)
%.bin: %.elf
$(Q)$(OBJCOPY) --strip-all --strip-debug --output-target binary $(<) $(@)
%.map %.list: %.elf
$(Q)$(OBJDUMP) -S $(<) > $(@)
%.elf: %.o %.ld $(OBJ) $(OPENCM3_LIB)/lib$(STM32F1_LIB).a
$(info linking $(@))
$(Q)$(LD) $(LDFLAGS) --script $(*).ld $(<) $(OBJ) $(LDLIBS) -o $(@)
$(Q)size $(@)
%.o: %.c $(CHDR) $(OPENCM3_LIB)/lib$(STM32F1_LIB).a
$(info compiling $(@))
$(Q)$(CC) $(CFLAGS) $(ARCH_FLAGS) -o $(@) -c $(<)
# find out which library source files also need to be compiled and linked, based on its dependencies
%.inc: %.c $(OPENCM3_LIB)/lib$(STM32F1_LIB).a
$(Q)echo "" > $(@)
$(Q)for dependency in $(shell $(CC) $(CFLAGS) $(ARCH_FLAGS) -MM -c $(<)); do \
if [ -f "$${dependency}" ]; then \
for lib in $(SRCLIBS); do \
if [ `dirname "$${dependency}"` = "$${lib}" ]; then \
if [ -f `echo "$${dependency}" | sed -e 's|\(.*\)\.h$$|\1.c|'` ]; then \
echo "$${dependency}" | sed -e 's|\(.*\)\.h$$|CSRC += \1.c\n-include \1.inc|g' -e 's|.*${*}.*||g' >> $(@); \
fi; \
fi; \
done; \
fi; \
done
# get libopencm3
$(OPENCM3_DIR)/Makefile:
$(info checking out libopencm3 submodule)
$(Q)git submodule init
$(Q)git submodule update
# compile libopencm3
$(OPENCM3_LIB)/lib$(STM32F1_LIB).a: $(OPENCM3_DIR)/Makefile
$(info compiling libopencm3 submodule)
$(Q)$(MAKE) --directory $(OPENCM3_DIR)
# doxygen documentation
doc: Doxyfile README.md $(patsubst %,%.c,$(FIRMWARE)) $(CSRC) $(CHDR)
$(Q)doxygen $(<)
clean:
$(Q)$(RM) $(BOOTLOADER).elf $(BOOTLOADER).bin $(BOOTLOADER).hex $(APPLICATION).elf $(APPLICATION).bin $(APPLICATION).hex $(OBJ) $(DEPENDENCIES) *.inc lib/*.inc
# flash application using DFU
flash: $(APPLICATION).bin
$(Q)dfu-util -d c440:0d00 -D $(<)
# flash bootloader using SWD
flash_bootloader: $(BOOTLOADER).hex
$(info flashing $(<) using SWD)
ifeq ($(SWD_ADAPTER),STLINKV2)
$(Q)$(OOCD) --file interface/$(OOCD_INTERFACE).cfg --file target/$(OOCD_TARGET).cfg --command "init" --command "reset init" --command "flash write_image erase $(<)" --command "reset" --command "shutdown" $(NULL)
else ifeq ($(SWD_ADAPTER),BMP)
$(Q)$(GDB) --eval-command="target extended-remote $(BMP_PORT)" --eval-command="set confirm off" --eval-command="monitor swdp_scan" --eval-command="attach 1" --eval-command="load" --eval-command="detach" --eval-command="quit" $(<)
endif
# flash application using SWD
flash_application: $(APPLICATION).hex
$(info flashing $(<) using SWD)
ifeq ($(SWD_ADAPTER),STLINKV2)
$(Q)$(OOCD) --file interface/$(OOCD_INTERFACE).cfg --file target/$(OOCD_TARGET).cfg --command "init" --command "reset init" --command "flash write_image erase $(<)" --command "reset" --command "shutdown" $(NULL)
else ifeq ($(SWD_ADAPTER),BMP)
$(Q)$(GDB) --eval-command="target extended-remote $(BMP_PORT)" --eval-command="set confirm off" --eval-command="monitor swdp_scan" --eval-command="attach 1" --eval-command="load" --eval-command="kill" --eval-command="quit" $(<)
endif
# reset device by setting the data width to 5 bis on the USB CDC ACM port
ifeq ($(SWD_ADAPTER)$(BMP_PORT),BMP/dev/ttyACM0)
ACM_PORT := /dev/ttyACM2
else
ACM_PORT := /dev/ttyACM0
endif
reset:
$(Q)stty --file $(ACM_PORT) raw cs5
$(Q)sleep 0.5
# debug application using GDB
debug: $(APPLICATION).elf
ifeq ($(SWD_ADAPTER),STLINKV2)
# for GDB to work with openOCD the firmware needs to be reloaded
$(Q)$(GDB) --eval-command="target remote | $(OOCD) --file interface/$(OOCD_INTERFACE).cfg --file target/$(OOCD_TARGET).cfg --command \"gdb_port pipe; log_output /dev/null; init\"" --eval-command="monitor reset halt" --eval-command="load" --eval-command="monitor reset init" $(<)
else ifeq ($(SWD_ADAPTER),BMP)
$(Q)$(GDB) --eval-command="target extended-remote $(BMP_PORT)" --eval-command="monitor version" --eval-command="monitor swdp_scan" --eval-command="attach 1" $(<)
endif
.PHONY: clean elf bin hex srec list flash reset