✨ Option to reset EEPROM on first run (#23276)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
This commit is contained in:
		| @@ -1837,6 +1837,7 @@ | ||||
| #define EEPROM_BOOT_SILENT    // Keep M503 quiet and only give errors during first load | ||||
| #if ENABLED(EEPROM_SETTINGS) | ||||
|   //#define EEPROM_AUTO_INIT  // Init EEPROM automatically on any errors. | ||||
|   //#define EEPROM_INIT_NOW   // Init EEPROM on first boot after a new build. | ||||
| #endif | ||||
|  | ||||
| // | ||||
|   | ||||
| @@ -36,7 +36,7 @@ | ||||
|  */ | ||||
|  | ||||
| // Change EEPROM version if the structure changes | ||||
| #define EEPROM_VERSION "V85" | ||||
| #define EEPROM_VERSION "V86" | ||||
| #define EEPROM_OFFSET 100 | ||||
|  | ||||
| // Check the integrity of data offsets. | ||||
| @@ -198,20 +198,32 @@ static const feedRate_t _DMF[] PROGMEM = DEFAULT_MAX_FEEDRATE; | ||||
|  */ | ||||
| typedef struct SettingsDataStruct { | ||||
|   char      version[4];                                 // Vnn\0 | ||||
|   #if ENABLED(EEPROM_INIT_NOW) | ||||
|     uint32_t build_hash;                                // Unique build hash | ||||
|   #endif | ||||
|   uint16_t  crc;                                        // Data Checksum | ||||
|  | ||||
|   // | ||||
|   // DISTINCT_E_FACTORS | ||||
|   // | ||||
|   uint8_t   esteppers;                                  // DISTINCT_AXES - LINEAR_AXES | ||||
|   uint8_t e_factors;                                    // DISTINCT_AXES - LINEAR_AXES | ||||
|  | ||||
|   // | ||||
|   // Planner settings | ||||
|   // | ||||
|   planner_settings_t planner_settings; | ||||
|  | ||||
|   xyze_float_t planner_max_jerk;                        // M205 XYZE  planner.max_jerk | ||||
|   float planner_junction_deviation_mm;                  // M205 J     planner.junction_deviation_mm | ||||
|  | ||||
|   // | ||||
|   // Home Offset | ||||
|   // | ||||
|   xyz_pos_t home_offset;                                // M206 XYZ / M665 TPZ | ||||
|  | ||||
|   // | ||||
|   // Hotend Offset | ||||
|   // | ||||
|   #if HAS_HOTEND_OFFSET | ||||
|     xyz_pos_t hotend_offset[HOTENDS - 1];               // M218 XYZ | ||||
|   #endif | ||||
| @@ -649,13 +661,24 @@ void MarlinSettings::postprocess() { | ||||
|  | ||||
|   const char version[4] = EEPROM_VERSION; | ||||
|  | ||||
|   #if ENABLED(EEPROM_INIT_NOW) | ||||
|     constexpr uint32_t strhash32(const char *s, const uint32_t h=0) { | ||||
|       return *s ? strhash32(s + 1, ((h + *s) << (*s & 3)) ^ *s) : h; | ||||
|     } | ||||
|     constexpr uint32_t build_hash = strhash32(__DATE__ __TIME__); | ||||
|   #endif | ||||
|  | ||||
|   bool MarlinSettings::eeprom_error, MarlinSettings::validating; | ||||
|   int MarlinSettings::eeprom_index; | ||||
|   uint16_t MarlinSettings::working_crc; | ||||
|  | ||||
|   bool MarlinSettings::size_error(const uint16_t size) { | ||||
|     if (size != datasize()) { | ||||
|       DEBUG_ERROR_MSG("EEPROM datasize error."); | ||||
|       DEBUG_ERROR_MSG("EEPROM datasize error." | ||||
|         #if ENABLED(MARLIN_DEV_MODE) | ||||
|           " (Actual:", size, " Expected:", datasize(), ")" | ||||
|         #endif | ||||
|       ); | ||||
|       return true; | ||||
|     } | ||||
|     return false; | ||||
| @@ -675,13 +698,17 @@ void MarlinSettings::postprocess() { | ||||
|     // Write or Skip version. (Flash doesn't allow rewrite without erase.) | ||||
|     TERN(FLASH_EEPROM_EMULATION, EEPROM_SKIP, EEPROM_WRITE)(ver); | ||||
|  | ||||
|     EEPROM_SKIP(working_crc); // Skip the checksum slot | ||||
|     #if ENABLED(EEPROM_INIT_NOW) | ||||
|       EEPROM_SKIP(build_hash);  // Skip the hash slot | ||||
|     #endif | ||||
|  | ||||
|     EEPROM_SKIP(working_crc);   // Skip the checksum slot | ||||
|  | ||||
|     working_crc = 0; // clear before first "real data" | ||||
|  | ||||
|     const uint8_t esteppers = COUNT(planner.settings.axis_steps_per_mm) - LINEAR_AXES; | ||||
|     _FIELD_TEST(esteppers); | ||||
|     EEPROM_WRITE(esteppers); | ||||
|     const uint8_t e_factors = DISTINCT_AXES - (LINEAR_AXES); | ||||
|     _FIELD_TEST(e_factors); | ||||
|     EEPROM_WRITE(e_factors); | ||||
|  | ||||
|     // | ||||
|     // Planner Motion | ||||
| @@ -1494,6 +1521,9 @@ void MarlinSettings::postprocess() { | ||||
|       eeprom_index = EEPROM_OFFSET; | ||||
|  | ||||
|       EEPROM_WRITE(version); | ||||
|       #if ENABLED(EEPROM_INIT_NOW) | ||||
|         EEPROM_WRITE(build_hash); | ||||
|       #endif | ||||
|       EEPROM_WRITE(final_crc); | ||||
|  | ||||
|       // Report storage size | ||||
| @@ -1527,9 +1557,6 @@ void MarlinSettings::postprocess() { | ||||
|     char stored_ver[4]; | ||||
|     EEPROM_READ_ALWAYS(stored_ver); | ||||
|  | ||||
|     uint16_t stored_crc; | ||||
|     EEPROM_READ_ALWAYS(stored_crc); | ||||
|  | ||||
|     // Version has to match or defaults are used | ||||
|     if (strncmp(version, stored_ver, 3) != 0) { | ||||
|       if (stored_ver[3] != '\0') { | ||||
| @@ -1543,14 +1570,25 @@ void MarlinSettings::postprocess() { | ||||
|       eeprom_error = true; | ||||
|     } | ||||
|     else { | ||||
|  | ||||
|       // Optionally reset on the first boot after flashing | ||||
|       #if ENABLED(EEPROM_INIT_NOW) | ||||
|         uint32_t stored_hash; | ||||
|         EEPROM_READ_ALWAYS(stored_hash); | ||||
|         if (stored_hash != build_hash) { EEPROM_FINISH(); return true; } | ||||
|       #endif | ||||
|  | ||||
|       uint16_t stored_crc; | ||||
|       EEPROM_READ_ALWAYS(stored_crc); | ||||
|  | ||||
|       float dummyf = 0; | ||||
|       working_crc = 0;  // Init to 0. Accumulated by EEPROM_READ | ||||
|  | ||||
|       _FIELD_TEST(esteppers); | ||||
|       _FIELD_TEST(e_factors); | ||||
|  | ||||
|       // Number of esteppers may change | ||||
|       uint8_t esteppers; | ||||
|       EEPROM_READ_ALWAYS(esteppers); | ||||
|       // Number of e_factors may change | ||||
|       uint8_t e_factors; | ||||
|       EEPROM_READ_ALWAYS(e_factors); | ||||
|  | ||||
|       // | ||||
|       // Planner Motion | ||||
| @@ -1558,16 +1596,16 @@ void MarlinSettings::postprocess() { | ||||
|       { | ||||
|         // Get only the number of E stepper parameters previously stored | ||||
|         // Any steppers added later are set to their defaults | ||||
|         uint32_t tmp1[LINEAR_AXES + esteppers]; | ||||
|         float tmp2[LINEAR_AXES + esteppers]; | ||||
|         feedRate_t tmp3[LINEAR_AXES + esteppers]; | ||||
|         uint32_t tmp1[LINEAR_AXES + e_factors]; | ||||
|         float tmp2[LINEAR_AXES + e_factors]; | ||||
|         feedRate_t tmp3[LINEAR_AXES + e_factors]; | ||||
|         EEPROM_READ((uint8_t *)tmp1, sizeof(tmp1)); // max_acceleration_mm_per_s2 | ||||
|         EEPROM_READ(planner.settings.min_segment_time_us); | ||||
|         EEPROM_READ((uint8_t *)tmp2, sizeof(tmp2)); // axis_steps_per_mm | ||||
|         EEPROM_READ((uint8_t *)tmp3, sizeof(tmp3)); // max_feedrate_mm_s | ||||
|  | ||||
|         if (!validating) LOOP_DISTINCT_AXES(i) { | ||||
|           const bool in = (i < esteppers + LINEAR_AXES); | ||||
|           const bool in = (i < e_factors + LINEAR_AXES); | ||||
|           planner.settings.max_acceleration_mm_per_s2[i] = in ? tmp1[i] : pgm_read_dword(&_DMA[ALIM(i, _DMA)]); | ||||
|           planner.settings.axis_steps_per_mm[i]          = in ? tmp2[i] : pgm_read_float(&_DASU[ALIM(i, _DASU)]); | ||||
|           planner.settings.max_feedrate_mm_s[i]          = in ? tmp3[i] : pgm_read_float(&_DMF[ALIM(i, _DMF)]); | ||||
| @@ -2496,7 +2534,7 @@ void MarlinSettings::postprocess() { | ||||
|       return success; | ||||
|     } | ||||
|     reset(); | ||||
|     #if ENABLED(EEPROM_AUTO_INIT) | ||||
|     #if EITHER(EEPROM_AUTO_INIT, EEPROM_INIT_NOW) | ||||
|       (void)save(); | ||||
|       SERIAL_ECHO_MSG("EEPROM Initialized"); | ||||
|     #endif | ||||
|   | ||||
| @@ -81,10 +81,19 @@ if pioutil.is_pio_build(): | ||||
| 		# | ||||
| 		# Give warnings on every build | ||||
| 		# | ||||
| 		warnfile = os.path.join(env['PROJECT_BUILD_DIR'], build_env, "src", "src", "inc", "Warnings.cpp.o") | ||||
| 		srcpath = os.path.join(env['PROJECT_BUILD_DIR'], build_env, "src", "src") | ||||
| 		warnfile = os.path.join(srcpath, "inc", "Warnings.cpp.o") | ||||
| 		if os.path.exists(warnfile): | ||||
| 			os.remove(warnfile) | ||||
|  | ||||
| 		# | ||||
| 		# Rebuild 'settings.cpp' for EEPROM_INIT_NOW | ||||
| 		# | ||||
| 		if 'EEPROM_INIT_NOW' in env['MARLIN_FEATURES']: | ||||
| 			setfile = os.path.join(srcpath, "module", "settings.cpp.o") | ||||
| 			if os.path.exists(setfile): | ||||
| 				os.remove(setfile) | ||||
|  | ||||
| 		# | ||||
| 		# Check for old files indicating an entangled Marlin (mixing old and new code) | ||||
| 		# | ||||
|   | ||||
		Reference in New Issue
	
	Block a user