From 51e0f2bee34e485d038ad0ca35fca7398a1576de Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Thu, 4 Jan 2018 19:51:18 -0600
Subject: [PATCH] Add MarlinSettings::validate()

---
 .../src/HAL/HAL_AVR/persistent_store_impl.cpp |   4 +-
 .../src/HAL/HAL_DUE/persistent_store_impl.cpp |   4 +-
 .../HAL/HAL_LPC1768/persistent_store_impl.cpp |  13 +-
 .../HAL_STM32F1/persistent_store_flash.cpp    |   8 +-
 .../HAL/HAL_STM32F1/persistent_store_impl.cpp |   8 +-
 .../HAL_TEENSY35_36/persistent_store_impl.cpp |   4 +-
 Marlin/src/HAL/persistent_store_api.h         |   2 +-
 .../eeprom/{M500-M503.cpp => M500-M504.cpp}   |  12 +
 Marlin/src/gcode/gcode.cpp                    |   3 +
 Marlin/src/gcode/gcode.h                      |   3 +
 Marlin/src/module/configuration_store.cpp     | 260 ++++++++++--------
 Marlin/src/module/configuration_store.h       |   9 +-
 12 files changed, 192 insertions(+), 138 deletions(-)
 rename Marlin/src/gcode/eeprom/{M500-M503.cpp => M500-M504.cpp} (87%)

diff --git a/Marlin/src/HAL/HAL_AVR/persistent_store_impl.cpp b/Marlin/src/HAL/HAL_AVR/persistent_store_impl.cpp
index bee8caf833..9d5ddd1bd7 100644
--- a/Marlin/src/HAL/HAL_AVR/persistent_store_impl.cpp
+++ b/Marlin/src/HAL/HAL_AVR/persistent_store_impl.cpp
@@ -38,10 +38,10 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) {
   return false;
 }
 
-bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) {
+bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) {
   do {
     uint8_t c = eeprom_read_byte((unsigned char*)pos);
-    *value = c;
+    if (writing) *value = c;
     crc16(crc, &c, 1);
     pos++;
     value++;
diff --git a/Marlin/src/HAL/HAL_DUE/persistent_store_impl.cpp b/Marlin/src/HAL/HAL_DUE/persistent_store_impl.cpp
index 0239a71638..f5276e045c 100644
--- a/Marlin/src/HAL/HAL_DUE/persistent_store_impl.cpp
+++ b/Marlin/src/HAL/HAL_DUE/persistent_store_impl.cpp
@@ -43,10 +43,10 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) {
   return false;
 }
 
-bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) {
+bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) {
   do {
     uint8_t c = eeprom_read_byte((unsigned char*)pos);
-    *value = c;
+    if (writing) *value = c;
     crc16(crc, &c, 1);
     pos++;
     value++;
diff --git a/Marlin/src/HAL/HAL_LPC1768/persistent_store_impl.cpp b/Marlin/src/HAL/HAL_LPC1768/persistent_store_impl.cpp
index 82fd567ab9..f2f33ba9f1 100644
--- a/Marlin/src/HAL/HAL_LPC1768/persistent_store_impl.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/persistent_store_impl.cpp
@@ -128,7 +128,7 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) {
   return (bytes_written != size);  // return true for any error
 }
 
-bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) {
+bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) {
   UINT bytes_read = 0;
   FRESULT s;
   s = f_lseek(&eeprom_file, pos);
@@ -140,7 +140,15 @@ bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) {
    SERIAL_PROTOCOLLNPAIR(" f_lseek()=", (int)s);
    return true;
   }
-  s = f_read(&eeprom_file, (void *)value, size, &bytes_read);
+  if (writing) {
+    s = f_read(&eeprom_file, (void *)value, size, &bytes_read);
+    crc16(crc, value, size);
+  }
+  else {
+    uint8_t temp[size];
+    s = f_read(&eeprom_file, (void *)temp, size, &bytes_read);
+    crc16(crc, temp, size);
+  }
   if (s) {
    SERIAL_PROTOCOLPAIR(" read_data(", pos);         // This extra chit-chat goes away soon.  But it is helpful
    SERIAL_PROTOCOLPAIR(",", (int)value);           // right now to see errors that are happening in the
@@ -151,7 +159,6 @@ bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) {
    SERIAL_PROTOCOLLNPAIR("\n bytes_read=",  bytes_read);
    return true;
   }
-  crc16(crc, value, size);
   pos = pos + size;
   return bytes_read != size;  // return true for any error
 }
diff --git a/Marlin/src/HAL/HAL_STM32F1/persistent_store_flash.cpp b/Marlin/src/HAL/HAL_STM32F1/persistent_store_flash.cpp
index d8b013ae6c..dff5122964 100644
--- a/Marlin/src/HAL/HAL_STM32F1/persistent_store_flash.cpp
+++ b/Marlin/src/HAL/HAL_STM32F1/persistent_store_flash.cpp
@@ -93,13 +93,13 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) {
   return true;
 }
 
-void read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) {
+void read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) {
   for (uint16_t i = 0; i < size; i++) {
     byte* accessPoint = (byte*)(pageBase + pos + i);
-    value[i] = *accessPoint;
+    uint8_t c = *accessPoint;
+    if (writing) value[i] = c;
+    crc16(crc, &c, 1);
   }
-
-  crc16(crc, value, size);
   pos += ((size + 1) & ~1);
 }
 
diff --git a/Marlin/src/HAL/HAL_STM32F1/persistent_store_impl.cpp b/Marlin/src/HAL/HAL_STM32F1/persistent_store_impl.cpp
index b8d7df7e6e..f5c6ec58bd 100644
--- a/Marlin/src/HAL/HAL_STM32F1/persistent_store_impl.cpp
+++ b/Marlin/src/HAL/HAL_STM32F1/persistent_store_impl.cpp
@@ -62,7 +62,6 @@ bool access_start() {
   return true;
 }
 
-
 bool access_finish(){
   if (!card.cardOK) return false;
   int16_t bytes_written = 0;
@@ -81,11 +80,12 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) {
   return false;
 }
 
-bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) {
+bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) {
   for (int i = 0; i < size; i++) {
-    value[i] = HAL_STM32F1_eeprom_content [pos + i];
+    uint8_t c = HAL_STM32F1_eeprom_content[pos + i];
+    if (writing) value[i] = c`;
+    crc16(crc, &c, 1);
   }
-  crc16(crc, value, size);
   pos += size;
   return false;
 }
diff --git a/Marlin/src/HAL/HAL_TEENSY35_36/persistent_store_impl.cpp b/Marlin/src/HAL/HAL_TEENSY35_36/persistent_store_impl.cpp
index f78a8ec4cd..be0604dae2 100644
--- a/Marlin/src/HAL/HAL_TEENSY35_36/persistent_store_impl.cpp
+++ b/Marlin/src/HAL/HAL_TEENSY35_36/persistent_store_impl.cpp
@@ -38,10 +38,10 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) {
   return false;
 }
 
-bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) {
+bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) {
   do {
     uint8_t c = eeprom_read_byte((unsigned char*)pos);
-    *value = c;
+    if (writing) *value = c;
     crc16(crc, &c, 1);
     pos++;
     value++;
diff --git a/Marlin/src/HAL/persistent_store_api.h b/Marlin/src/HAL/persistent_store_api.h
index ada9e0d88b..642e5712f3 100644
--- a/Marlin/src/HAL/persistent_store_api.h
+++ b/Marlin/src/HAL/persistent_store_api.h
@@ -10,7 +10,7 @@ namespace PersistentStore {
 bool access_start();
 bool access_finish();
 bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc);
-bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc);
+bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing=true);
 
 } // PersistentStore
 } // HAL
diff --git a/Marlin/src/gcode/eeprom/M500-M503.cpp b/Marlin/src/gcode/eeprom/M500-M504.cpp
similarity index 87%
rename from Marlin/src/gcode/eeprom/M500-M503.cpp
rename to Marlin/src/gcode/eeprom/M500-M504.cpp
index 45faa10179..74140eee15 100644
--- a/Marlin/src/gcode/eeprom/M500-M503.cpp
+++ b/Marlin/src/gcode/eeprom/M500-M504.cpp
@@ -55,3 +55,15 @@ void GcodeSuite::M502() {
   }
 
 #endif // !DISABLE_M503
+
+#if ENABLED(EEPROM_SETTINGS)
+  /**
+   * M504: Validate EEPROM Contents
+   */
+  void GcodeSuite::M504() {
+    if (settings.validate()) {
+      SERIAL_ECHO_START();
+      SERIAL_ECHOLNPGM("EEPROM OK");
+    }
+  }
+#endif
diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp
index 31d628d859..70e396f4ab 100644
--- a/Marlin/src/gcode/gcode.cpp
+++ b/Marlin/src/gcode/gcode.cpp
@@ -610,6 +610,9 @@ void GcodeSuite::process_parsed_command() {
       #if DISABLED(DISABLE_M503)
         case 503: M503(); break;  // M503: print settings currently in memory
       #endif
+      #if ENABLED(EEPROM_SETTINGS)
+        case 504: M504(); break;  // M504: Validate EEPROM contents
+      #endif
 
       #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
         case 540: M540(); break;  // M540: Set abort on endstop hit for SD printing
diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h
index 377c948b68..823ba44d62 100644
--- a/Marlin/src/gcode/gcode.h
+++ b/Marlin/src/gcode/gcode.h
@@ -681,6 +681,9 @@ private:
   #if DISABLED(DISABLE_M503)
     static void M503();
   #endif
+  #if ENABLED(EEPROM_SETTINGS)
+    static void M504();
+  #endif
 
   #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
     static void M540();
diff --git a/Marlin/src/module/configuration_store.cpp b/Marlin/src/module/configuration_store.cpp
index 57a12f3223..4415a043a6 100644
--- a/Marlin/src/module/configuration_store.cpp
+++ b/Marlin/src/module/configuration_store.cpp
@@ -289,12 +289,13 @@ void MarlinSettings::postprocess() {
   #define EEPROM_FINISH() HAL::PersistentStore::access_finish()
   #define EEPROM_SKIP(VAR) eeprom_index += sizeof(VAR)
   #define EEPROM_WRITE(VAR) HAL::PersistentStore::write_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc)
-  #define EEPROM_READ(VAR) HAL::PersistentStore::read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc)
+  #define EEPROM_READ(VAR) HAL::PersistentStore::read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc, !validating)
+  #define EEPROM_READ_ALWAYS(VAR) HAL::PersistentStore::read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc)
   #define EEPROM_ASSERT(TST,ERR) if (!(TST)) do{ SERIAL_ERROR_START(); SERIAL_ERRORLNPGM(ERR); eeprom_read_error = true; }while(0)
 
   const char version[4] = EEPROM_VERSION;
 
-  bool MarlinSettings::eeprom_error;
+  bool MarlinSettings::eeprom_error, MarlinSettings::validating;
 
   #if ENABLED(AUTO_BED_LEVELING_UBL)
     int16_t MarlinSettings::meshes_begin;
@@ -718,6 +719,9 @@ void MarlinSettings::postprocess() {
       for (uint8_t q = MAX_EXTRUDERS * 2; q--;) EEPROM_WRITE(dummy);
     #endif
 
+    //
+    // Validate CRC
+    //
     if (!eeprom_error) {
       #if ENABLED(EEPROM_CHITCHAT)
         const int eeprom_size = eeprom_index;
@@ -741,6 +745,9 @@ void MarlinSettings::postprocess() {
     }
     EEPROM_FINISH();
 
+    //
+    // UBL Mesh
+    //
     #if ENABLED(UBL_SAVE_ACTIVE_ON_M500)
       if (ubl.storage_slot >= 0)
         store_mesh(ubl.storage_slot);
@@ -752,16 +759,16 @@ void MarlinSettings::postprocess() {
   /**
    * M501 - Retrieve Configuration
    */
-  bool MarlinSettings::load() {
+  bool MarlinSettings::_load() {
     uint16_t working_crc = 0;
 
     EEPROM_START();
 
     char stored_ver[4];
-    EEPROM_READ(stored_ver);
+    EEPROM_READ_ALWAYS(stored_ver);
 
     uint16_t stored_crc;
-    EEPROM_READ(stored_crc);
+    EEPROM_READ_ALWAYS(stored_crc);
 
     // Version has to match or defaults are used
     if (strncmp(version, stored_ver, 3) != 0) {
@@ -775,7 +782,8 @@ void MarlinSettings::postprocess() {
         SERIAL_ECHOPAIR("(EEPROM=", stored_ver);
         SERIAL_ECHOLNPGM(" Marlin=" EEPROM_VERSION ")");
       #endif
-      reset();
+      if (!validating) reset();
+      eeprom_error = true;
     }
     else {
       float dummy = 0;
@@ -787,7 +795,7 @@ void MarlinSettings::postprocess() {
 
       // Number of esteppers may change
       uint8_t esteppers;
-      EEPROM_READ(esteppers);
+      EEPROM_READ_ALWAYS(esteppers);
 
       //
       // Planner Motion
@@ -802,7 +810,7 @@ void MarlinSettings::postprocess() {
       EEPROM_READ(tmp1);
       EEPROM_READ(tmp2);
       EEPROM_READ(tmp3);
-      LOOP_XYZE_N(i) {
+      if (!validating) LOOP_XYZE_N(i) {
         planner.axis_steps_per_mm[i]          = i < XYZ + esteppers ? tmp1[i] : def1[i < COUNT(def1) ? i : COUNT(def1) - 1];
         planner.max_feedrate_mm_s[i]          = i < XYZ + esteppers ? tmp2[i] : def2[i < COUNT(def2) ? i : COUNT(def2) - 1];
         planner.max_acceleration_mm_per_s2[i] = i < XYZ + esteppers ? tmp3[i] : def3[i < COUNT(def3) ? i : COUNT(def3) - 1];
@@ -851,21 +859,23 @@ void MarlinSettings::postprocess() {
 
       bool leveling_is_on;
       uint8_t mesh_num_x, mesh_num_y;
-      EEPROM_READ(leveling_is_on);
+      EEPROM_READ_ALWAYS(leveling_is_on);
       EEPROM_READ(dummy);
-      EEPROM_READ(mesh_num_x);
-      EEPROM_READ(mesh_num_y);
+      EEPROM_READ_ALWAYS(mesh_num_x);
+      EEPROM_READ_ALWAYS(mesh_num_y);
 
       #if ENABLED(MESH_BED_LEVELING)
-        mbl.has_mesh = leveling_is_on;
-        mbl.z_offset = dummy;
+        if (!validating) {
+          mbl.has_mesh = leveling_is_on;
+          mbl.z_offset = dummy;
+        }
         if (mesh_num_x == GRID_MAX_POINTS_X && mesh_num_y == GRID_MAX_POINTS_Y) {
           // EEPROM data fits the current mesh
           EEPROM_READ(mbl.z_values);
         }
         else {
           // EEPROM data is stale
-          mbl.reset();
+          if (!validating) mbl.reset();
           for (uint16_t q = mesh_num_x * mesh_num_y; q--;) EEPROM_READ(dummy);
         }
       #else
@@ -893,11 +903,11 @@ void MarlinSettings::postprocess() {
       //
 
       uint8_t grid_max_x, grid_max_y;
-      EEPROM_READ(grid_max_x);                       // 1 byte
-      EEPROM_READ(grid_max_y);                       // 1 byte
+      EEPROM_READ_ALWAYS(grid_max_x);                       // 1 byte
+      EEPROM_READ_ALWAYS(grid_max_y);                       // 1 byte
       #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
         if (grid_max_x == GRID_MAX_POINTS_X && grid_max_y == GRID_MAX_POINTS_Y) {
-          set_bed_leveling_enabled(false);
+          if (!validating) set_bed_leveling_enabled(false);
           EEPROM_READ(bilinear_grid_spacing);        // 2 ints
           EEPROM_READ(bilinear_start);               // 2 ints
           EEPROM_READ(z_values);                     // 9 to 256 floats
@@ -989,7 +999,7 @@ void MarlinSettings::postprocess() {
           EEPROM_READ(dummy); // Kp
           if (e < HOTENDS && dummy != DUMMY_PID_VALUE) {
             // do not need to scale PID values as the values in EEPROM are already scaled
-            PID_PARAM(Kp, e) = dummy;
+            if (!validating) PID_PARAM(Kp, e) = dummy;
             EEPROM_READ(PID_PARAM(Ki, e));
             EEPROM_READ(PID_PARAM(Kd, e));
             #if ENABLED(PID_EXTRUSION_SCALING)
@@ -1023,7 +1033,7 @@ void MarlinSettings::postprocess() {
       #if ENABLED(PIDTEMPBED)
         EEPROM_READ(dummy); // bedKp
         if (dummy != DUMMY_PID_VALUE) {
-          thermalManager.bedKp = dummy;
+          if (!validating) thermalManager.bedKp = dummy;
           EEPROM_READ(thermalManager.bedKi);
           EEPROM_READ(thermalManager.bedKd);
         }
@@ -1068,7 +1078,8 @@ void MarlinSettings::postprocess() {
 
         for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
           EEPROM_READ(dummy);
-          if (q < COUNT(planner.filament_size)) planner.filament_size[q] = dummy;
+          if (!validating && q < COUNT(planner.filament_size))
+            planner.filament_size[q] = dummy;
         }
 
       #else
@@ -1081,55 +1092,48 @@ void MarlinSettings::postprocess() {
       //
       // TMC2130 Stepper Current
       //
-
-      uint16_t val;
       #if HAS_TRINAMIC
+        #define SET_CURR(N,Q) stepper##Q.setCurrent(val[N], R_SENSE, HOLD_MULTIPLIER)
+        uint16_t val[11];
         EEPROM_READ(val);
-        #if X_IS_TRINAMIC
-          stepperX.setCurrent(val, R_SENSE, HOLD_MULTIPLIER);
-        #endif
-        EEPROM_READ(val);
-        #if Y_IS_TRINAMIC
-          stepperY.setCurrent(val, R_SENSE, HOLD_MULTIPLIER);
-        #endif
-        EEPROM_READ(val);
-        #if Z_IS_TRINAMIC
-          stepperZ.setCurrent(val, R_SENSE, HOLD_MULTIPLIER);
-        #endif
-        EEPROM_READ(val);
-        #if X2_IS_TRINAMIC
-          stepperX2.setCurrent(val, R_SENSE, HOLD_MULTIPLIER);
-        #endif
-        EEPROM_READ(val);
-        #if Y2_IS_TRINAMIC
-          stepperY2.setCurrent(val, R_SENSE, HOLD_MULTIPLIER);
-        #endif
-        EEPROM_READ(val);
-        #if Z2_IS_TRINAMIC
-          stepperZ2.setCurrent(val, R_SENSE, HOLD_MULTIPLIER);
-        #endif
-        EEPROM_READ(val);
-        #if E0_IS_TRINAMIC
-          stepperE0.setCurrent(val, R_SENSE, HOLD_MULTIPLIER);
-        #endif
-        EEPROM_READ(val);
-        #if E1_IS_TRINAMIC
-          stepperE1.setCurrent(val, R_SENSE, HOLD_MULTIPLIER);
-        #endif
-        EEPROM_READ(val);
-        #if E2_IS_TRINAMIC
-          stepperE2.setCurrent(val, R_SENSE, HOLD_MULTIPLIER);
-        #endif
-        EEPROM_READ(val);
-        #if E3_IS_TRINAMIC
-          stepperE3.setCurrent(val, R_SENSE, HOLD_MULTIPLIER);
-        #endif
-        EEPROM_READ(val);
-        #if E4_IS_TRINAMIC
-          stepperE4.setCurrent(val, R_SENSE, HOLD_MULTIPLIER);
-        #endif
+        if (!validating) {
+          #if X_IS_TRINAMIC
+            SET_CURR(0, X);
+          #endif
+          #if Y_IS_TRINAMIC
+            SET_CURR(1, Y);
+          #endif
+          #if Z_IS_TRINAMIC
+            SET_CURR(2, Z);
+          #endif
+          #if X2_IS_TRINAMIC
+            SET_CURR(3, X2);
+          #endif
+          #if Y2_IS_TRINAMIC
+            SET_CURR(4, Y2);
+          #endif
+          #if Z2_IS_TRINAMIC
+            SET_CURR(5, Z2);
+          #endif
+          #if E0_IS_TRINAMIC
+            SET_CURR(6, E0);
+          #endif
+          #if E1_IS_TRINAMIC
+            SET_CURR(7, E1);
+          #endif
+          #if E2_IS_TRINAMIC
+            SET_CURR(8, E2);
+          #endif
+          #if E3_IS_TRINAMIC
+            SET_CURR(9, E3);
+          #endif
+          #if E4_IS_TRINAMIC
+            SET_CURR(10, E4);
+          #endif
+        }
       #else
-        for (uint8_t q = 11; q--;) EEPROM_READ(val);
+        uint16_t val;
+        for (uint8_t q=11; q--;) EEPROM_READ(val);
       #endif
 
       /*
@@ -1140,19 +1144,23 @@ void MarlinSettings::postprocess() {
       int16_t thrs;
       #if ENABLED(SENSORLESS_HOMING)
         EEPROM_READ(thrs);
-        #if ENABLED(X_IS_TMC2130)
-          stepperX.sgt(thrs);
-        #endif
-        #if ENABLED(X2_IS_TMC2130)
-          stepperX2.sgt(thrs);
-        #endif
+        if (!validating) {
+          #if ENABLED(X_IS_TMC2130)
+            stepperX.sgt(thrs);
+          #endif
+          #if ENABLED(X2_IS_TMC2130)
+            stepperX2.sgt(thrs);
+          #endif
+        }
         EEPROM_READ(thrs);
-        #if ENABLED(Y_IS_TMC2130)
-          stepperY.sgt(thrs);
-        #endif
-        #if ENABLED(Y2_IS_TMC2130)
-          stepperY2.sgt(thrs);
-        #endif
+        if (!validating) {
+          #if ENABLED(Y_IS_TMC2130)
+            stepperY.sgt(thrs);
+          #endif
+          #if ENABLED(Y2_IS_TMC2130)
+            stepperY2.sgt(thrs);
+          #endif
+        }
       #else
         for (uint8_t q = 0; q < 2; q++) EEPROM_READ(thrs);
       #endif
@@ -1185,7 +1193,7 @@ void MarlinSettings::postprocess() {
       //
 
       #if ENABLED(CNC_COORDINATE_SYSTEMS)
-        (void)gcode.select_coordinate_system(-1); // Go back to machine space
+        if (!validating) (void)gcode.select_coordinate_system(-1); // Go back to machine space
         EEPROM_READ(gcode.coordinate_system);                  // 27 floats
       #else
         for (uint8_t q = 27; q--;) EEPROM_READ(dummy);
@@ -1215,25 +1223,27 @@ void MarlinSettings::postprocess() {
       #if ENABLED(ADVANCED_PAUSE_FEATURE)
         for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
           EEPROM_READ(dummy);
-          if (q < COUNT(filament_change_unload_length)) filament_change_unload_length[q] = dummy;
+          if (!validating && q < COUNT(filament_change_unload_length)) filament_change_unload_length[q] = dummy;
         }
         for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
           EEPROM_READ(dummy);
-          if (q < COUNT(filament_change_load_length)) filament_change_load_length[q] = dummy;
+          if (!validating && q < COUNT(filament_change_load_length)) filament_change_load_length[q] = dummy;
         }
       #else
         for (uint8_t q = MAX_EXTRUDERS * 2; q--;) EEPROM_READ(dummy);
       #endif
 
       if (working_crc == stored_crc) {
-        postprocess();
-        #if ENABLED(EEPROM_CHITCHAT)
-          SERIAL_ECHO_START();
-          SERIAL_ECHO(version);
-          SERIAL_ECHOPAIR(" stored settings retrieved (", eeprom_index - (EEPROM_OFFSET));
-          SERIAL_ECHOPAIR(" bytes; crc ", (uint32_t)working_crc);
-          SERIAL_ECHOLNPGM(")");
-        #endif
+        if (!validating) {
+          postprocess();
+          #if ENABLED(EEPROM_CHITCHAT)
+            SERIAL_ECHO_START();
+            SERIAL_ECHO(version);
+            SERIAL_ECHOPAIR(" stored settings retrieved (", eeprom_index - (EEPROM_OFFSET));
+            SERIAL_ECHOPAIR(" bytes; crc ", (uint32_t)working_crc);
+            SERIAL_ECHOLNPGM(")");
+          #endif
+        }
       }
       else {
         #if ENABLED(EEPROM_CHITCHAT)
@@ -1253,46 +1263,62 @@ void MarlinSettings::postprocess() {
                                                       // disrupting the mesh data
         ubl.report_state();
 
-        if (!ubl.sanity_check()) {
-          SERIAL_EOL();
-          #if ENABLED(EEPROM_CHITCHAT)
-            ubl.echo_name();
-            SERIAL_ECHOLNPGM(" initialized.\n");
-          #endif
-        }
-        else {
-          #if ENABLED(EEPROM_CHITCHAT)
-            SERIAL_PROTOCOLPGM("?Can't enable ");
-            ubl.echo_name();
-            SERIAL_PROTOCOLLNPGM(".");
-          #endif
-          ubl.reset();
-        }
+        if (!validating) {
+          if (!ubl.sanity_check()) {
+            SERIAL_EOL();
+            #if ENABLED(EEPROM_CHITCHAT)
+              ubl.echo_name();
+              SERIAL_ECHOLNPGM(" initialized.\n");
+            #endif
+          }
+          else {
+            eeprom_error = true;
+            #if ENABLED(EEPROM_CHITCHAT)
+              SERIAL_PROTOCOLPGM("?Can't enable ");
+              ubl.echo_name();
+              SERIAL_PROTOCOLLNPGM(".");
+            #endif
+            ubl.reset();
+          }
 
-        if (ubl.storage_slot >= 0) {
-          load_mesh(ubl.storage_slot);
-          #if ENABLED(EEPROM_CHITCHAT)
-            SERIAL_ECHOPAIR("Mesh ", ubl.storage_slot);
-            SERIAL_ECHOLNPGM(" loaded from storage.");
-          #endif
-        }
-        else {
-          ubl.reset();
-          #if ENABLED(EEPROM_CHITCHAT)
-            SERIAL_ECHOLNPGM("UBL System reset()");
-          #endif
+          if (ubl.storage_slot >= 0) {
+            load_mesh(ubl.storage_slot);
+            #if ENABLED(EEPROM_CHITCHAT)
+              SERIAL_ECHOPAIR("Mesh ", ubl.storage_slot);
+              SERIAL_ECHOLNPGM(" loaded from storage.");
+            #endif
+          }
+          else {
+            ubl.reset();
+            #if ENABLED(EEPROM_CHITCHAT)
+              SERIAL_ECHOLNPGM("UBL System reset()");
+            #endif
+          }
         }
       #endif
     }
 
     #if ENABLED(EEPROM_CHITCHAT) && DISABLED(DISABLE_M503)
-      report();
+      if (!validating) report();
     #endif
     EEPROM_FINISH();
 
     return !eeprom_error;
   }
 
+  bool MarlinSettings::validate() {
+    validating = true;
+    const bool success = _load();
+    validating = false;
+    return success;
+  }
+
+  bool MarlinSettings::load() {
+    if (validate()) return _load();
+    reset();
+    return true;
+  }
+
   #if ENABLED(AUTO_BED_LEVELING_UBL)
 
     #if ENABLED(EEPROM_CHITCHAT)
diff --git a/Marlin/src/module/configuration_store.h b/Marlin/src/module/configuration_store.h
index d27f374f93..56fd3c2bad 100644
--- a/Marlin/src/module/configuration_store.h
+++ b/Marlin/src/module/configuration_store.h
@@ -30,7 +30,7 @@ class MarlinSettings {
     MarlinSettings() { }
 
     static void reset();
-    static bool save();
+    static bool save();   // Return 'true' if data was saved
 
     FORCE_INLINE static bool init_eeprom() {
       bool success = true;
@@ -48,7 +48,8 @@ class MarlinSettings {
     }
 
     #if ENABLED(EEPROM_SETTINGS)
-      static bool load();
+      static bool load();     // Return 'true' if data was loaded ok
+      static bool validate(); // Return 'true' if EEPROM data is ok
 
       #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
                                          // That can store is enabled
@@ -77,7 +78,8 @@ class MarlinSettings {
     static void postprocess();
 
     #if ENABLED(EEPROM_SETTINGS)
-      static bool eeprom_error;
+
+      static bool eeprom_error, validating;
 
       #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
                                          // That can store is enabled
@@ -87,6 +89,7 @@ class MarlinSettings {
 
       #endif
 
+      static bool _load();
     #endif
 };