# Select the board to build for: if not given on the command line, # then default to PYBV10. BOARD ?= PYBV10 ifeq ($(wildcard boards/$(BOARD)/.),) $(error Invalid BOARD specified) endif # If the build directory is not given, make it reflect the board name. BUILD ?= build-$(BOARD) include ../py/mkenv.mk -include mpconfigport.mk include boards/$(BOARD)/mpconfigboard.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h $(BUILD)/modstm_qstr.h # include py core make definitions include ../py/py.mk CMSIS_DIR=cmsis HAL_DIR=hal/$(MCU_SERIES) USBDEV_DIR=usbdev #USBHOST_DIR=usbhost FATFS_DIR=lib/fatfs DFU=../tools/dfu.py # may need to prefix dfu-util with sudo USE_PYDFU ?= 1 PYDFU ?= ../tools/pydfu.py DFU_UTIL ?= dfu-util DEVICE=0483:df11 STFLASH ?= st-flash OPENOCD ?= openocd OPENOCD_CONFIG ?= boards/openocd_stm32f4.cfg CROSS_COMPILE = arm-none-eabi- INC += -I. INC += -I.. INC += -I$(BUILD) INC += -I$(CMSIS_DIR)/inc INC += -I$(CMSIS_DIR)/devinc INC += -I$(HAL_DIR)/inc INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc #INC += -I$(USBHOST_DIR) INC += -I../lib/mp-readline INC += -I../lib/netutils INC += -I../lib/timeutils CFLAGS_CORTEX_M = -mthumb -mabi=aapcs-linux -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion CFLAGS_MCU_f4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -DMCU_SERIES_F4 CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 -DMCU_SERIES_F7 CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -DMCU_SERIES_L4 CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_MOD) CFLAGS += -D$(CMSIS_MCU) CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) CFLAGS += $(COPT) CFLAGS += -Iboards/$(BOARD) CFLAGS += -DSTM32_HAL_H='' LDFLAGS = -nostdlib -T $(LD_FILE) -Map=$(@:.elf=.map) --cref LIBS = # Remove uncalled code from the final image. CFLAGS += -fdata-sections -ffunction-sections LDFLAGS += --gc-sections # Debugging/Optimization ifeq ($(DEBUG), 1) CFLAGS += -g -DPENDSV_DEBUG COPT = -O0 else COPT += -Os -DNDEBUG endif # uncomment this if you want libgcc #LIBS += $(shell $(CC) -print-libgcc-file-name) SRC_LIB = $(addprefix lib/,\ libc/string0.c \ libm/math.c \ libm/asinfacosf.c \ libm/atanf.c \ libm/atan2f.c \ libm/fmodf.c \ libm/roundf.c \ libm/log1pf.c \ libm/acoshf.c \ libm/asinhf.c \ libm/atanhf.c \ libm/kf_rem_pio2.c \ libm/kf_sin.c \ libm/kf_cos.c \ libm/kf_tan.c \ libm/ef_rem_pio2.c \ libm/erf_lgamma.c \ libm/sf_sin.c \ libm/sf_cos.c \ libm/sf_tan.c \ libm/sf_frexp.c \ libm/sf_modf.c \ libm/sf_ldexp.c \ libm/sf_erf.c \ libm/wf_lgamma.c \ libm/wf_tgamma.c \ fatfs/ff.c \ fatfs/option/ccsbcs.c \ mp-readline/readline.c \ netutils/netutils.c \ timeutils/timeutils.c \ utils/pyexec.c \ utils/pyhelp.c \ ) SRC_C = \ main.c \ system_stm32.c \ stm32_it.c \ usbd_conf.c \ usbd_desc.c \ usbd_cdc_interface.c \ usbd_msc_storage.c \ mphalport.c \ irq.c \ pendsv.c \ systick.c \ timer.c \ led.c \ pin.c \ pin_defs_stmhal.c \ pin_named_pins.c \ bufhelper.c \ dma.c \ i2c.c \ spi.c \ uart.c \ can.c \ usb.c \ wdt.c \ gccollect.c \ pybstdio.c \ help.c \ input.c \ modmachine.c \ modpyb.c \ modstm.c \ moduos.c \ modutime.c \ moduselect.c \ modusocket.c \ modnetwork.c \ import.c \ lexerfatfs.c \ extint.c \ usrsw.c \ rng.c \ rtc.c \ flash.c \ storage.c \ builtin_open.c \ sdcard.c \ fatfs_port.c \ lcd.c \ accel.c \ servo.c \ dac.c \ adc.c \ $(wildcard boards/$(BOARD)/*.c) SRC_O = \ startup_stm32.o \ gchelper.o \ SRC_HAL = $(addprefix $(HAL_DIR)/src/stm32$(MCU_SERIES)xx_,\ hal.c \ hal_adc.c \ hal_adc_ex.c \ hal_can.c \ hal_cortex.c \ hal_dac.c \ hal_dac_ex.c \ hal_dma.c \ hal_flash.c \ hal_flash_ex.c \ hal_gpio.c \ hal_i2c.c \ hal_pcd.c \ hal_pcd_ex.c \ hal_pwr.c \ hal_pwr_ex.c \ hal_rcc.c \ hal_rcc_ex.c \ hal_rng.c \ hal_rtc.c \ hal_rtc_ex.c \ hal_sd.c \ hal_spi.c \ hal_tim.c \ hal_tim_ex.c \ hal_uart.c \ ll_sdmmc.c \ ll_usb.c \ ) SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\ core/src/usbd_core.c \ core/src/usbd_ctlreq.c \ core/src/usbd_ioreq.c \ class/src/usbd_cdc_msc_hid.c \ class/src/usbd_msc_bot.c \ class/src/usbd_msc_scsi.c \ class/src/usbd_msc_data.c \ ) ifeq ($(MICROPY_PY_WIZNET5K),1) WIZNET5K_DIR=drivers/wiznet5k INC += -I$(TOP)/$(WIZNET5K_DIR) CFLAGS_MOD += -DMICROPY_PY_WIZNET5K=1 SRC_MOD += modnwwiznet5k.c SRC_MOD += $(addprefix $(WIZNET5K_DIR)/,\ ethernet/w5200/w5200.c \ ethernet/wizchip_conf.c \ ethernet/socket.c \ internet/dns/dns.c \ ) endif # for CC3000 module ifeq ($(MICROPY_PY_CC3K),1) CC3000_DIR=drivers/cc3000 INC += -I$(TOP)/$(CC3000_DIR)/inc CFLAGS_MOD += -DMICROPY_PY_CC3K=1 SRC_MOD += modnwcc3k.c SRC_MOD += $(addprefix $(CC3000_DIR)/src/,\ cc3000_common.c \ evnt_handler.c \ hci.c \ netapp.c \ nvmem.c \ security.c \ socket.c \ wlan.c \ ccspi.c \ inet_ntop.c \ inet_pton.c \ patch.c \ patch_prog.c \ ) endif OBJ = OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_O)) OBJ += $(addprefix $(BUILD)/, $(SRC_HAL:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_USBDEV:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(BUILD)/pins_$(BOARD).o # We put ff.o and stm32f4xx_hal_sd.o into the first 16K section with the ISRs. # If we compile these using -O0 then it won't fit. So if you really want these # to be compiled with -O0, then edit stm32f405.ld (in the .isr_vector section) # and comment out the following 2 lines. $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os $(BUILD)/$(HAL_DIR)/src/stm32$(MCU_SERIES)xx_hal_sd.o: COPT += -Os all: $(BUILD)/firmware.dfu $(BUILD)/firmware.hex ifneq ($(FROZEN_DIR),) CFLAGS += -DMICROPY_MODULE_FROZEN_STR OBJ += $(BUILD)/frozen-files.o MAKE_FROZEN = ../tools/make-frozen.py $(BUILD)/frozen-files.o: $(BUILD)/frozen-files.c $(call compile_c) $(BUILD)/frozen-files.c: $(shell find $(FROZEN_DIR) -type f) @$(ECHO) "Creating $@" $(Q)$(PYTHON) $(MAKE_FROZEN) $(FROZEN_DIR) > $@ endif ifneq ($(FROZEN_MPY_DIR),) # To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and # then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py') FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool CFLAGS += -DMICROPY_MODULE_FROZEN_MPY OBJ += $(BUILD)/$(BUILD)/frozen_mpy.o MPY_CROSS = ../mpy-cross/mpy-cross MPY_TOOL = ../tools/mpy-tool.py $(BUILD)/$(FROZEN_MPY_DIR)/%.mpy: $(FROZEN_MPY_DIR)/%.py @$(ECHO) "MPY $<" $(Q)$(MKDIR) -p $(dir $@) $(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $^ $(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h @$(ECHO) "Creating $@" $(Q)$(PYTHON) $(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h $(FROZEN_MPY_MPY_FILES) > $@ endif .PHONY: deploy deploy: $(BUILD)/firmware.dfu $(ECHO) "Writing $< to the board" ifeq ($(USE_PYDFU),1) $(Q)$(PYTHON) $(PYDFU) -u $< else $(Q)$(DFU_UTIL) -a 0 -d $(DEVICE) -D $< endif deploy-stlink: $(BUILD)/firmware.dfu $(ECHO) "Writing $(BUILD)/firmware0.bin to the board via ST-LINK" $(Q)$(STFLASH) write $(BUILD)/firmware0.bin 0x08000000 $(ECHO) "Writing $(BUILD)/firmware1.bin to the board via ST-LINK" $(Q)$(STFLASH) --reset write $(BUILD)/firmware1.bin 0x08020000 deploy-openocd: $(BUILD)/firmware.dfu $(ECHO) "Writing $(BUILD)/firmware{0,1}.bin to the board via ST-LINK using OpenOCD" $(Q)$(OPENOCD) -f $(OPENOCD_CONFIG) -c "stm_flash $(BUILD)/firmware0.bin $(BUILD)/firmware1.bin" $(BUILD)/firmware.dfu: $(BUILD)/firmware.elf $(ECHO) "Create $@" $(Q)$(OBJCOPY) -O binary -j .isr_vector $^ $(BUILD)/firmware0.bin $(Q)$(OBJCOPY) -O binary -j .text -j .data $^ $(BUILD)/firmware1.bin $(Q)$(PYTHON) $(DFU) -b 0x08000000:$(BUILD)/firmware0.bin -b 0x08020000:$(BUILD)/firmware1.bin $@ $(BUILD)/firmware.hex: $(BUILD)/firmware.elf $(ECHO) "Create $@" $(Q)$(OBJCOPY) -O ihex $< $@ $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ MAKE_PINS = boards/make-pins.py BOARD_PINS = boards/$(BOARD)/pins.csv PREFIX_FILE = boards/stm32f4xx_prefix.c GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c GEN_PINS_HDR = $(HEADER_BUILD)/pins.h GEN_PINS_QSTR = $(BUILD)/pins_qstr.h GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h GEN_PINS_AF_PY = $(BUILD)/pins_af.py INSERT_USB_IDS = ../tools/insert-usb-ids.py FILE2H = ../tools/file2h.py USB_IDS_FILE = usb.h CDCINF_TEMPLATE = pybcdc.inf_template GEN_CDCINF_FILE = $(HEADER_BUILD)/pybcdc.inf GEN_CDCINF_HEADER = $(HEADER_BUILD)/pybcdc_inf.h # List of sources for qstr extraction SRC_QSTR += $(SRC_C) $(SRC_MOD) $(SRC_LIB) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += $(GEN_CDCINF_HEADER) # Making OBJ use an order-only depenedency on the generated pins.h file # has the side effect of making the pins.h file before we actually compile # any of the objects. The normal dependency generation will deal with the # case when pins.h is modified. But when it doesn't exist, we don't know # which source files might need it. $(OBJ): | $(HEADER_BUILD)/pins.h # With conditional pins, we may need to regenerate qstrdefs.h when config # options change. $(HEADER_BUILD)/qstrdefs.generated.h: boards/$(BOARD)/mpconfigboard.h # main.c can't be even preprocessed without $(GEN_CDCINF_HEADER) main.c: $(GEN_CDCINF_HEADER) # Use a pattern rule here so that make will only call make-pins.py once to make # both pins_$(BOARD).c and pins.h $(BUILD)/%_$(BOARD).c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(BUILD)/%_qstr.h: boards/$(BOARD)/%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD) $(ECHO) "Create $@" $(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) --af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC) $(BUILD)/pins_$(BOARD).o: $(BUILD)/pins_$(BOARD).c $(call compile_c) GEN_STMCONST_HDR = $(HEADER_BUILD)/modstm_const.h GEN_STMCONST_QSTR = $(BUILD)/modstm_qstr.h GEN_STMCONST_MPZ = $(HEADER_BUILD)/modstm_mpz.h CMSIS_MCU_LOWER = $(shell echo $(CMSIS_MCU) | tr '[:upper:]' '[:lower:]') CMSIS_MCU_HDR = cmsis/devinc/$(CMSIS_MCU_LOWER).h $(BUILD)/modstm.o: $(GEN_STMCONST_HDR) # Use a pattern rule here so that make will only call make-stmconst.py once to # make both modstm_const.h and modstm_qstr.h $(HEADER_BUILD)/%_const.h $(BUILD)/%_qstr.h: $(CMSIS_MCU_HDR) make-stmconst.py | $(HEADER_BUILD) $(ECHO) "Create stmconst $@" $(Q)$(PYTHON) make-stmconst.py --qstr $(GEN_STMCONST_QSTR) --mpz $(GEN_STMCONST_MPZ) $(CMSIS_MCU_HDR) > $(GEN_STMCONST_HDR) $(GEN_CDCINF_HEADER): $(GEN_CDCINF_FILE) $(FILE2H) | $(HEADER_BUILD) $(ECHO) "Create $@" $(Q)$(PYTHON) $(FILE2H) $< > $@ $(GEN_CDCINF_FILE): $(CDCINF_TEMPLATE) $(INSERT_USB_IDS) $(USB_IDS_FILE) | $(HEADER_BUILD) $(ECHO) "Create $@" $(Q)$(PYTHON) $(INSERT_USB_IDS) $(USB_IDS_FILE) $< > $@ include ../py/mkrules.mk