From 176e287791540e67ea2e0052e90c3ded1ed2482a Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 17 Aug 2021 09:50:13 -0400 Subject: [PATCH] improve reboot timer with safe_reboot flag; add support for leveraging a program for periodic reboot: a program with name :>reboot will trigger a reboot while controller is idle (i.e. no program running); a program with name :>reboot_now will trigger a reboot right away. Both reboot actions will be delayed by 1 minute from the program start time to avoid it running again right after reboot --- main.cpp | 32 +- makeEspArduino.mk | 740 ++++++++++++++++++--------------------- makeEspArduino.mk.old | 617 ++++++++++++++++++++++++++++++++ opensprinkler_server.cpp | 5 +- 4 files changed, 985 insertions(+), 409 deletions(-) create mode 100644 makeEspArduino.mk.old diff --git a/main.cpp b/main.cpp index 668a2e21..0dcf7fe3 100644 --- a/main.cpp +++ b/main.cpp @@ -80,7 +80,7 @@ ulong flow_count = 0; byte prev_flow_state = HIGH; float flow_last_gpm=0; -unsigned long reboot_timer = 0; +uint32_t reboot_timer = 0; void flow_poll() { #if defined(ESP8266) @@ -386,7 +386,7 @@ void turn_off_station(byte sid, ulong curr_time); void process_dynamic_events(ulong curr_time); void check_network(); void check_weather(); -bool process_special_program_command(const char*); +bool process_special_program_command(const char*, uint32_t curr_time); void perform_ntp_sync(); void delete_log(char *name); @@ -644,11 +644,7 @@ void do_loop() last_time = curr_time; if (os.button_timeout) os.button_timeout--; - - if(reboot_timer && millis() > reboot_timer) { - os.reboot_dev(REBOOT_CAUSE_TIMER); - } - + #if defined(ARDUINO) if (!ui_state) os.lcd_print_time(os.now_tz()); // print time @@ -734,7 +730,7 @@ void do_loop() if(prog.check_match(curr_time)) { // program match found // check and process special program command - if(process_special_program_command(prog.name)) continue; + if(process_special_program_command(prog.name, curr_time)) continue; // process all selected stations for(sid=0;sid reboot_timer)) { // if no program is running at the moment if (!os.status.program_busy) { // and if no program is scheduled to run in the next minute @@ -988,8 +987,9 @@ void do_loop() os.reboot_dev(os.nvdata.reboot_cause); } } + } else if(reboot_timer && (curr_time > reboot_timer)) { + os.reboot_dev(REBOOT_CAUSE_TIMER); } -#endif // real-time flow count static ulong flowcount_rt_start = 0; @@ -1037,10 +1037,16 @@ void do_loop() } /** Check and process special program command */ -bool process_special_program_command(const char* pname) { +bool process_special_program_command(const char* pname, uint32_t curr_time) { if(pname[0]==':') { // special command start with : - if(strncmp(pname, ":>reboot", 8) == 0) { - reboot_timer = millis()+90000; // set a timer to reboot in 90 seconds + if(strncmp(pname, ":>reboot_now", 12) == 0) { + os.status.safe_reboot = 0; // reboot regardless of program status + reboot_timer = curr_time + 65; // set a timer to reboot in 65 seconds + // this is to avoid the same command being executed again right after reboot + return true; + } else if(strncmp(pname, ":>reboot", 8) == 0) { + os.status.safe_reboot = 1; // by default reboot should only happen when controller is idle + reboot_timer = curr_time + 65; // set a timer to reboot in 65 seconds // this is to avoid the same command being executed again right after reboot return true; } diff --git a/makeEspArduino.mk b/makeEspArduino.mk index b09091e9..c494e603 100644 --- a/makeEspArduino.mk +++ b/makeEspArduino.mk @@ -7,35 +7,54 @@ # General and full license information is available at: # https://github.com/plerup/makeEspArduino # -# Copyright (c) 2016-2018 Peter Lerup. All rights reserved. +# Copyright (c) 2016-2021 Peter Lerup. All rights reserved. # #==================================================================================== -#==================================================================================== -# Project specific values -#==================================================================================== +START_TIME := $(shell date +%s) +__THIS_FILE := $(abspath $(lastword $(MAKEFILE_LIST))) +__TOOLS_DIR := $(dir $(__THIS_FILE))tools +OS ?= $(shell uname -s) + +# Include possible operating system specfic settings +-include $(dir $(__THIS_FILE))/os/$(OS).mk -# Include possible project makefile. This can be used to override the defaults below +# Include possible global user settings +CONFIG_ROOT ?= $(if $(XDG_CONFIG_HOME),$(XDG_CONFIG_HOME),$(HOME)/.config) +-include $(CONFIG_ROOT)/makeEspArduino/config.mk + +# Include possible project specific settings -include $(firstword $(PROJ_CONF) $(dir $(SKETCH))config.mk) -#=== Default values not available in the Arduino configuration files +# Build threads, default is using all the PC cpus +BUILD_THREADS ?= $(shell nproc) +MAKEFLAGS += -j $(BUILD_THREADS) -CHIP ?= esp8266 +# Build verbosity, silent by default +ifndef VERBOSE + MAKEFLAGS += --silent +endif -# Set chip specific default board unless specified -BOARD ?= $(if $(filter $(CHIP), esp32),esp32,generic) +# ESP chip family type +CHIP ?= esp8266 +UC_CHIP := $(shell perl -e "print uc $(CHIP)") +IS_ESP32 := $(if $(filter-out esp32,$(CHIP)),,1) # Serial flashing parameters -UPLOAD_PORT ?= $(shell ls -1tr /dev/tty*USB* 2>/dev/null | tail -1) -UPLOAD_PORT := $(if $(UPLOAD_PORT),$(UPLOAD_PORT),/dev/ttyS0) +UPLOAD_PORT_MATCH ?= /dev/ttyU* +UPLOAD_PORT ?= $(shell ls -1tr $(UPLOAD_PORT_MATCH) 2>/dev/null | tail -1) + +# Monitor definitions +MONITOR_SPEED ?= 115200 +MONITOR_PORT ?= $(UPLOAD_PORT) +MONITOR_PAR ?= --rts=0 --dtr=0 +MONITOR_COM ?= $(if $(NO_PY_WRAP),python3,$(PY_WRAP)) -m serial.tools.miniterm $(MONITOR_PAR) $(MONITOR_PORT) $(MONITOR_SPEED) # OTA parameters OTA_ADDR ?= -OTA_PORT ?= $(if $(filter $(CHIP), esp32),3232,8266) +OTA_PORT ?= $(if $(IS_ESP32),3232,8266) OTA_PWD ?= - OTA_ARGS = --progress --ip="$(OTA_ADDR)" --port="$(OTA_PORT)" - ifneq ($(OTA_PWD),) OTA_ARGS += --auth="$(OTA_PWD)" endif @@ -45,90 +64,88 @@ HTTP_ADDR ?= HTTP_URI ?= /update HTTP_PWD ?= user HTTP_USR ?= password +HTTP_OPT ?= --progress-bar -o /dev/null # Output directory BUILD_ROOT ?= /tmp/mkESP BUILD_DIR ?= $(BUILD_ROOT)/$(MAIN_NAME)_$(BOARD) -# File system source directory +# File system and corresponding disk directories +FS_TYPE ?= spiffs FS_DIR ?= $(dir $(SKETCH))data -FS_REST_DIR ?= $(BUILD_DIR)/file_system - -# Bootloader -BOOT_LOADER ?= $(ESP_ROOT)/bootloaders/eboot/eboot.elf - -#==================================================================================== -# Standard build logic and values -#==================================================================================== - -START_TIME := $(shell date +%s) -OS ?= $(shell uname -s) +FS_RESTORE_DIR ?= $(BUILD_DIR)/file_system # Utility functions git_description = $(shell git -C $(1) describe --tags --always --dirty 2>/dev/null || echo Unknown) time_string = $(shell date +$(1)) -ifeq ($(OS), Darwin) - find_files = $(shell find -E $2 -regex ".*\.($1)" | sed 's/\/\//\//') -else - find_files = $(shell find $2 -regextype posix-egrep -regex ".*\.($1)") -endif +find_files = $(shell find $2 | awk '/.*\.($1)$$/') # ESP Arduino directories ifndef ESP_ROOT # Location not defined, find and use possible version in the Arduino IDE installation - ifeq ($(OS), Windows_NT) - ARDUINO_ROOT = $(shell cygpath -m $(LOCALAPPDATA)/Arduino15) - else ifeq ($(OS), Darwin) - ARDUINO_ROOT = $(HOME)/Library/Arduino15 - else - ARDUINO_ROOT = $(HOME)/.arduino15 - endif + ARDUINO_ROOT ?= $(HOME)/.arduino15 ARDUINO_ESP_ROOT = $(ARDUINO_ROOT)/packages/$(CHIP) - ESP_ROOT := $(lastword $(wildcard $(ARDUINO_ESP_ROOT)/hardware/$(CHIP)/*)) + ESP_ROOT := $(if $(ARDUINO_HW_ESP_ROOT),$(ARDUINO_HW_ESP_ROOT),$(lastword $(wildcard $(ARDUINO_ESP_ROOT)/hardware/$(CHIP)/*))) ifeq ($(ESP_ROOT),) $(error No installed version of $(CHIP) Arduino found) endif - ARDUINO_LIBS = $(shell grep -o "sketchbook.path=.*" $(ARDUINO_ROOT)/preferences.txt 2>/dev/null | cut -f2- -d=)/libraries + ARDUINO_LIBS ?= $(shell grep -o "sketchbook.path=.*" $(ARDUINO_ROOT)/preferences.txt 2>/dev/null | cut -f2- -d=)/libraries ESP_ARDUINO_VERSION := $(notdir $(ESP_ROOT)) # Find used version of compiler and tools COMP_PATH := $(lastword $(wildcard $(ARDUINO_ESP_ROOT)/tools/xtensa-*/*)) - ESPTOOL_PATH := $(lastword $(wildcard $(ARDUINO_ESP_ROOT)/tools/esptool*/*)) - MKSPIFFS_PATH := $(lastword $(wildcard $(ARDUINO_ESP_ROOT)/tools/mkspiffs/*/*)) + MK_FS_PATH := $(lastword $(wildcard $(ARDUINO_ESP_ROOT)/tools/mk$(FS_TYPE)/*/mk$(FS_TYPE))) + PYTHON3_PATH := $(lastword $(wildcard $(ARDUINO_ESP_ROOT)/tools/python3/*)) else - # Location defined, assume it is a git clone + # Location defined, assume that it is a git clone ESP_ARDUINO_VERSION = $(call git_description,$(ESP_ROOT)) - MKSPIFFS_PATH := $(lastword $(wildcard $(ESP_ROOT)/tools/mkspiffs/*)) + MK_FS_PATH := $(lastword $(wildcard $(ESP_ROOT)/tools/mk$(FS_TYPE)/mk$(FS_TYPE))) + PYTHON3_PATH := $(wildcard $(ESP_ROOT)/tools/python3) endif ESP_LIBS = $(ESP_ROOT)/libraries SDK_ROOT = $(ESP_ROOT)/tools/sdk TOOLS_ROOT = $(ESP_ROOT)/tools -ifeq ($(shell grep -o "$(BOARD).name" $(ESP_ROOT)/boards.txt 2>/dev/null),) - $(error Invalid board: $(BOARD)) -endif +# The esp8266 tools directory contains the python3 executable as well as some modules +# Use these to avoid additional python installation requirements here +PYTHON3_PATH := $(if $(PYTHON3_PATH),$(PYTHON3_PATH),$(dir $(shell which python3 2>/dev/null))) +PY_WRAP = $(PYTHON3_PATH)/python3 $(__TOOLS_DIR)/py_wrap.py $(TOOLS_ROOT) +NO_PY_WRAP ?= $(if $(IS_ESP32),1,) +# Validate the selected version of ESP Arduino ifeq ($(wildcard $(ESP_ROOT)/cores/$(CHIP)),) $(error $(ESP_ROOT) is not a vaild directory for $(CHIP)) endif -ESPTOOL ?= $(shell which esptool.py 2>/dev/null || which esptool 2>/dev/null) -ifneq ($(ESPTOOL),) - # esptool exists in path, overide defaults and use it for esp8266 flash operations - ifeq ($(CHIP),esp8266) - ESPTOOL_COM = $(ESPTOOL) - UPLOAD_COM = $(ESPTOOL_PATTERN) -a soft_reset write_flash 0x00000 $(BUILD_DIR)/$(MAIN_NAME).bin - FS_UPLOAD_COM = $(ESPTOOL_PATTERN) -a soft_reset write_flash $(SPIFFS_START) $(FS_IMAGE) - endif +# Set possible default board variant and validate +BOARD_OP = perl $(__TOOLS_DIR)/board_op.pl $(ESP_ROOT)/boards.txt "$(CPU)" +ifeq ($(BOARD),) + BOARD := $(if $(IS_ESP32),esp32,generic) +else ifeq ($(shell $(BOARD_OP) $(BOARD) check),) + $(error Invalid board: $(BOARD)) endif -ESPTOOL_PATTERN = echo Using: $(UPLOAD_PORT) @ $(UPLOAD_SPEED) && "$(ESPTOOL_COM)" --baud=$(UPLOAD_SPEED) --port $(UPLOAD_PORT) --chip $(CHIP) -ifeq ($(MAKECMDGOALS),help) - DEMO=1 +# Handle esptool variants +ESPTOOL_EXT = $(if $(IS_ESP32),,.py) +ESPTOOL ?= $(if $(NO_PY_WRAP),$(ESP_ROOT)/tools/esptool/esptool$(ESPTOOL_EXT),$(PY_WRAP) esptool) +ESPTOOL_COM ?= $(ESPTOOL) --baud=$(UPLOAD_SPEED) --port $(UPLOAD_PORT) --chip $(CHIP) +ifeq ($(IS_ESP32),) + # esp8266, use esptool directly instead of via tools/upload.py in order to avoid speed restrictions currently implied there + UPLOAD_COM = $(ESPTOOL_COM) $(UPLOAD_RESET) write_flash 0x00000 $(BUILD_DIR)/$(MAIN_NAME).bin + FS_UPLOAD_COM = $(ESPTOOL_COM) $(UPLOAD_RESET) write_flash $(SPIFFS_START) $(FS_IMAGE) +endif + +# Detect if the specified goal involves building or not +GOALS := $(if $(MAKECMDGOALS),$(MAKECMDGOALS),all) +BUILDING := $(if $(filter $(GOALS), monitor list_boards list_flash_defs list_lwip set_git_version install help tools_dir preproc info),,1) + +# Sketch (main program) selection +ifeq ($(BUILDING),) + SKETCH = /dev/null endif ifdef DEMO - SKETCH := $(if $(filter $(CHIP), esp32),$(ESP_LIBS)/WiFi/examples/WiFiScan/WiFiScan.ino,$(ESP_LIBS)/ESP8266WebServer/examples/HelloServer/HelloServer.ino) + SKETCH := $(if $(IS_ESP32),$(ESP_LIBS)/WiFi/examples/WiFiScan/WiFiScan.ino,$(ESP_LIBS)/ESP8266WiFi/examples/WiFiScan/WiFiScan.ino) endif -SKETCH ?= $(wildcard *.ino *.pde) +SKETCH ?= $(abspath $(wildcard *.ino *.pde)) ifeq ($(SKETCH),) $(error No sketch specified or found. Use "DEMO=1" for testing) endif @@ -141,24 +158,12 @@ SRC_GIT_VERSION := $(call git_description,$(dir $(SKETCH))) SKETCH_NAME := $(basename $(notdir $(SKETCH))) MAIN_NAME ?= $(SKETCH_NAME) MAIN_EXE ?= $(BUILD_DIR)/$(MAIN_NAME).bin -FS_IMAGE ?= $(BUILD_DIR)/FS.spiffs - -ifeq ($(OS), Windows_NT) - # Adjust some paths for cygwin - BUILD_DIR := $(shell cygpath -m $(BUILD_DIR)) - SKETCH := $(shell cygpath -m $(SKETCH)) - ifdef ARDUINO_LIBS - ARDUINO_LIBS := $(shell cygpath -m $(ARDUINO_LIBS)) - endif -endif +FS_IMAGE ?= $(BUILD_DIR)/FS.bin # Build file extensions OBJ_EXT = .o DEP_EXT = .d -# Auto generated makefile with Arduino definitions -ARDUINO_MK = $(BUILD_DIR)/arduino.mk - # Special tool definitions OTA_TOOL ?= python $(TOOLS_ROOT)/espota.py HTTP_TOOL ?= curl @@ -168,55 +173,39 @@ CORE_DIR = $(ESP_ROOT)/cores/$(CHIP) CORE_SRC := $(call find_files,S|c|cpp,$(CORE_DIR)) CORE_OBJ := $(patsubst %,$(BUILD_DIR)/%$(OBJ_EXT),$(notdir $(CORE_SRC))) CORE_LIB = $(BUILD_DIR)/arduino.ar +USER_OBJ_LIB = $(BUILD_DIR)/user_obj.ar -SKETCH_DIR = $(dir $(SKETCH)) -# User defined compilation units and directories -ifeq ($(LIBS),) - # Automatically find directories with header files used by the sketch - LIBS := $(shell perl -e 'use File::Find;@d = split(" ", shift);while (<>) {$$f{"$$1"} = 1 if /^\s*\#include\s+[<"]([^>"]+)/;}find(sub {if ($$f{$$_}){print $$File::Find::dir," ";$$f{$$_}=0;}}, @d);' \ - "$(CUSTOM_LIBS) $(ESP_LIBS) $(ARDUINO_LIBS)" $(SKETCH) $(call find_files,S|c|cpp,$(SKETCH_DIR))) - ifneq ($(findstring /examples/,$(realpath $(SKETCH))),) - # Assume library example sketch, add the library directory unless it is an Arduino basic example - EX_LIB := $(shell perl -e 'print $$ARGV[0] if $$ARGV[0] =~ s/\/examples\/(?!\d\d\.).+//' $(realpath $(SKETCH))) - ifneq ($(EX_LIB),) - ifneq ($(wildcard $(EX_LIB)/src),) - # Library in src sub directory - EX_LIB := $(EX_LIB)/src - else - # Library at root. Avoid getting files from other examples - EXCLUDE_DIRS ?= $(EX_LIB)/examples - endif - LIBS += $(EX_LIB) - endif - endif -endif +# Find project specific source files and include directories +SRC_LIST = $(BUILD_DIR)/src_list.mk +FIND_SRC_CMD = $(__TOOLS_DIR)/find_src.pl +$(SRC_LIST): $(MAKEFILE_LIST) $(FIND_SRC_CMD) | $(BUILD_DIR) + $(if $(BUILDING),echo "- Finding all involved files for the build ...",) + perl $(FIND_SRC_CMD) "$(EXCLUDE_DIRS)" $(SKETCH) "$(CUSTOM_LIBS)" "$(LIBS)" $(ESP_LIBS) $(ARDUINO_LIBS) >$(SRC_LIST) + +-include $(SRC_LIST) -IGNORE_PATTERN := $(foreach dir,$(EXCLUDE_DIRS),$(dir)/%) -USER_INC := $(filter-out $(IGNORE_PATTERN),$(call find_files,h|hpp,$(SKETCH_DIR) $(dir $(LIBS)))) -USER_SRC := $(SKETCH) $(filter-out $(IGNORE_PATTERN),$(call find_files,S|c|cpp$(USER_SRC_PATTERN),$(SKETCH_DIR) $(LIBS))) -# Object file suffix seems to be significant for the linker... -USER_OBJ := $(subst .ino,_.cpp,$(patsubst %,$(BUILD_DIR)/%$(OBJ_EXT),$(notdir $(USER_SRC)))) +# Use sketch copy with correct C++ extension +SKETCH_CPP = $(BUILD_DIR)/$(notdir $(SKETCH)).cpp +USER_SRC := $(subst $(SKETCH),$(SKETCH_CPP),$(USER_SRC)) + +USER_OBJ := $(patsubst %,$(BUILD_DIR)/%$(OBJ_EXT),$(notdir $(USER_SRC))) USER_DIRS := $(sort $(dir $(USER_SRC))) -USER_INC_DIRS := $(sort $(dir $(USER_INC))) -USER_LIBS := $(filter-out $(IGNORE_PATTERN),$(call find_files,a,$(SKETCH_DIR) $(LIBS))) # Use first flash definition for the board as default -FLASH_DEF_MATCH = $(if $(filter $(CHIP), esp32),build\.flash_size=(\S+),menu\.(?:FlashSize|eesz)\.([^\.]+)=(.+)) -FLASH_DEF ?= $(shell cat $(ESP_ROOT)/boards.txt | perl -e 'while (<>) {if (/^$(BOARD)\.$(FLASH_DEF_MATCH)/){ print "$$1"; exit;}}') +FLASH_DEF ?= $(shell $(BOARD_OP) $(BOARD) first_flash) # Same method for LwIPVariant -LWIP_VARIANT ?= $(shell cat $(ESP_ROOT)/boards.txt | perl -e 'while (<>) {if (/^$(BOARD)\.menu\.(?:LwIPVariant|ip)\.([^\.=]+)=/){ print "$$1"; exit;}}') +LWIP_VARIANT ?= $(shell $(BOARD_OP) $(BOARD) first_lwip) # Handle possible changed state i.e. make command line parameters or changed git versions -ifeq ($(OS), Darwin) - CMD_LINE := $(shell ps $$PPID -o command | tail -1) -else - CMD_LINE := $(shell tr "\0" " " $(ARDUINO_MK) +ARDUINO_MK = $(BUILD_DIR)/arduino.mk +OS_NAME ?= linux +ARDUINO_DESC := $(shell find -L $(ESP_ROOT) -maxdepth 1 -name "*.txt" | sort) +$(ARDUINO_MK): $(ARDUINO_DESC) $(MAKEFILE_LIST) $(__TOOLS_DIR)/parse_arduino.pl | $(BUILD_DIR) + $(if $(BUILDING),echo "- Parsing Arduino configuration files ...",) + perl $(__TOOLS_DIR)/parse_arduino.pl $(BOARD) '$(FLASH_DEF)' '$(OS_NAME)' '$(LWIP_VARIANT)' $(ARDUINO_EXTRA_DESC) $(ARDUINO_DESC) >$(ARDUINO_MK) -include $(ARDUINO_MK) @@ -237,79 +229,103 @@ INCLUDE_DIRS += $(CORE_DIR) $(ESP_ROOT)/variants/$(INCLUDE_VARIANT) $(BUILD_DIR) C_INCLUDES := $(foreach dir,$(INCLUDE_DIRS) $(USER_INC_DIRS),-I$(dir)) VPATH += $(shell find $(CORE_DIR) -type d) $(USER_DIRS) -# Automatically generated build information data -# Makes the build date and git descriptions at the actual build event available as string constants in the program +# Automatically generated build information data source file +# Makes the build date and git descriptions at the time of actual build event +# available as string constants in the program BUILD_INFO_H = $(BUILD_DIR)/buildinfo.h BUILD_INFO_CPP = $(BUILD_DIR)/buildinfo.c++ BUILD_INFO_OBJ = $(BUILD_INFO_CPP)$(OBJ_EXT) +BUILD_DATE = $(call time_string,"%Y-%m-%d") +BUILD_TIME = $(call time_string,"%H:%M:%S") $(BUILD_INFO_H): | $(BUILD_DIR) - echo "typedef struct { const char *date, *time, *src_version, *env_version;} _tBuildInfo; extern _tBuildInfo _BuildInfo;" >$@ + @echo "typedef struct { const char *date, *time, *src_version, *env_version; } _tBuildInfo; extern _tBuildInfo _BuildInfo;" >$@ -# ccache? -ifeq ($(USE_CCACHE), 1) +# Use ccache if it is available and not explicitly disabled (USE_CCACHE=0) +USE_CCACHE ?= $(if $(shell which ccache 2>/dev/null),1,0) +ifeq ($(USE_CCACHE),1) C_COM_PREFIX = ccache CPP_COM_PREFIX = $(C_COM_PREFIX) endif -# Build rules for the different source file types -$(BUILD_DIR)/%.cpp$(OBJ_EXT): %.cpp $(BUILD_INFO_H) $(ARDUINO_MK) - echo $(" >$@ + cat $(abspath $<) >>$@ -$(BUILD_DIR)/%.pde$(OBJ_EXT): %.pde $(BUILD_INFO_H) $(ARDUINO_MK) - echo $(' >$(BUILD_INFO_CPP) - echo '_tBuildInfo _BuildInfo = {"$(BUILD_DATE)","$(BUILD_TIME)","$(SRC_GIT_VERSION)","$(ESP_ARDUINO_VERSION)"};' >>$(BUILD_INFO_CPP) +# Linking the executable +$(MAIN_EXE): $(CORE_LIB) $(USER_LIBS) $(USER_OBJ_DEP) + @echo Linking $(MAIN_EXE) + $(PRELINK) + @echo " Versions: $(SRC_GIT_VERSION), $(ESP_ARDUINO_VERSION)" + @echo '#include ' >$(BUILD_INFO_CPP) + @echo '_tBuildInfo _BuildInfo = {"$(BUILD_DATE)","$(BUILD_TIME)","$(SRC_GIT_VERSION)","$(ESP_ARDUINO_VERSION)"};' >>$(BUILD_INFO_CPP) $(CPP_COM) $(BUILD_INFO_CPP) -o $(BUILD_INFO_OBJ) $(LD_COM) $(LD_EXTRA) $(GEN_PART_COM) - $(ELF2BIN_COM) - $(SIZE_COM) | perl -e "$$MEM_USAGE" "$(MEM_FLASH)" "$(MEM_RAM)" + $(OBJCOPY) + $(SIZE_COM) | perl $(__TOOLS_DIR)/mem_use.pl "$(MEM_FLASH)" "$(MEM_RAM)" ifneq ($(LWIP_INFO),) - printf "LwIPVariant: $(LWIP_INFO)\n" + @printf "LwIPVariant: $(LWIP_INFO)\n" endif ifneq ($(FLASH_INFO),) - printf "Flash size: $(FLASH_INFO)\n\n" + @printf "Flash size: $(FLASH_INFO)\n\n" endif - perl -e 'print "Build complete. Elapsed time: ", time()-$(START_TIME), " seconds\n\n"' + @perl -e 'print "Build complete. Elapsed time: ", time()-$(START_TIME), " seconds\n\n"' +# Flashing operations +CHECK_PORT := $(if $(UPLOAD_PORT),\ + @echo === Using upload port: $(UPLOAD_PORT) @ $(UPLOAD_SPEED),\ + @echo "*** Upload port not found or defined" && exit 1) upload flash: all + $(CHECK_PORT) $(UPLOAD_COM) ota: all ifeq ($(OTA_ADDR),) - echo == Error: Address of device must be specified via OTA_ADDR + @echo == Error: Address of device must be specified via OTA_ADDR exit 1 endif $(OTA_PRE_COM) @@ -317,301 +333,237 @@ endif http: all ifeq ($(HTTP_ADDR),) - echo == Error: Address of device must be specified via HTTP_ADDR + @echo == Error: Address of device must be specified via HTTP_ADDR exit 1 endif - $(HTTP_TOOL) --verbose -F image=@$(MAIN_EXE) --user $(HTTP_USR):$(HTTP_PWD) http://$(HTTP_ADDR)$(HTTP_URI) - echo "\n" + $(HTTP_TOOL) $(HTTP_OPT) -F image=@$(MAIN_EXE) --user $(HTTP_USR):$(HTTP_PWD) http://$(HTTP_ADDR)$(HTTP_URI) + @echo "\n" -$(FS_IMAGE): $(ARDUINO_MK) $(wildcard $(FS_DIR)/*) - echo Generating filesystem image: $(FS_IMAGE) - $(MKSPIFFS_COM) +$(FS_IMAGE): $(ARDUINO_MK) $(shell find $(FS_DIR)/ 2>/dev/null) +ifeq ($(SPIFFS_SIZE),) + @echo == Error: No file system specified in FLASH_DEF + exit 1 +endif + @echo Generating file system image: $(FS_IMAGE) + $(MK_FS_COM) fs: $(FS_IMAGE) upload_fs flash_fs: $(FS_IMAGE) + $(CHECK_PORT) $(FS_UPLOAD_COM) ota_fs: $(FS_IMAGE) ifeq ($(OTA_ADDR),) - echo == Error: Address of device must be specified via OTA_ADDR + @echo == Error: Address of device must be specified via OTA_ADDR exit 1 endif $(OTA_TOOL) $(OTA_ARGS) --spiffs --file="$(FS_IMAGE)" run: flash - python -m serial.tools.miniterm --rts=0 --dtr=0 $(UPLOAD_PORT) 115200 + $(MONITOR_COM) + +monitor: +ifeq ($(MONITOR_PORT),) + @echo "*** Monitor port not found or defined" && exit 1 +endif + $(MONITOR_COM) FLASH_FILE ?= $(BUILD_DIR)/esp_flash.bin dump_flash: - echo Dumping flash memory to file: $(FLASH_FILE) - $(ESPTOOL_PATTERN) read_flash 0 $(shell perl -e 'shift =~ /(\d+)([MK])/ || die "Invalid memory size\n";$$mem_size=$$1*1024;$$mem_size*=1024 if $$2 eq "M";print $$mem_size;' $(FLASH_DEF)) $(FLASH_FILE) + $(CHECK_PORT) + @echo Dumping flash memory to file: $(FLASH_FILE) + $(ESPTOOL_COM) read_flash 0 $(shell perl -e 'shift =~ /(\d+)([MK])/ || die "Invalid memory size\n";$$mem_size=$$1*1024;$$mem_size*=1024 if $$2 eq "M";print $$mem_size;' $(FLASH_DEF)) $(FLASH_FILE) dump_fs: - echo Dumping flash file system to directory: $(FS_REST_DIR) - -$(ESPTOOL_PATTERN) read_flash $(SPIFFS_START) $(SPIFFS_SIZE) $(FS_IMAGE) - mkdir -p $(FS_REST_DIR) - echo - echo == Files == - $(RESTSPIFFS_COM) + $(CHECK_PORT) + @echo Dumping flash file system to directory: $(FS_RESTORE_DIR) + -$(ESPTOOL_COM) read_flash $(SPIFFS_START) $(SPIFFS_SIZE) $(FS_IMAGE) + mkdir -p $(FS_RESTORE_DIR) + @echo + @echo == Files == + $(RESTORE_FS_COM) restore_flash: - echo Restoring flash memory from file: $(FLASH_FILE) - $(ESPTOOL_PATTERN) -a soft_reset write_flash 0 $(FLASH_FILE) + $(CHECK_PORT) + @echo Restoring flash memory from file: $(FLASH_FILE) + $(ESPTOOL_COM) -a soft_reset write_flash 0 $(FLASH_FILE) erase_flash: - $(ESPTOOL_PATTERN) erase_flash + $(CHECK_PORT) + $(ESPTOOL_COM) erase_flash +# Building library instead of executable LIB_OUT_FILE ?= $(BUILD_DIR)/$(MAIN_NAME).a .PHONY: lib lib: $(LIB_OUT_FILE) -$(LIB_OUT_FILE): $(filter-out $(BUILD_DIR)/$(MAIN_NAME)_.cpp$(OBJ_EXT),$(USER_OBJ)) - echo Building library $(LIB_OUT_FILE) +$(LIB_OUT_FILE): $(filter-out $(BUILD_DIR)/$(MAIN_NAME).cpp$(OBJ_EXT),$(USER_OBJ)) + @echo Building library $(LIB_OUT_FILE) rm -f $(LIB_OUT_FILE) $(LIB_COM) cru $(LIB_OUT_FILE) $^ +# Miscellaneous operations clean: - echo Removing all build files + @echo Removing all build files rm -rf "$(BUILD_DIR)" $(FILES_TO_CLEAN) list_boards: - echo === Available boards === - cat $(ESP_ROOT)/boards.txt | perl -e 'while (<>) { if (/^([\w\-]+)\.name=(.+)/){ print sprintf("%-20s %s\n", $$1,$$2);} }' + $(BOARD_OP) $(BOARD) list_names -list_lib: - echo === User specific libraries === - perl -e 'foreach (@ARGV) {print "$$_\n"}' "* Include directories:" $(USER_INC_DIRS) "* Library source files:" $(USER_SRC) +list_lib: $(SRC_LIST) + perl -e 'foreach (@ARGV) {print "$$_\n"}' "===== Include directories =====" $(USER_INC_DIRS) "===== Source files =====" $(USER_SRC) list_flash_defs: - echo === Memory configurations for board: $(BOARD) === - cat $(ESP_ROOT)/boards.txt | perl -e 'while (<>) { if (/^$(BOARD)\.$(FLASH_DEF_MATCH)/){ print sprintf("%-10s %s\n", $$1,$$2);} }' + $(BOARD_OP) $(BOARD) list_flash list_lwip: - echo === lwip configurations for board: $(BOARD) === - cat $(ESP_ROOT)/boards.txt | perl -e 'while (<>) { if (/^$(BOARD)\.menu\.(?:LwIPVariant|ip)\.(\w+)=(.+)/){ print sprintf("%-10s %s\n", $$1,$$2);} }' - -help: $(ARDUINO_MK) - echo - echo "Generic makefile for building Arduino esp8266 and esp32 projects" - echo "This file can either be used directly or included from another makefile" - echo "" - echo "The following targets are available:" - echo " all (default) Build the project application" - echo " clean Remove all intermediate build files" - echo " lib Build a library with all involved object files" - echo " flash Build and and flash the project application" - echo " flash_fs Build and and flash file system (when applicable)" - echo " ota Build and and flash via OTA" - echo " Params: OTA_ADDR, OTA_PORT and OTA_PWD" - echo " ota_fs Build and and flash file system via OTA" - echo " http Build and and flash via http (curl)" - echo " Params: HTTP_ADDR, HTTP_URI, HTTP_PWD and HTTP_USR" - echo " dump_flash Dump the whole board flash memory to a file" - echo " restore_flash Restore flash memory from a previously dumped file" - echo " dump_fs Extract all files from the flash file system" - echo " Params: FS_DUMP_DIR" - echo " erase_flash Erase the whole flash" - echo " list_lib Show a list of used library files and include paths" - echo "Configurable parameters:" - echo " SKETCH Main source file" - echo " If not specified the first sketch in current" - echo " directory will be used." - echo " LIBS Includes in the sketch file of libraries from within" - echo " the ESP Arduino directories are automatically" - echo " detected. If this is not enough, define this" - echo " variable with all libraries or directories needed." - echo " CHIP Set to esp8266 or esp32. Default: '$(CHIP)'" - echo " BOARD Name of the target board. Default: '$(BOARD)'" - echo " Use 'list_boards' to get list of available ones" - echo " FLASH_DEF Flash partitioning info. Default '$(FLASH_DEF)'" - echo " Use 'list_flash_defs' to get list of available ones" - echo " BUILD_DIR Directory for intermediate build files." - echo " Default '$(BUILD_DIR)'" - echo " BUILD_EXTRA_FLAGS Additional parameters for the compilation commands" - echo " FS_DIR File system root directory" - echo " UPLOAD_PORT Serial flashing port name. Default: '$(UPLOAD_PORT)'" - echo " UPLOAD_SPEED Serial flashing baud rate. Default: '$(UPLOAD_SPEED)'" - echo " FLASH_FILE File name for dump and restore flash operations" - echo " Default: '$(FLASH_FILE)'" - echo " LWIP_VARIANT Use specified variant of the lwip library when applicable" - echo " Use 'list_lwip' to get list of available ones" - echo " Default: $(LWIP_VARIANT) ($(LWIP_INFO))" - echo " VERBOSE Set to 1 to get full printout of the build" - echo " BUILD_THREADS Number of parallel build threads" - echo " Default: Maximum possible, based on number of CPUs" - echo " USE_CCACHE Set to 1 to use ccache in the build" - echo + $(BOARD_OP) $(BOARD) list_lwip -$(BUILD_DIR): - mkdir -p $(BUILD_DIR) +# Update the git version of the esp Arduino repo +set_git_version: +ifeq ($(REQ_GIT_VERSION),) + @echo == Error: Version tag must be specified via REQ_GIT_VERSION + exit 1 +endif + @echo == Setting $(ESP_ROOT) to $(REQ_GIT_VERSION) ... + git -C $(ESP_ROOT) checkout -fq --recurse-submodules $(REQ_GIT_VERSION) + git -C $(ESP_ROOT) clean -fdxq -f + git -C $(ESP_ROOT) submodule update --init + git -C $(ESP_ROOT) submodule foreach -q --recursive git clean -xfd + cd $(ESP_ROOT)/tools; ./get.py -q + +# Generate a Visual Studio Code configuration and launch +BIN_DIR = /usr/local/bin +_MAKE_COM = make -f $(__THIS_FILE) ESP_ROOT=$(ESP_ROOT) +ifeq ($(CHIP),esp32) + _MAKE_COM += CHIP=esp32 + _SCRIPT = espmake32 +else + _SCRIPT = espmake +endif +vscode: all + perl $(__TOOLS_DIR)/vscode.pl -n $(MAIN_NAME) -m "$(_MAKE_COM)" -w "$(VS_CODE_DIR)" -i "$(VSCODE_INC_EXTRA)" -p "$(VSCODE_PROJ_NAME)" $(CPP_COM) + +# Create shortcut command for running this file +install: + @echo Creating command \"$(_SCRIPT)\" in $(BIN_DIR) + sudo sh -c 'echo $(_MAKE_COM) "\"\$$@\"" >$(BIN_DIR)/$(_SCRIPT)' + sudo chmod +x $(BIN_DIR)/$(_SCRIPT) + +# Just return the path of the tools directory (intended to be used to find vscode.pl above from othe makefiles) +tools_dir: + @echo $(__TOOLS_DIR) + +# Show ram memory usage per variable +ram_usage: $(MAIN_EXE) + $(shell find $(TOOLS_ROOT) | grep 'gcc-nm') -Clrtd --size-sort $(BUILD_DIR)/$(MAIN_NAME).elf | grep -i ' [b] ' + +# Show ram and flash usage per object files used in the build +OBJ_INFO_FORM ?= 0 +OBJ_INFO_SORT ?= 1 +obj_info: $(MAIN_EXE) + perl $(__TOOLS_DIR)/obj_info.pl "$(shell find $(TOOLS_ROOT) | grep 'elf-size$$')" "$(OBJ_INFO_FORM)" "$(OBJ_INFO_SORT)" $(BUILD_DIR)/*.o + +# Analyze crash log +crash: $(MAIN_EXE) + perl $(__TOOLS_DIR)/crash_tool.pl $(ESP_ROOT) $(BUILD_DIR)/$(MAIN_NAME).elf + +# Run compiler preprocessor to get full expanded source for a file +preproc: +ifeq ($(SRC_FILE),) + $(error SRC_FILE must be defined) +endif + $(CPP_COM) -E $(SRC_FILE) +# Main default rule, build the executable .PHONY: all -all: $(BUILD_DIR) $(ARDUINO_MK) $(BUILD_INFO_H) prebuild $(MAIN_EXE) +all: $(BUILD_DIR) $(ARDUINO_MK) prebuild $(MAIN_EXE) +# Prebuild is currently only mandatory for esp32 +USE_PREBUILD ?= $(if $(IS_ESP32),1,) prebuild: -ifdef USE_PREBUILD - $(CORE_PREBUILD) +ifneq ($(USE_PREBUILD),) + $(PREBUILD) endif - $(SKETCH_PREBUILD) -# Include all available dependencies +help: $(ARDUINO_MK) + @echo + @echo "Generic makefile for building Arduino esp8266 and esp32 projects" + @echo "This file can either be used directly or included from another makefile" + @echo "" + @echo "The following targets are available:" + @echo " all (default) Build the project application" + @echo " clean Remove all intermediate build files" + @echo " lib Build a library with all involved object files" + @echo " flash Build and and flash the project application" + @echo " flash_fs Build and and flash file system (when applicable)" + @echo " ota Build and and flash via OTA" + @echo " Params: OTA_ADDR, OTA_PORT and OTA_PWD" + @echo " ota_fs Build and and flash file system via OTA" + @echo " http Build and and flash via http (curl)" + @echo " Params: HTTP_ADDR, HTTP_URI, HTTP_PWD and HTTP_USR" + @echo " dump_flash Dump the whole board flash memory to a file" + @echo " restore_flash Restore flash memory from a previously dumped file" + @echo " dump_fs Extract all files from the flash file system" + @echo " Params: FS_DUMP_DIR" + @echo " erase_flash Erase the whole flash (use with care!)" + @echo " list_lib Show a list of used solurce files and include directories" + @echo " set_git_version Setup ESP Arduino git repo to a the tag version" + @echo " specified via REQ_GIT_VERSION" + @echo " install Create the commands \"espmake\" and \"espmake32\"" + @echo " vscode Create config file for Visual Studio Code and launch" + @echo " ram_usage Show global variables RAM usage" + @echo " obj_info Show memory usage per object file" + @echo " monitor Start serial monitor on the upload port" + @echo " run Build flash and start serial monitor" + @echo " crash Analyze stack trace from a crash" + @echo " preproc Run compiler preprocessor on source file" + @echo " specified via SRC_FILE" + @echo " info Show location and version of used esp Arduino" + @echo "Configurable parameters:" + @echo " SKETCH Main source file" + @echo " If not specified the first sketch in current" + @echo " directory will be used." + @echo " LIBS Use this variable to declare additional directories" + @echo " and/or files which should be included in the build" + @echo " CHIP Set to esp8266 or esp32. Default: '$(CHIP)'" + @echo " BOARD Name of the target board. Default: '$(BOARD)'" + @echo " Use 'list_boards' to get list of available ones" + @echo " FLASH_DEF Flash partitioning info. Default '$(FLASH_DEF)'" + @echo " Use 'list_flash_defs' to get list of available ones" + @echo " BUILD_DIR Directory for intermediate build files." + @echo " Default '$(BUILD_DIR)'" + @echo " BUILD_EXTRA_FLAGS Additional parameters for the compilation commands" + @echo " COMP_WARNINGS Compilation warning options. Default: $(COMP_WARNINGS)" + @echo " FS_TYPE File system type. Default: $(FS_TYPE)" + @echo " FS_DIR File system root directory" + @echo " UPLOAD_PORT Serial flashing port name. Default: '$(UPLOAD_PORT)'" + @echo " UPLOAD_SPEED Serial flashing baud rate. Default: '$(UPLOAD_SPEED)'" + @echo " MONITOR_SPEED Baud rate for the monitor. Default: '$(MONITOR_SPEED)'" + @echo " FLASH_FILE File name for dump and restore flash operations" + @echo " Default: '$(FLASH_FILE)'" + @echo " LWIP_VARIANT Use specified variant of the lwip library when applicable" + @echo " Use 'list_lwip' to get list of available ones" + @echo " Default: $(LWIP_VARIANT) ($(LWIP_INFO))" + @echo " VERBOSE Set to 1 to get full printout of the build" + @echo " BUILD_THREADS Number of parallel build threads" + @echo " Default: Maximum possible, based on number of CPUs" + @echo " USE_CCACHE Set to 0 to disable ccache when it is available" + @echo " NO_USER_OBJ_LIB Set to 1 to disable putting all object files into an archive" + @echo + +# Show installation information +info: + echo == Build info + echo " CHIP: $(CHIP)" + echo " ESP_ROOT: $(ESP_ROOT)" + echo " Version: $(ESP_ARDUINO_VERSION)" + echo " Threads: $(BUILD_THREADS)" + echo " Upload port: $(UPLOAD_PORT)" + +# Include all available dependencies from the previous compilation -include $(wildcard $(BUILD_DIR)/*$(DEP_EXT)) DEFAULT_GOAL ?= all .DEFAULT_GOAL := $(DEFAULT_GOAL) -ifeq ($(OS), Darwin) - BUILD_THREADS ?= $(shell sysctl -n hw.ncpu) -else - BUILD_THREADS ?= $(shell nproc) -endif -MAKEFLAGS += -j $(BUILD_THREADS) - -ifndef VERBOSE - # Set silent mode as default - MAKEFLAGS += --silent -endif - -# Inline Perl scripts - -# Parse Arduino definitions and build commands from the descriptions -define PARSE_ARDUINO -my $$board = shift; -my $$flashSize = shift; -my $$os = shift; -$$os =~ s/Windows_NT/windows/; -$$os =~ s/Linux/linux/; -$$os =~ s/Darwin/macosx/; -my $$lwipvariant = shift; -my %v; - -sub def_var { - my ($$name, $$var) = @_; - print "$$var ?= $$v{$$name}\n"; - $$v{$$name} = "\$$($$var)"; -} - -$$v{'runtime.platform.path'} = '$$(ESP_ROOT)'; -$$v{'includes'} = '$$(C_INCLUDES)'; -$$v{'runtime.ide.version'} = '10605'; -$$v{'build.arch'} = uc('$(CHIP)'); -$$v{'build.project_name'} = '$$(MAIN_NAME)'; -$$v{'build.path'} = '$$(BUILD_DIR)'; -$$v{'object_files'} = '$$^ $$(BUILD_INFO_OBJ)'; -$$v{'archive_file_path'} = '$$(CORE_LIB)'; - -foreach my $$fn (@ARGV) { - open($$f, $$fn) || die "Failed to open: $$fn\n"; - while (<$$f>) { - s/\s+$$//; - s/\.esptool_py\./.esptool./g; - next unless /^(\w[\w\-\.]+)=(.*)/; - my ($$key, $$val) =($$1, $$2); - $$board_defined = 1 if $$key eq "$$board.name"; - $$key =~ s/$$board\.menu\.(?:FlashSize|eesz)\.$$flashSize\.//; - $$key =~ s/$$board\.menu\.CpuFrequency\.[^\.]+\.//; - $$key =~ s/$$board\.menu\.(?:FlashFreq|xtal)\.[^\.]+\.//; - $$key =~ s/$$board\.menu\.UploadSpeed\.[^\.]+\.//; - $$key =~ s/$$board\.menu\.baud\.[^\.]+\.//; - $$key =~ s/$$board\.menu\.ResetMethod\.[^\.]+\.//; - $$key =~ s/$$board\.menu\.FlashMode\.[^\.]+\.//; - $$key =~ s/$$board\.menu\.(?:LwIPVariant|ip)\.$$lwipvariant\.//; - $$key =~ s/^$$board\.//; - $$v{$$key} ||= $$val; - $$v{$$1} = $$v{$$key} if $$key =~ /(.+)\.$$os$$/; - } - close($$f); -} -$$v{'runtime.tools.xtensa-lx106-elf-gcc.path'} ||= '$$(COMP_PATH)'; -$$v{'runtime.tools.xtensa-esp32-elf-gcc.path'} ||= '$$(COMP_PATH)'; -$$v{'runtime.tools.esptool.path'} ||= '$$(ESPTOOL_PATH)'; - -die "* Unknown board $$board\n" unless $$board_defined; -print "# Board definitions\n"; -def_var('build.code_debug', 'CORE_DEBUG_LEVEL'); -def_var('build.f_cpu', 'F_CPU'); -def_var('build.flash_mode', 'FLASH_MODE'); -def_var('build.flash_freq', 'FLASH_SPEED'); -def_var('upload.resetmethod', 'UPLOAD_RESET'); -def_var('upload.speed', 'UPLOAD_SPEED'); -def_var('compiler.warning_flags', 'COMP_WARNINGS'); -$$v{'serial.port'} = '$$(UPLOAD_PORT)'; -$$v{'recipe.objcopy.hex.pattern'} =~ s/[^"]+\/bootloaders\/eboot\/eboot.elf/\$$(BOOT_LOADER)/; -$$v{'recipe.objcopy.hex.1.pattern'} =~ s/[^"]+\/bootloaders\/eboot\/eboot.elf/\$$(BOOT_LOADER)/; -$$v{'recipe.hooks.linking.prelink.1.pattern'} =~ s/\{build.vtable_flags\}/\$$(VTABLE_FLAGS)/; -$$v{'tools.esptool.upload.pattern'} =~ s/\{(cmd|path)\}/\{tools.esptool.$$1\}/g; -$$v{'compiler.cpreprocessor.flags'} .= " \$$(C_PRE_PROC_FLAGS)"; -$$v{'build.extra_flags'} .= " \$$(BUILD_EXTRA_FLAGS)"; - -foreach my $$key (sort keys %v) { - while ($$v{$$key} =~/\{/) { - $$v{$$key} =~ s/\{([\w\-\.]+)\}/$$v{$$1}/; - $$v{$$key} =~ s/""//; - } - $$v{$$key} =~ s/ -o\s+$$//; - $$v{$$key} =~ s/(-D\w+=)"([^"]+)"/$$1\\"$$2\\"/g; -} - -print "INCLUDE_VARIANT = $$v{'build.variant'}\n"; -print "# Commands\n"; -print "C_COM=\$$(C_COM_PREFIX) $$v{'recipe.c.o.pattern'}\n"; -print "CPP_COM=\$$(CPP_COM_PREFIX) $$v{'recipe.cpp.o.pattern'}\n"; -print "S_COM=$$v{'recipe.S.o.pattern'}\n"; -print "LIB_COM=\"$$v{'compiler.path'}$$v{'compiler.ar.cmd'}\"\n"; -print "CORE_LIB_COM=$$v{'recipe.ar.pattern'}\n"; -print "LD_COM=$$v{'recipe.c.combine.pattern'}\n"; -print "PART_FILE?=$$1\n" if $$v{'recipe.objcopy.eep.pattern'} =~ /\"([^\"]+\.csv)\"/; -$$v{'recipe.objcopy.eep.pattern'} =~ s/\"([^\"]+\.csv)\"/\$$(PART_FILE)/; -print "GEN_PART_COM=$$v{'recipe.objcopy.eep.pattern'}\n"; -print "ELF2BIN_COM=", $$v{'recipe.objcopy.hex.pattern'} || $$v{'recipe.objcopy.hex.1.pattern'}, "\n"; -print "SIZE_COM=$$v{'recipe.size.pattern'}\n"; -print "ESPTOOL_COM?=$$v{'tools.esptool.path'}/$$v{'tools.esptool.cmd'}\n"; -print "UPLOAD_COM?=$$v{'tools.esptool.upload.pattern'}\n"; - -if ($$v{'build.spiffs_start'}) { - print "SPIFFS_START?=$$v{'build.spiffs_start'}\n"; - my $$spiffs_size = sprintf("0x%X", hex($$v{'build.spiffs_end'})-hex($$v{'build.spiffs_start'})); - print "SPIFFS_SIZE?=$$spiffs_size\n"; -} elsif ($$v{'build.partitions'}) { - print "COMMA=,\n"; - print "SPIFFS_SPEC:=\$$(subst \$$(COMMA), ,\$$(shell grep spiffs \$$(PART_FILE)))\n"; - print "SPIFFS_START:=\$$(word 4,\$$(SPIFFS_SPEC))\n"; - print "SPIFFS_SIZE:=\$$(word 5,\$$(SPIFFS_SPEC))\n"; -} -$$v{'build.spiffs_blocksize'} ||= "4096"; -print "SPIFFS_BLOCK_SIZE?=$$v{'build.spiffs_blocksize'}\n"; -print "MKSPIFFS_COM?=\"\$$(MKSPIFFS_PATH)\" -b \$$(SPIFFS_BLOCK_SIZE) -s \$$(SPIFFS_SIZE) -c \$$(FS_DIR) \$$(FS_IMAGE)\n"; -print "RESTSPIFFS_COM?=\"\$$(MKSPIFFS_PATH)\" -b \$$(SPIFFS_BLOCK_SIZE) -s \$$(SPIFFS_SIZE) -u \$$(FS_REST_DIR) \$$(FS_IMAGE)\n"; - -my $$fs_upload_com = $$v{'tools.esptool.upload.pattern'}; -$$fs_upload_com =~ s/(.+ -ca) .+/$$1 \$$(SPIFFS_START) -cf \$$(FS_IMAGE)/; -$$fs_upload_com =~ s/(.+ --flash_size detect) .+/$$1 \$$(SPIFFS_START) \$$(FS_IMAGE)/; -print "FS_UPLOAD_COM?=$$fs_upload_com\n"; -my $$val = $$v{'recipe.hooks.core.prebuild.1.pattern'}; -$$val =~ s/bash -c "(.+)"/$$1/; -$$val =~ s/(#define .+0x)(\`)/"\\$$1\"$$2/; -$$val =~ s/(\\)//; -print "CORE_PREBUILD=$$val\n"; -print "SKETCH_PREBUILD=$$v{'recipe.hooks.sketch.prebuild.1.pattern'}\n"; -print "VTABLE_FLAGS?=$$v{'build.vtable_flags'}\n"; -print "LINK_PREBUILD=$$v{'recipe.hooks.linking.prelink.1.pattern'}\n"; -print "MEM_FLASH=$$v{'recipe.size.regex'}\n"; -print "MEM_RAM=$$v{'recipe.size.regex.data'}\n"; -$$flash_info = $$v{'menu.FlashSize.' . $$flashSize} || $$v{'menu.eesz.' . $$flashSize}; -print "FLASH_INFO=$$flash_info\n"; -print "LWIP_INFO=", $$v{'menu.LwIPVariant.' . $$lwipvariant} || $$v{'menu.ip.' . $$lwipvariant}, "\n"; -endef -export PARSE_ARDUINO - -# Convert memory information -define MEM_USAGE -$$fp = shift; -$$rp = shift; -while (<>) { - $$r += $$1 if /$$rp/; - $$f += $$1 if /$$fp/; -} -print "\nMemory usage\n"; -print sprintf(" %-6s %6d bytes\n" x 2 ."\n", "Ram:", $$r, "Flash:", $$f); -endef -export MEM_USAGE diff --git a/makeEspArduino.mk.old b/makeEspArduino.mk.old new file mode 100644 index 00000000..b09091e9 --- /dev/null +++ b/makeEspArduino.mk.old @@ -0,0 +1,617 @@ +#==================================================================================== +# makeESPArduino +# +# A makefile for ESP8286 and ESP32 Arduino projects. +# +# License: LGPL 2.1 +# General and full license information is available at: +# https://github.com/plerup/makeEspArduino +# +# Copyright (c) 2016-2018 Peter Lerup. All rights reserved. +# +#==================================================================================== + +#==================================================================================== +# Project specific values +#==================================================================================== + +# Include possible project makefile. This can be used to override the defaults below +-include $(firstword $(PROJ_CONF) $(dir $(SKETCH))config.mk) + +#=== Default values not available in the Arduino configuration files + +CHIP ?= esp8266 + +# Set chip specific default board unless specified +BOARD ?= $(if $(filter $(CHIP), esp32),esp32,generic) + +# Serial flashing parameters +UPLOAD_PORT ?= $(shell ls -1tr /dev/tty*USB* 2>/dev/null | tail -1) +UPLOAD_PORT := $(if $(UPLOAD_PORT),$(UPLOAD_PORT),/dev/ttyS0) + +# OTA parameters +OTA_ADDR ?= +OTA_PORT ?= $(if $(filter $(CHIP), esp32),3232,8266) +OTA_PWD ?= + +OTA_ARGS = --progress --ip="$(OTA_ADDR)" --port="$(OTA_PORT)" + +ifneq ($(OTA_PWD),) + OTA_ARGS += --auth="$(OTA_PWD)" +endif + +# HTTP update parameters +HTTP_ADDR ?= +HTTP_URI ?= /update +HTTP_PWD ?= user +HTTP_USR ?= password + +# Output directory +BUILD_ROOT ?= /tmp/mkESP +BUILD_DIR ?= $(BUILD_ROOT)/$(MAIN_NAME)_$(BOARD) + +# File system source directory +FS_DIR ?= $(dir $(SKETCH))data +FS_REST_DIR ?= $(BUILD_DIR)/file_system + +# Bootloader +BOOT_LOADER ?= $(ESP_ROOT)/bootloaders/eboot/eboot.elf + +#==================================================================================== +# Standard build logic and values +#==================================================================================== + +START_TIME := $(shell date +%s) +OS ?= $(shell uname -s) + +# Utility functions +git_description = $(shell git -C $(1) describe --tags --always --dirty 2>/dev/null || echo Unknown) +time_string = $(shell date +$(1)) +ifeq ($(OS), Darwin) + find_files = $(shell find -E $2 -regex ".*\.($1)" | sed 's/\/\//\//') +else + find_files = $(shell find $2 -regextype posix-egrep -regex ".*\.($1)") +endif + +# ESP Arduino directories +ifndef ESP_ROOT + # Location not defined, find and use possible version in the Arduino IDE installation + ifeq ($(OS), Windows_NT) + ARDUINO_ROOT = $(shell cygpath -m $(LOCALAPPDATA)/Arduino15) + else ifeq ($(OS), Darwin) + ARDUINO_ROOT = $(HOME)/Library/Arduino15 + else + ARDUINO_ROOT = $(HOME)/.arduino15 + endif + ARDUINO_ESP_ROOT = $(ARDUINO_ROOT)/packages/$(CHIP) + ESP_ROOT := $(lastword $(wildcard $(ARDUINO_ESP_ROOT)/hardware/$(CHIP)/*)) + ifeq ($(ESP_ROOT),) + $(error No installed version of $(CHIP) Arduino found) + endif + ARDUINO_LIBS = $(shell grep -o "sketchbook.path=.*" $(ARDUINO_ROOT)/preferences.txt 2>/dev/null | cut -f2- -d=)/libraries + ESP_ARDUINO_VERSION := $(notdir $(ESP_ROOT)) + # Find used version of compiler and tools + COMP_PATH := $(lastword $(wildcard $(ARDUINO_ESP_ROOT)/tools/xtensa-*/*)) + ESPTOOL_PATH := $(lastword $(wildcard $(ARDUINO_ESP_ROOT)/tools/esptool*/*)) + MKSPIFFS_PATH := $(lastword $(wildcard $(ARDUINO_ESP_ROOT)/tools/mkspiffs/*/*)) +else + # Location defined, assume it is a git clone + ESP_ARDUINO_VERSION = $(call git_description,$(ESP_ROOT)) + MKSPIFFS_PATH := $(lastword $(wildcard $(ESP_ROOT)/tools/mkspiffs/*)) +endif +ESP_LIBS = $(ESP_ROOT)/libraries +SDK_ROOT = $(ESP_ROOT)/tools/sdk +TOOLS_ROOT = $(ESP_ROOT)/tools + +ifeq ($(shell grep -o "$(BOARD).name" $(ESP_ROOT)/boards.txt 2>/dev/null),) + $(error Invalid board: $(BOARD)) +endif + +ifeq ($(wildcard $(ESP_ROOT)/cores/$(CHIP)),) + $(error $(ESP_ROOT) is not a vaild directory for $(CHIP)) +endif + +ESPTOOL ?= $(shell which esptool.py 2>/dev/null || which esptool 2>/dev/null) +ifneq ($(ESPTOOL),) + # esptool exists in path, overide defaults and use it for esp8266 flash operations + ifeq ($(CHIP),esp8266) + ESPTOOL_COM = $(ESPTOOL) + UPLOAD_COM = $(ESPTOOL_PATTERN) -a soft_reset write_flash 0x00000 $(BUILD_DIR)/$(MAIN_NAME).bin + FS_UPLOAD_COM = $(ESPTOOL_PATTERN) -a soft_reset write_flash $(SPIFFS_START) $(FS_IMAGE) + endif +endif +ESPTOOL_PATTERN = echo Using: $(UPLOAD_PORT) @ $(UPLOAD_SPEED) && "$(ESPTOOL_COM)" --baud=$(UPLOAD_SPEED) --port $(UPLOAD_PORT) --chip $(CHIP) + +ifeq ($(MAKECMDGOALS),help) + DEMO=1 +endif +ifdef DEMO + SKETCH := $(if $(filter $(CHIP), esp32),$(ESP_LIBS)/WiFi/examples/WiFiScan/WiFiScan.ino,$(ESP_LIBS)/ESP8266WebServer/examples/HelloServer/HelloServer.ino) +endif +SKETCH ?= $(wildcard *.ino *.pde) +ifeq ($(SKETCH),) + $(error No sketch specified or found. Use "DEMO=1" for testing) +endif +ifeq ($(wildcard $(SKETCH)),) + $(error Sketch $(SKETCH) not found) +endif +SRC_GIT_VERSION := $(call git_description,$(dir $(SKETCH))) + +# Main output definitions +SKETCH_NAME := $(basename $(notdir $(SKETCH))) +MAIN_NAME ?= $(SKETCH_NAME) +MAIN_EXE ?= $(BUILD_DIR)/$(MAIN_NAME).bin +FS_IMAGE ?= $(BUILD_DIR)/FS.spiffs + +ifeq ($(OS), Windows_NT) + # Adjust some paths for cygwin + BUILD_DIR := $(shell cygpath -m $(BUILD_DIR)) + SKETCH := $(shell cygpath -m $(SKETCH)) + ifdef ARDUINO_LIBS + ARDUINO_LIBS := $(shell cygpath -m $(ARDUINO_LIBS)) + endif +endif + +# Build file extensions +OBJ_EXT = .o +DEP_EXT = .d + +# Auto generated makefile with Arduino definitions +ARDUINO_MK = $(BUILD_DIR)/arduino.mk + +# Special tool definitions +OTA_TOOL ?= python $(TOOLS_ROOT)/espota.py +HTTP_TOOL ?= curl + +# Core source files +CORE_DIR = $(ESP_ROOT)/cores/$(CHIP) +CORE_SRC := $(call find_files,S|c|cpp,$(CORE_DIR)) +CORE_OBJ := $(patsubst %,$(BUILD_DIR)/%$(OBJ_EXT),$(notdir $(CORE_SRC))) +CORE_LIB = $(BUILD_DIR)/arduino.ar + +SKETCH_DIR = $(dir $(SKETCH)) +# User defined compilation units and directories +ifeq ($(LIBS),) + # Automatically find directories with header files used by the sketch + LIBS := $(shell perl -e 'use File::Find;@d = split(" ", shift);while (<>) {$$f{"$$1"} = 1 if /^\s*\#include\s+[<"]([^>"]+)/;}find(sub {if ($$f{$$_}){print $$File::Find::dir," ";$$f{$$_}=0;}}, @d);' \ + "$(CUSTOM_LIBS) $(ESP_LIBS) $(ARDUINO_LIBS)" $(SKETCH) $(call find_files,S|c|cpp,$(SKETCH_DIR))) + ifneq ($(findstring /examples/,$(realpath $(SKETCH))),) + # Assume library example sketch, add the library directory unless it is an Arduino basic example + EX_LIB := $(shell perl -e 'print $$ARGV[0] if $$ARGV[0] =~ s/\/examples\/(?!\d\d\.).+//' $(realpath $(SKETCH))) + ifneq ($(EX_LIB),) + ifneq ($(wildcard $(EX_LIB)/src),) + # Library in src sub directory + EX_LIB := $(EX_LIB)/src + else + # Library at root. Avoid getting files from other examples + EXCLUDE_DIRS ?= $(EX_LIB)/examples + endif + LIBS += $(EX_LIB) + endif + endif +endif + +IGNORE_PATTERN := $(foreach dir,$(EXCLUDE_DIRS),$(dir)/%) +USER_INC := $(filter-out $(IGNORE_PATTERN),$(call find_files,h|hpp,$(SKETCH_DIR) $(dir $(LIBS)))) +USER_SRC := $(SKETCH) $(filter-out $(IGNORE_PATTERN),$(call find_files,S|c|cpp$(USER_SRC_PATTERN),$(SKETCH_DIR) $(LIBS))) +# Object file suffix seems to be significant for the linker... +USER_OBJ := $(subst .ino,_.cpp,$(patsubst %,$(BUILD_DIR)/%$(OBJ_EXT),$(notdir $(USER_SRC)))) +USER_DIRS := $(sort $(dir $(USER_SRC))) +USER_INC_DIRS := $(sort $(dir $(USER_INC))) +USER_LIBS := $(filter-out $(IGNORE_PATTERN),$(call find_files,a,$(SKETCH_DIR) $(LIBS))) + +# Use first flash definition for the board as default +FLASH_DEF_MATCH = $(if $(filter $(CHIP), esp32),build\.flash_size=(\S+),menu\.(?:FlashSize|eesz)\.([^\.]+)=(.+)) +FLASH_DEF ?= $(shell cat $(ESP_ROOT)/boards.txt | perl -e 'while (<>) {if (/^$(BOARD)\.$(FLASH_DEF_MATCH)/){ print "$$1"; exit;}}') +# Same method for LwIPVariant +LWIP_VARIANT ?= $(shell cat $(ESP_ROOT)/boards.txt | perl -e 'while (<>) {if (/^$(BOARD)\.menu\.(?:LwIPVariant|ip)\.([^\.=]+)=/){ print "$$1"; exit;}}') + +# Handle possible changed state i.e. make command line parameters or changed git versions +ifeq ($(OS), Darwin) + CMD_LINE := $(shell ps $$PPID -o command | tail -1) +else + CMD_LINE := $(shell tr "\0" " " $(STATE_LOG)) +endif + +# The actual build commands are to be extracted from the Arduino description files +ARDUINO_DESC := $(shell find $(ESP_ROOT) -maxdepth 1 -name "*.txt" | sort) +$(ARDUINO_MK): $(ARDUINO_DESC) $(MAKEFILE_LIST) | $(BUILD_DIR) + perl -e "$$PARSE_ARDUINO" $(BOARD) '$(FLASH_DEF)' '$(OS)' '$(LWIP_VARIANT)' $(ARDUINO_EXTRA_DESC) $(ARDUINO_DESC) >$(ARDUINO_MK) + +-include $(ARDUINO_MK) + +# Compilation directories and path +INCLUDE_DIRS += $(CORE_DIR) $(ESP_ROOT)/variants/$(INCLUDE_VARIANT) $(BUILD_DIR) +C_INCLUDES := $(foreach dir,$(INCLUDE_DIRS) $(USER_INC_DIRS),-I$(dir)) +VPATH += $(shell find $(CORE_DIR) -type d) $(USER_DIRS) + +# Automatically generated build information data +# Makes the build date and git descriptions at the actual build event available as string constants in the program +BUILD_INFO_H = $(BUILD_DIR)/buildinfo.h +BUILD_INFO_CPP = $(BUILD_DIR)/buildinfo.c++ +BUILD_INFO_OBJ = $(BUILD_INFO_CPP)$(OBJ_EXT) + +$(BUILD_INFO_H): | $(BUILD_DIR) + echo "typedef struct { const char *date, *time, *src_version, *env_version;} _tBuildInfo; extern _tBuildInfo _BuildInfo;" >$@ + +# ccache? +ifeq ($(USE_CCACHE), 1) + C_COM_PREFIX = ccache + CPP_COM_PREFIX = $(C_COM_PREFIX) +endif + +# Build rules for the different source file types +$(BUILD_DIR)/%.cpp$(OBJ_EXT): %.cpp $(BUILD_INFO_H) $(ARDUINO_MK) + echo $(' >$(BUILD_INFO_CPP) + echo '_tBuildInfo _BuildInfo = {"$(BUILD_DATE)","$(BUILD_TIME)","$(SRC_GIT_VERSION)","$(ESP_ARDUINO_VERSION)"};' >>$(BUILD_INFO_CPP) + $(CPP_COM) $(BUILD_INFO_CPP) -o $(BUILD_INFO_OBJ) + $(LD_COM) $(LD_EXTRA) + $(GEN_PART_COM) + $(ELF2BIN_COM) + $(SIZE_COM) | perl -e "$$MEM_USAGE" "$(MEM_FLASH)" "$(MEM_RAM)" +ifneq ($(LWIP_INFO),) + printf "LwIPVariant: $(LWIP_INFO)\n" +endif +ifneq ($(FLASH_INFO),) + printf "Flash size: $(FLASH_INFO)\n\n" +endif + perl -e 'print "Build complete. Elapsed time: ", time()-$(START_TIME), " seconds\n\n"' + +upload flash: all + $(UPLOAD_COM) + +ota: all +ifeq ($(OTA_ADDR),) + echo == Error: Address of device must be specified via OTA_ADDR + exit 1 +endif + $(OTA_PRE_COM) + $(OTA_TOOL) $(OTA_ARGS) --file="$(MAIN_EXE)" + +http: all +ifeq ($(HTTP_ADDR),) + echo == Error: Address of device must be specified via HTTP_ADDR + exit 1 +endif + $(HTTP_TOOL) --verbose -F image=@$(MAIN_EXE) --user $(HTTP_USR):$(HTTP_PWD) http://$(HTTP_ADDR)$(HTTP_URI) + echo "\n" + +$(FS_IMAGE): $(ARDUINO_MK) $(wildcard $(FS_DIR)/*) + echo Generating filesystem image: $(FS_IMAGE) + $(MKSPIFFS_COM) + +fs: $(FS_IMAGE) + +upload_fs flash_fs: $(FS_IMAGE) + $(FS_UPLOAD_COM) + +ota_fs: $(FS_IMAGE) +ifeq ($(OTA_ADDR),) + echo == Error: Address of device must be specified via OTA_ADDR + exit 1 +endif + $(OTA_TOOL) $(OTA_ARGS) --spiffs --file="$(FS_IMAGE)" + +run: flash + python -m serial.tools.miniterm --rts=0 --dtr=0 $(UPLOAD_PORT) 115200 + +FLASH_FILE ?= $(BUILD_DIR)/esp_flash.bin +dump_flash: + echo Dumping flash memory to file: $(FLASH_FILE) + $(ESPTOOL_PATTERN) read_flash 0 $(shell perl -e 'shift =~ /(\d+)([MK])/ || die "Invalid memory size\n";$$mem_size=$$1*1024;$$mem_size*=1024 if $$2 eq "M";print $$mem_size;' $(FLASH_DEF)) $(FLASH_FILE) + +dump_fs: + echo Dumping flash file system to directory: $(FS_REST_DIR) + -$(ESPTOOL_PATTERN) read_flash $(SPIFFS_START) $(SPIFFS_SIZE) $(FS_IMAGE) + mkdir -p $(FS_REST_DIR) + echo + echo == Files == + $(RESTSPIFFS_COM) + +restore_flash: + echo Restoring flash memory from file: $(FLASH_FILE) + $(ESPTOOL_PATTERN) -a soft_reset write_flash 0 $(FLASH_FILE) + +erase_flash: + $(ESPTOOL_PATTERN) erase_flash + +LIB_OUT_FILE ?= $(BUILD_DIR)/$(MAIN_NAME).a +.PHONY: lib +lib: $(LIB_OUT_FILE) +$(LIB_OUT_FILE): $(filter-out $(BUILD_DIR)/$(MAIN_NAME)_.cpp$(OBJ_EXT),$(USER_OBJ)) + echo Building library $(LIB_OUT_FILE) + rm -f $(LIB_OUT_FILE) + $(LIB_COM) cru $(LIB_OUT_FILE) $^ + +clean: + echo Removing all build files + rm -rf "$(BUILD_DIR)" $(FILES_TO_CLEAN) + +list_boards: + echo === Available boards === + cat $(ESP_ROOT)/boards.txt | perl -e 'while (<>) { if (/^([\w\-]+)\.name=(.+)/){ print sprintf("%-20s %s\n", $$1,$$2);} }' + +list_lib: + echo === User specific libraries === + perl -e 'foreach (@ARGV) {print "$$_\n"}' "* Include directories:" $(USER_INC_DIRS) "* Library source files:" $(USER_SRC) + +list_flash_defs: + echo === Memory configurations for board: $(BOARD) === + cat $(ESP_ROOT)/boards.txt | perl -e 'while (<>) { if (/^$(BOARD)\.$(FLASH_DEF_MATCH)/){ print sprintf("%-10s %s\n", $$1,$$2);} }' + +list_lwip: + echo === lwip configurations for board: $(BOARD) === + cat $(ESP_ROOT)/boards.txt | perl -e 'while (<>) { if (/^$(BOARD)\.menu\.(?:LwIPVariant|ip)\.(\w+)=(.+)/){ print sprintf("%-10s %s\n", $$1,$$2);} }' + +help: $(ARDUINO_MK) + echo + echo "Generic makefile for building Arduino esp8266 and esp32 projects" + echo "This file can either be used directly or included from another makefile" + echo "" + echo "The following targets are available:" + echo " all (default) Build the project application" + echo " clean Remove all intermediate build files" + echo " lib Build a library with all involved object files" + echo " flash Build and and flash the project application" + echo " flash_fs Build and and flash file system (when applicable)" + echo " ota Build and and flash via OTA" + echo " Params: OTA_ADDR, OTA_PORT and OTA_PWD" + echo " ota_fs Build and and flash file system via OTA" + echo " http Build and and flash via http (curl)" + echo " Params: HTTP_ADDR, HTTP_URI, HTTP_PWD and HTTP_USR" + echo " dump_flash Dump the whole board flash memory to a file" + echo " restore_flash Restore flash memory from a previously dumped file" + echo " dump_fs Extract all files from the flash file system" + echo " Params: FS_DUMP_DIR" + echo " erase_flash Erase the whole flash" + echo " list_lib Show a list of used library files and include paths" + echo "Configurable parameters:" + echo " SKETCH Main source file" + echo " If not specified the first sketch in current" + echo " directory will be used." + echo " LIBS Includes in the sketch file of libraries from within" + echo " the ESP Arduino directories are automatically" + echo " detected. If this is not enough, define this" + echo " variable with all libraries or directories needed." + echo " CHIP Set to esp8266 or esp32. Default: '$(CHIP)'" + echo " BOARD Name of the target board. Default: '$(BOARD)'" + echo " Use 'list_boards' to get list of available ones" + echo " FLASH_DEF Flash partitioning info. Default '$(FLASH_DEF)'" + echo " Use 'list_flash_defs' to get list of available ones" + echo " BUILD_DIR Directory for intermediate build files." + echo " Default '$(BUILD_DIR)'" + echo " BUILD_EXTRA_FLAGS Additional parameters for the compilation commands" + echo " FS_DIR File system root directory" + echo " UPLOAD_PORT Serial flashing port name. Default: '$(UPLOAD_PORT)'" + echo " UPLOAD_SPEED Serial flashing baud rate. Default: '$(UPLOAD_SPEED)'" + echo " FLASH_FILE File name for dump and restore flash operations" + echo " Default: '$(FLASH_FILE)'" + echo " LWIP_VARIANT Use specified variant of the lwip library when applicable" + echo " Use 'list_lwip' to get list of available ones" + echo " Default: $(LWIP_VARIANT) ($(LWIP_INFO))" + echo " VERBOSE Set to 1 to get full printout of the build" + echo " BUILD_THREADS Number of parallel build threads" + echo " Default: Maximum possible, based on number of CPUs" + echo " USE_CCACHE Set to 1 to use ccache in the build" + echo + +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +.PHONY: all +all: $(BUILD_DIR) $(ARDUINO_MK) $(BUILD_INFO_H) prebuild $(MAIN_EXE) + +prebuild: +ifdef USE_PREBUILD + $(CORE_PREBUILD) +endif + $(SKETCH_PREBUILD) + +# Include all available dependencies +-include $(wildcard $(BUILD_DIR)/*$(DEP_EXT)) + +DEFAULT_GOAL ?= all +.DEFAULT_GOAL := $(DEFAULT_GOAL) + +ifeq ($(OS), Darwin) + BUILD_THREADS ?= $(shell sysctl -n hw.ncpu) +else + BUILD_THREADS ?= $(shell nproc) +endif +MAKEFLAGS += -j $(BUILD_THREADS) + +ifndef VERBOSE + # Set silent mode as default + MAKEFLAGS += --silent +endif + +# Inline Perl scripts + +# Parse Arduino definitions and build commands from the descriptions +define PARSE_ARDUINO +my $$board = shift; +my $$flashSize = shift; +my $$os = shift; +$$os =~ s/Windows_NT/windows/; +$$os =~ s/Linux/linux/; +$$os =~ s/Darwin/macosx/; +my $$lwipvariant = shift; +my %v; + +sub def_var { + my ($$name, $$var) = @_; + print "$$var ?= $$v{$$name}\n"; + $$v{$$name} = "\$$($$var)"; +} + +$$v{'runtime.platform.path'} = '$$(ESP_ROOT)'; +$$v{'includes'} = '$$(C_INCLUDES)'; +$$v{'runtime.ide.version'} = '10605'; +$$v{'build.arch'} = uc('$(CHIP)'); +$$v{'build.project_name'} = '$$(MAIN_NAME)'; +$$v{'build.path'} = '$$(BUILD_DIR)'; +$$v{'object_files'} = '$$^ $$(BUILD_INFO_OBJ)'; +$$v{'archive_file_path'} = '$$(CORE_LIB)'; + +foreach my $$fn (@ARGV) { + open($$f, $$fn) || die "Failed to open: $$fn\n"; + while (<$$f>) { + s/\s+$$//; + s/\.esptool_py\./.esptool./g; + next unless /^(\w[\w\-\.]+)=(.*)/; + my ($$key, $$val) =($$1, $$2); + $$board_defined = 1 if $$key eq "$$board.name"; + $$key =~ s/$$board\.menu\.(?:FlashSize|eesz)\.$$flashSize\.//; + $$key =~ s/$$board\.menu\.CpuFrequency\.[^\.]+\.//; + $$key =~ s/$$board\.menu\.(?:FlashFreq|xtal)\.[^\.]+\.//; + $$key =~ s/$$board\.menu\.UploadSpeed\.[^\.]+\.//; + $$key =~ s/$$board\.menu\.baud\.[^\.]+\.//; + $$key =~ s/$$board\.menu\.ResetMethod\.[^\.]+\.//; + $$key =~ s/$$board\.menu\.FlashMode\.[^\.]+\.//; + $$key =~ s/$$board\.menu\.(?:LwIPVariant|ip)\.$$lwipvariant\.//; + $$key =~ s/^$$board\.//; + $$v{$$key} ||= $$val; + $$v{$$1} = $$v{$$key} if $$key =~ /(.+)\.$$os$$/; + } + close($$f); +} +$$v{'runtime.tools.xtensa-lx106-elf-gcc.path'} ||= '$$(COMP_PATH)'; +$$v{'runtime.tools.xtensa-esp32-elf-gcc.path'} ||= '$$(COMP_PATH)'; +$$v{'runtime.tools.esptool.path'} ||= '$$(ESPTOOL_PATH)'; + +die "* Unknown board $$board\n" unless $$board_defined; +print "# Board definitions\n"; +def_var('build.code_debug', 'CORE_DEBUG_LEVEL'); +def_var('build.f_cpu', 'F_CPU'); +def_var('build.flash_mode', 'FLASH_MODE'); +def_var('build.flash_freq', 'FLASH_SPEED'); +def_var('upload.resetmethod', 'UPLOAD_RESET'); +def_var('upload.speed', 'UPLOAD_SPEED'); +def_var('compiler.warning_flags', 'COMP_WARNINGS'); +$$v{'serial.port'} = '$$(UPLOAD_PORT)'; +$$v{'recipe.objcopy.hex.pattern'} =~ s/[^"]+\/bootloaders\/eboot\/eboot.elf/\$$(BOOT_LOADER)/; +$$v{'recipe.objcopy.hex.1.pattern'} =~ s/[^"]+\/bootloaders\/eboot\/eboot.elf/\$$(BOOT_LOADER)/; +$$v{'recipe.hooks.linking.prelink.1.pattern'} =~ s/\{build.vtable_flags\}/\$$(VTABLE_FLAGS)/; +$$v{'tools.esptool.upload.pattern'} =~ s/\{(cmd|path)\}/\{tools.esptool.$$1\}/g; +$$v{'compiler.cpreprocessor.flags'} .= " \$$(C_PRE_PROC_FLAGS)"; +$$v{'build.extra_flags'} .= " \$$(BUILD_EXTRA_FLAGS)"; + +foreach my $$key (sort keys %v) { + while ($$v{$$key} =~/\{/) { + $$v{$$key} =~ s/\{([\w\-\.]+)\}/$$v{$$1}/; + $$v{$$key} =~ s/""//; + } + $$v{$$key} =~ s/ -o\s+$$//; + $$v{$$key} =~ s/(-D\w+=)"([^"]+)"/$$1\\"$$2\\"/g; +} + +print "INCLUDE_VARIANT = $$v{'build.variant'}\n"; +print "# Commands\n"; +print "C_COM=\$$(C_COM_PREFIX) $$v{'recipe.c.o.pattern'}\n"; +print "CPP_COM=\$$(CPP_COM_PREFIX) $$v{'recipe.cpp.o.pattern'}\n"; +print "S_COM=$$v{'recipe.S.o.pattern'}\n"; +print "LIB_COM=\"$$v{'compiler.path'}$$v{'compiler.ar.cmd'}\"\n"; +print "CORE_LIB_COM=$$v{'recipe.ar.pattern'}\n"; +print "LD_COM=$$v{'recipe.c.combine.pattern'}\n"; +print "PART_FILE?=$$1\n" if $$v{'recipe.objcopy.eep.pattern'} =~ /\"([^\"]+\.csv)\"/; +$$v{'recipe.objcopy.eep.pattern'} =~ s/\"([^\"]+\.csv)\"/\$$(PART_FILE)/; +print "GEN_PART_COM=$$v{'recipe.objcopy.eep.pattern'}\n"; +print "ELF2BIN_COM=", $$v{'recipe.objcopy.hex.pattern'} || $$v{'recipe.objcopy.hex.1.pattern'}, "\n"; +print "SIZE_COM=$$v{'recipe.size.pattern'}\n"; +print "ESPTOOL_COM?=$$v{'tools.esptool.path'}/$$v{'tools.esptool.cmd'}\n"; +print "UPLOAD_COM?=$$v{'tools.esptool.upload.pattern'}\n"; + +if ($$v{'build.spiffs_start'}) { + print "SPIFFS_START?=$$v{'build.spiffs_start'}\n"; + my $$spiffs_size = sprintf("0x%X", hex($$v{'build.spiffs_end'})-hex($$v{'build.spiffs_start'})); + print "SPIFFS_SIZE?=$$spiffs_size\n"; +} elsif ($$v{'build.partitions'}) { + print "COMMA=,\n"; + print "SPIFFS_SPEC:=\$$(subst \$$(COMMA), ,\$$(shell grep spiffs \$$(PART_FILE)))\n"; + print "SPIFFS_START:=\$$(word 4,\$$(SPIFFS_SPEC))\n"; + print "SPIFFS_SIZE:=\$$(word 5,\$$(SPIFFS_SPEC))\n"; +} +$$v{'build.spiffs_blocksize'} ||= "4096"; +print "SPIFFS_BLOCK_SIZE?=$$v{'build.spiffs_blocksize'}\n"; +print "MKSPIFFS_COM?=\"\$$(MKSPIFFS_PATH)\" -b \$$(SPIFFS_BLOCK_SIZE) -s \$$(SPIFFS_SIZE) -c \$$(FS_DIR) \$$(FS_IMAGE)\n"; +print "RESTSPIFFS_COM?=\"\$$(MKSPIFFS_PATH)\" -b \$$(SPIFFS_BLOCK_SIZE) -s \$$(SPIFFS_SIZE) -u \$$(FS_REST_DIR) \$$(FS_IMAGE)\n"; + +my $$fs_upload_com = $$v{'tools.esptool.upload.pattern'}; +$$fs_upload_com =~ s/(.+ -ca) .+/$$1 \$$(SPIFFS_START) -cf \$$(FS_IMAGE)/; +$$fs_upload_com =~ s/(.+ --flash_size detect) .+/$$1 \$$(SPIFFS_START) \$$(FS_IMAGE)/; +print "FS_UPLOAD_COM?=$$fs_upload_com\n"; +my $$val = $$v{'recipe.hooks.core.prebuild.1.pattern'}; +$$val =~ s/bash -c "(.+)"/$$1/; +$$val =~ s/(#define .+0x)(\`)/"\\$$1\"$$2/; +$$val =~ s/(\\)//; +print "CORE_PREBUILD=$$val\n"; +print "SKETCH_PREBUILD=$$v{'recipe.hooks.sketch.prebuild.1.pattern'}\n"; +print "VTABLE_FLAGS?=$$v{'build.vtable_flags'}\n"; +print "LINK_PREBUILD=$$v{'recipe.hooks.linking.prelink.1.pattern'}\n"; +print "MEM_FLASH=$$v{'recipe.size.regex'}\n"; +print "MEM_RAM=$$v{'recipe.size.regex.data'}\n"; +$$flash_info = $$v{'menu.FlashSize.' . $$flashSize} || $$v{'menu.eesz.' . $$flashSize}; +print "FLASH_INFO=$$flash_info\n"; +print "LWIP_INFO=", $$v{'menu.LwIPVariant.' . $$lwipvariant} || $$v{'menu.ip.' . $$lwipvariant}, "\n"; +endef +export PARSE_ARDUINO + +# Convert memory information +define MEM_USAGE +$$fp = shift; +$$rp = shift; +while (<>) { + $$r += $$1 if /$$rp/; + $$f += $$1 if /$$fp/; +} +print "\nMemory usage\n"; +print sprintf(" %-6s %6d bytes\n" x 2 ."\n", "Ram:", $$r, "Flash:", $$f); +endef +export MEM_USAGE diff --git a/opensprinkler_server.cpp b/opensprinkler_server.cpp index 389bca8c..37b43320 100644 --- a/opensprinkler_server.cpp +++ b/opensprinkler_server.cpp @@ -1188,7 +1188,7 @@ void server_change_values() { #if defined(ESP8266) char *p = NULL; - extern unsigned long reboot_timer; + extern uint32_t reboot_timer; if(!process_password()) return; if (m_client) p = get_buffer; @@ -1207,7 +1207,8 @@ void server_change_values() if (findKeyVal(p, tmp_buffer, TMP_BUFFER_SIZE, PSTR("rbt"), true) && atoi(tmp_buffer) > 0) { #if defined(ESP8266) - reboot_timer = millis() + 1000; + os.status.safe_reboot = 0; + reboot_timer = os.now_tz() + 2; handle_return(HTML_SUCCESS); #else print_html_standard_header();