Browse Source

✨ Configurations embed and retrieve (#21321)

X-Ryl669 3 years ago
parent
commit
b464a4b1a4

+ 3 - 0
.gitignore

@@ -22,6 +22,9 @@
 # Generated files
 _Version.h
 bdf2u8g
+marlin_config.json
+mczip.h
+*.gen
 
 #
 # OS

+ 8 - 0
Marlin/Configuration_adv.h

@@ -1593,6 +1593,14 @@
     #define SD_FIRMWARE_UPDATE_INACTIVE_VALUE 0xFF
   #endif
 
+  /**
+   * Enable this option if you have more than ~3K of unused flash space.
+   * Marlin will embed all settings in the firmware binary as compressed data.
+   * Use 'M503 C' to write the settings out to the SD Card as 'mc.zip'.
+   * See docs/ConfigEmbedding.md for details on how to use 'mc-apply.py'.
+   */
+  //#define CONFIGURATION_EMBEDDING
+
   // Add an optimized binary file transfer mode, initiated with 'M28 B1'
   //#define BINARY_FILE_TRANSFER
 

+ 18 - 0
Marlin/src/gcode/eeprom/M500-M504.cpp

@@ -25,6 +25,11 @@
 #include "../../core/serial.h"
 #include "../../inc/MarlinConfig.h"
 
+#if ENABLED(CONFIGURATION_EMBEDDING)
+  #include "../../sd/SdBaseFile.h"
+  #include "../../mczip.h"
+#endif
+
 /**
  * M500: Store settings in EEPROM
  */
@@ -50,9 +55,22 @@ void GcodeSuite::M502() {
 
   /**
    * M503: print settings currently in memory
+   *
+   * With CONFIGURATION_EMBEDDING:
+   *   C<flag> : Save the full Marlin configuration to SD Card as "mc.zip"
    */
   void GcodeSuite::M503() {
     (void)settings.report(!parser.boolval('S', true));
+
+    #if ENABLED(CONFIGURATION_EMBEDDING)
+      if (parser.seen_test('C')) {
+        SdBaseFile file;
+        const uint16_t size = sizeof(mc_zip);
+        // Need to create the config size on the SD card
+        if (file.open("mc.zip", O_WRITE|O_CREAT) && file.write(pgm_read_ptr(mc_zip), size) != -1 && file.close())
+          SERIAL_ECHO_MSG("Configuration saved as 'mc.zip'");
+      }
+    #endif
   }
 
 #endif // !DISABLE_M503

+ 21 - 7
Marlin/src/gcode/host/M115.cpp

@@ -24,7 +24,6 @@
 #include "../../inc/MarlinConfig.h"
 #include "../queue.h"           // for getting the command port
 
-
 #if ENABLED(M115_GEOMETRY_REPORT)
   #include "../../module/motion.h"
 #endif
@@ -33,13 +32,25 @@
   #include "../../feature/caselight.h"
 #endif
 
+//#define MINIMAL_CAP_LINES // Don't even mention the disabled capabilities
+
 #if ENABLED(EXTENDED_CAPABILITIES_REPORT)
-  static void cap_line(FSTR_P const name, bool ena=false) {
-    SERIAL_ECHOPGM("Cap:");
-    SERIAL_ECHOF(name);
-    SERIAL_CHAR(':', '0' + ena);
-    SERIAL_EOL();
-  }
+  #if ENABLED(MINIMAL_CAP_LINES)
+    #define cap_line(S,C) if (C) _cap_line(S)
+    static void _cap_line(FSTR_P const name) {
+      SERIAL_ECHOPGM("Cap:");
+      SERIAL_ECHOF(name);
+      SERIAL_ECHOLNPGM(":1");
+    }
+  #else
+    #define cap_line(V...) _cap_line(V)
+    static void _cap_line(FSTR_P const name, bool ena=false) {
+      SERIAL_ECHOPGM("Cap:");
+      SERIAL_ECHOF(name);
+      SERIAL_CHAR(':', '0' + ena);
+      SERIAL_EOL();
+    }
+  #endif
 #endif
 
 /**
@@ -167,6 +178,9 @@ void GcodeSuite::M115() {
     // MEATPACK Compression
     cap_line(F("MEATPACK"), SERIAL_IMPL.has_feature(port, SerialFeature::MeatPack));
 
+    // CONFIG_EXPORT
+    cap_line(F("CONFIG_EXPORT"), ENABLED(CONFIG_EMBED_AND_SAVE_TO_SD));
+
     // Machine Geometry
     #if ENABLED(M115_GEOMETRY_REPORT)
       const xyz_pos_t bmin = { 0, 0, 0 },

+ 6 - 0
Marlin/src/inc/Conditionals_adv.h

@@ -1004,3 +1004,9 @@
 #if EITHER(MEATPACK_ON_SERIAL_PORT_1, MEATPACK_ON_SERIAL_PORT_2)
   #define HAS_MEATPACK 1
 #endif
+
+// AVR are (usually) too limited in resources to store the configuration into the binary
+#if !defined(FORCE_CONFIG_EMBED) && (defined(__AVR__) || DISABLED(SDSUPPORT) || EITHER(SDCARD_READONLY, DISABLE_M503))
+  #undef CONFIGURATION_EMBEDDING
+  #define CANNOT_EMBED_CONFIGURATION defined(__AVR__)
+#endif

+ 4 - 0
Marlin/src/inc/Warnings.cpp

@@ -549,3 +549,7 @@
 #elif !USE_SENSORLESS && ENABLED(USES_DIAG_PINS)
   #warning "Driver DIAG pins must be physically removed unless SENSORLESS_HOMING is enabled. (See https://bit.ly/2ZPRlt0)"
 #endif
+
+#if CANNOT_EMBED_CONFIGURATION
+  #warning "Disabled CONFIGURATION_EMBEDDING because the target usually has less flash storage. Define FORCE_CONFIG_EMBED to override."
+#endif

+ 1 - 1
buildroot/bin/restore_configs

@@ -2,4 +2,4 @@
 
 git checkout Marlin/Configuration*.h 2>/dev/null
 git checkout Marlin/src/pins/ramps/pins_RAMPS.h 2>/dev/null
-rm -f Marlin/_Bootscreen.h Marlin/_Statusscreen.h
+rm -f Marlin/_Bootscreen.h Marlin/_Statusscreen.h marlin_config.json .pio/build/mc.zip

+ 0 - 1
buildroot/share/PlatformIO/scripts/SAMD51_grandcentral_m4.py

@@ -6,7 +6,6 @@ import pioutil
 if pioutil.is_pio_build():
 	from os.path import join, isfile
 	import shutil
-	from pprint import pprint
 
 	Import("env")
 

+ 0 - 0
buildroot/share/PlatformIO/scripts/__init__.py


+ 11 - 76
buildroot/share/PlatformIO/scripts/common-dependencies.py

@@ -192,63 +192,6 @@ if pioutil.is_pio_build():
 				lib_ignore = env.GetProjectOption('lib_ignore') + [feat['lib_ignore']]
 				set_env_field('lib_ignore', lib_ignore)
 
-	#
-	# Find a compiler, considering the OS
-	#
-	ENV_BUILD_PATH = os.path.join(env.Dictionary('PROJECT_BUILD_DIR'), env['PIOENV'])
-	GCC_PATH_CACHE = os.path.join(ENV_BUILD_PATH, ".gcc_path")
-	def search_compiler():
-		try:
-			filepath = env.GetProjectOption('custom_gcc')
-			blab("Getting compiler from env")
-			return filepath
-		except:
-			pass
-
-		if os.path.exists(GCC_PATH_CACHE):
-			with open(GCC_PATH_CACHE, 'r') as f:
-				return f.read()
-
-		# Find the current platform compiler by searching the $PATH
-		# which will be in a platformio toolchain bin folder
-		path_regex = re.escape(env['PROJECT_PACKAGES_DIR'])
-
-		# See if the environment provides a default compiler
-		try:
-			gcc = env.GetProjectOption('custom_deps_gcc')
-		except:
-			gcc = "g++"
-
-		if env['PLATFORM'] == 'win32':
-			path_separator = ';'
-			path_regex += r'.*\\bin'
-			gcc += ".exe"
-		else:
-			path_separator = ':'
-			path_regex += r'/.+/bin'
-
-		# Search for the compiler
-		for pathdir in env['ENV']['PATH'].split(path_separator):
-			if not re.search(path_regex, pathdir, re.IGNORECASE):
-				continue
-			for filepath in os.listdir(pathdir):
-				if not filepath.endswith(gcc):
-					continue
-				# Use entire path to not rely on env PATH
-				filepath = os.path.sep.join([pathdir, filepath])
-				# Cache the g++ path to no search always
-				if os.path.exists(ENV_BUILD_PATH):
-					with open(GCC_PATH_CACHE, 'w+') as f:
-						f.write(filepath)
-
-				return filepath
-
-		filepath = env.get('CXX')
-		if filepath == 'CC':
-			filepath = gcc
-		blab("Couldn't find a compiler! Fallback to %s" % filepath)
-		return filepath
-
 	#
 	# Use the compiler to get a list of all enabled features
 	#
@@ -257,25 +200,8 @@ if pioutil.is_pio_build():
 			return
 
 		# Process defines
-		build_flags = env.get('BUILD_FLAGS')
-		build_flags = env.ParseFlagsExtended(build_flags)
-
-		cxx = search_compiler()
-		cmd = ['"' + cxx + '"']
-
-		# Build flags from board.json
-		#if 'BOARD' in env:
-		#	cmd += [env.BoardConfig().get("build.extra_flags")]
-		for s in build_flags['CPPDEFINES']:
-			if isinstance(s, tuple):
-				cmd += ['-D' + s[0] + '=' + str(s[1])]
-			else:
-				cmd += ['-D' + s]
-
-		cmd += ['-D__MARLIN_DEPS__ -w -dM -E -x c++ buildroot/share/PlatformIO/scripts/common-dependencies.h']
-		cmd = ' '.join(cmd)
-		blab(cmd, 4)
-		define_list = subprocess.check_output(cmd, shell=True).splitlines()
+		from preprocessor import run_preprocessor
+		define_list = run_preprocessor(env)
 		marlin_features = {}
 		for define in define_list:
 			feature = define[8:].strip().decode().split(' ')
@@ -310,9 +236,18 @@ if pioutil.is_pio_build():
 	except:
 		pass
 
+	#
 	# Add a method for other PIO scripts to query enabled features
+	#
 	env.AddMethod(MarlinFeatureIsEnabled)
 
+	#
 	# Add dependencies for enabled Marlin features
+	#
 	apply_features_config()
 	force_ignore_unused_libs()
+
+	#print(env.Dump())
+
+	from signature import compute_build_signature
+	compute_build_signature(env)

Some files were not shown because too many files changed in this diff