1
0
mirror of https://github.com/MarlinFirmware/Marlin.git synced 2024-11-27 13:56:24 +00:00

🚸 Improve EEPROM validation (#25860)

This commit is contained in:
Scott Lahteine 2023-05-19 23:30:48 -05:00
parent 62a7bba225
commit 09247e7ea9
19 changed files with 210 additions and 101 deletions

View File

@ -192,6 +192,7 @@
#define STR_ERR_LONG_EXTRUDE_STOP " too long extrusion prevented"
#define STR_ERR_HOTEND_TOO_COLD "Hotend too cold"
#define STR_ERR_EEPROM_WRITE "Error writing to EEPROM!"
#define STR_ERR_EEPROM_CORRUPT "EEPROM Corrupt"
#define STR_FILAMENT_CHANGE_HEAT_LCD "Press button to heat nozzle"
#define STR_FILAMENT_CHANGE_INSERT_LCD "Insert filament and press button"

View File

@ -414,7 +414,7 @@ namespace Language_de {
LSTR MSG_RESTORE_DEFAULTS = _UxGT("Standardwerte laden");
LSTR MSG_INIT_EEPROM = _UxGT("Werkseinstellungen");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("EEPROM CRC Fehler");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("EEPROM Index Fehler");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("EEPROM Größe Fehler");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("EEPROM Version Fehler");
LSTR MSG_SETTINGS_STORED = _UxGT("Einstell. gespei.");
LSTR MSG_MEDIA_UPDATE = _UxGT("FW Update vom Medium");

View File

@ -445,9 +445,10 @@ namespace Language_en {
LSTR MSG_LOAD_EEPROM = _UxGT("Load Settings");
LSTR MSG_RESTORE_DEFAULTS = _UxGT("Restore Defaults");
LSTR MSG_INIT_EEPROM = _UxGT("Initialize EEPROM");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("EEPROM CRC Error");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("EEPROM Index Error");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("EEPROM Version Error");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("Err: EEPROM CRC");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("Err: EEPROM Size");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("Err: EEPROM Version");
LSTR MSG_ERR_EEPROM_CORRUPT = _UxGT("Err: EEPROM Corrupt");
LSTR MSG_SETTINGS_STORED = _UxGT("Settings Stored");
LSTR MSG_MEDIA_UPDATE = MEDIA_TYPE_EN _UxGT(" Update");
LSTR MSG_RESET_PRINTER = _UxGT("Reset Printer");

View File

@ -315,7 +315,7 @@ namespace Language_es {
LSTR MSG_RESTORE_DEFAULTS = _UxGT("Rest. fábrica");
LSTR MSG_INIT_EEPROM = _UxGT("Inicializar EEPROM");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("Err: EEPROM CRC");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("Err: Índice EEPROM");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("Err: EEPROM Tamaño");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("Err: Versión EEPROM");
LSTR MSG_MEDIA_UPDATE = _UxGT("Actualizar SD/FD");
LSTR MSG_RESET_PRINTER = _UxGT("Resetear Impresora");

View File

@ -317,7 +317,7 @@ namespace Language_gl {
LSTR MSG_RESTORE_DEFAULTS = _UxGT("Rest. Defecto");
LSTR MSG_INIT_EEPROM = _UxGT("Inicializar EEPROM");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("Erro: CRC EEPROM");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("Erro: Índice EEPROM");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("Erro: Tamaño EEPROM");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("Erro: Versión EEPROM");
LSTR MSG_SETTINGS_STORED = _UxGT("Config Gardada");
LSTR MSG_MEDIA_UPDATE = _UxGT("Actualizar SD/FD");

View File

@ -363,7 +363,7 @@ namespace Language_hu {
LSTR MSG_RESTORE_DEFAULTS = _UxGT("Alapértelmezett");
LSTR MSG_INIT_EEPROM = _UxGT("EEPROM inicializálás");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("Hiba: EEPROM CRC");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("Hiba: EEPROM index");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("Hiba: EEPROM mérete");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("Hiba: EEPROM verzió");
LSTR MSG_SETTINGS_STORED = _UxGT("Beállítások mentve");
LSTR MSG_MEDIA_UPDATE = _UxGT("Tároló frissítés");

View File

@ -451,7 +451,7 @@ namespace Language_it {
LSTR MSG_RESTORE_DEFAULTS = _UxGT("Ripristina imp.");
LSTR MSG_INIT_EEPROM = _UxGT("Inizializza EEPROM");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("Err: CRC EEPROM");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("Err: Indice EEPROM");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("Err: Taglia EEPROM");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("Err: Versione EEPROM");
LSTR MSG_SETTINGS_STORED = _UxGT("Impostazioni mem.");
LSTR MSG_MEDIA_UPDATE = _UxGT("Aggiorna media");

View File

@ -317,9 +317,9 @@ namespace Language_ro {
LSTR MSG_LOAD_EEPROM = _UxGT("Load Settings");
LSTR MSG_RESTORE_DEFAULTS = _UxGT("Restore Defaults");
LSTR MSG_INIT_EEPROM = _UxGT("Initialize EEPROM");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("EEPROM CRC Error");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("EEPROM Index Error");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("EEPROM Version Error");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("Err: EEPROM CRC");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("Err: Mărimea EEPROM");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("Err: Versiunea EEPROM");
LSTR MSG_SETTINGS_STORED = _UxGT("Settings Stored");
LSTR MSG_MEDIA_UPDATE = _UxGT("Media Update");
LSTR MSG_RESET_PRINTER = _UxGT("Reset Imprimanta");

View File

@ -454,7 +454,7 @@ namespace Language_ru {
LSTR MSG_INIT_EEPROM = _UxGT("Инициализ. EEPROM");
#endif
LSTR MSG_ERR_EEPROM_CRC = _UxGT("Сбой EEPROM: CRC");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("Сбой EEPROM: индекс");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("Сбой EEPROM: размер");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("Сбой EEPROM: версия");
LSTR MSG_SETTINGS_STORED = _UxGT("Параметры сохранены");
LSTR MSG_MEDIA_UPDATE = _UxGT("Обновление прошивки");

View File

@ -452,7 +452,7 @@ namespace Language_sk {
LSTR MSG_RESTORE_DEFAULTS = _UxGT("Obnoviť nastavenie");
LSTR MSG_INIT_EEPROM = _UxGT("Inicializ. EEPROM");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("Chyba: EEPROM CRC");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("Chyba: EEPROM Index");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("Chyba: Veľkosť EEPROM");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("Chyba: Verzia EEPROM");
LSTR MSG_SETTINGS_STORED = _UxGT("Nastavenie uložené");
LSTR MSG_MEDIA_UPDATE = _UxGT("Aktualiz. z karty");

View File

@ -348,7 +348,7 @@ namespace Language_sv {
LSTR MSG_RESTORE_DEFAULTS = _UxGT("Återställ Standard");
LSTR MSG_INIT_EEPROM = _UxGT("Initiera EEPROM");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("EEPROM CRC Fel");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("EEPROM Index Fel");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("EEPROM Storlek Fel");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("EEPROM Version Fel");
LSTR MSG_SETTINGS_STORED = _UxGT("Inställningar Lagrad");
LSTR MSG_MEDIA_UPDATE = _UxGT("Media Uppdatera");

View File

@ -431,7 +431,7 @@ namespace Language_tr {
LSTR MSG_RESTORE_DEFAULTS = _UxGT("Fabrika Ayarları");
LSTR MSG_INIT_EEPROM = _UxGT("EEPROM'u başlat");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("Hata: EEPROM CRC");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("Hata: EEPROM Indeks");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("Hata: EEPROM Boyutu");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("Hata: EEPROM Sürümü");
LSTR MSG_SETTINGS_STORED = _UxGT("Ayarlar Kaydedildi");
LSTR MSG_MEDIA_UPDATE = _UxGT("SD Güncellemesi");

View File

@ -465,7 +465,7 @@ namespace Language_uk {
LSTR MSG_INIT_EEPROM = _UxGT("Ініціаліз. EEPROM");
#endif
LSTR MSG_ERR_EEPROM_CRC = _UxGT("Збій EEPROM: CRC");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("Збій EEPROM: індекс");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("Збій EEPROM: розмір");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("Збій EEPROM: версія");
LSTR MSG_SETTINGS_STORED = _UxGT("Параметри збережені");
LSTR MSG_MEDIA_UPDATE = _UxGT("Оновити SD-картку");

View File

@ -317,9 +317,9 @@ namespace Language_zh_CN {
LSTR MSG_LOAD_EEPROM = _UxGT("装载设置"); // "Load memory"
LSTR MSG_RESTORE_DEFAULTS = _UxGT("恢复安全值"); // "Restore Defaults"
LSTR MSG_INIT_EEPROM = _UxGT("初始化设置"); // "Initialize EEPROM"
LSTR MSG_ERR_EEPROM_CRC = _UxGT("EEPROM CRC 错误");
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("EEPROM Index 错误");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("EEPROM Version 错误");
LSTR MSG_ERR_EEPROM_CRC = _UxGT("EEPROM 校验和 错误");
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("EEPROM 尺寸 错误");
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("EEPROM 版本 错误");
LSTR MSG_SETTINGS_STORED = _UxGT("设置已保存");
LSTR MSG_MEDIA_UPDATE = _UxGT("存储器更新");
LSTR MSG_RESET_PRINTER = _UxGT("复位打印机");

View File

@ -299,8 +299,8 @@ namespace Language_zh_TW {
LSTR MSG_RESTORE_DEFAULTS = _UxGT("恢復安全值"); // "Restore failsafe"
LSTR MSG_INIT_EEPROM = _UxGT("初始化設置"); // "Initialize EEPROM"
LSTR MSG_ERR_EEPROM_CRC = _UxGT("錯誤: EEPROM CRC"); // "Err: EEPROM CRC"
LSTR MSG_ERR_EEPROM_INDEX = _UxGT("錯誤: EEPROM Index"); // "Err: EEPROM Index"
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("錯誤: EEPROM Version"); // "EEPROM Version"
LSTR MSG_ERR_EEPROM_SIZE = _UxGT("錯誤: EEPROM 尺寸"); // "Err: EEPROM Index"
LSTR MSG_ERR_EEPROM_VERSION = _UxGT("錯誤: EEPROM 版本"); // "EEPROM Version"
LSTR MSG_MEDIA_UPDATE = _UxGT("媒體更新"); // "Media Update"
LSTR MSG_RESET_PRINTER = _UxGT("重置打印機"); // "Reset Printer
LSTR MSG_REFRESH = _UxGT("刷新"); // "Refresh"

View File

@ -1899,18 +1899,22 @@ void MarlinUI::init() {
#if DISABLED(EEPROM_AUTO_INIT)
static inline FSTR_P eeprom_err(const uint8_t msgid) {
switch (msgid) {
default:
case 0: return GET_TEXT_F(MSG_ERR_EEPROM_CRC);
case 1: return GET_TEXT_F(MSG_ERR_EEPROM_INDEX);
case 2: return GET_TEXT_F(MSG_ERR_EEPROM_VERSION);
static inline FSTR_P eeprom_err(const EEPROM_Error err) {
switch (err) {
case ERR_EEPROM_VERSION: return GET_TEXT_F(MSG_ERR_EEPROM_VERSION);
case ERR_EEPROM_SIZE: return GET_TEXT_F(MSG_ERR_EEPROM_SIZE);
case ERR_EEPROM_CRC: return GET_TEXT_F(MSG_ERR_EEPROM_CRC);
case ERR_EEPROM_CORRUPT: return GET_TEXT_F(MSG_ERR_EEPROM_CORRUPT);
default: return nullptr;
}
}
void MarlinUI::eeprom_alert(const uint8_t msgid) {
void MarlinUI::eeprom_alert(const EEPROM_Error err) {
FSTR_P const err_msg = eeprom_err(err);
set_status(err_msg);
TERN_(HOST_PROMPT_SUPPORT, hostui.notify(err_msg));
#if HAS_MARLINUI_MENU
editable.uint8 = msgid;
editable.uint8 = err;
goto_screen([]{
FSTR_P const restore_msg = GET_TEXT_F(MSG_INIT_EEPROM);
char msg[utf8_strlen(restore_msg) + 1];
@ -1918,11 +1922,9 @@ void MarlinUI::init() {
MenuItem_confirm::select_screen(
GET_TEXT_F(MSG_BUTTON_RESET), GET_TEXT_F(MSG_BUTTON_IGNORE),
init_eeprom, return_to_status,
eeprom_err(editable.uint8), msg, F("?")
eeprom_err((EEPROM_Error)editable.uint8), msg, F("?")
);
});
#else
set_status(eeprom_err(msgid));
#endif
}

View File

@ -27,6 +27,10 @@
#include "../libs/buzzer.h"
#include "buttons.h"
#if ENABLED(EEPROM_SETTINGS)
#include "../module/settings.h"
#endif
#if ENABLED(TOUCH_SCREEN_CALIBRATION)
#include "tft_io/touch_calibration.h"
#endif
@ -672,12 +676,7 @@ public:
static void load_settings();
static void store_settings();
#endif
#if DISABLED(EEPROM_AUTO_INIT)
static void eeprom_alert(const uint8_t msgid);
static void eeprom_alert_crc() { eeprom_alert(0); }
static void eeprom_alert_index() { eeprom_alert(1); }
static void eeprom_alert_version() { eeprom_alert(2); }
#endif
static void eeprom_alert(const EEPROM_Error) TERN_(EEPROM_AUTO_INIT, {});
#endif
//

View File

@ -36,12 +36,13 @@
*/
// Change EEPROM version if the structure changes
#define EEPROM_VERSION "V87"
#define EEPROM_VERSION "V88"
#define EEPROM_OFFSET 100
// Check the integrity of data offsets.
// Can be disabled for production build.
//#define DEBUG_EEPROM_READWRITE
//#define DEBUG_EEPROM_OBSERVE
#include "settings.h"
@ -207,7 +208,8 @@ typedef struct SettingsDataStruct {
#if ENABLED(EEPROM_INIT_NOW)
uint32_t build_hash; // Unique build hash
#endif
uint16_t crc; // Data Checksum
uint16_t crc; // Data Checksum for validation
uint16_t data_size; // Data Size for validation
//
// DISTINCT_E_FACTORS
@ -250,6 +252,7 @@ typedef struct SettingsDataStruct {
//
float mbl_z_offset; // bedlevel.z_offset
uint8_t mesh_num_x, mesh_num_y; // GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y
uint16_t mesh_check; // Hash to check against X/Y
float mbl_z_values[TERN(MESH_BED_LEVELING, GRID_MAX_POINTS_X, 3)] // bedlevel.z_values
[TERN(MESH_BED_LEVELING, GRID_MAX_POINTS_Y, 3)];
@ -268,6 +271,7 @@ typedef struct SettingsDataStruct {
// AUTO_BED_LEVELING_BILINEAR
//
uint8_t grid_max_x, grid_max_y; // GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y
uint16_t grid_check; // Hash to check against X/Y
xy_pos_t bilinear_grid_spacing, bilinear_start; // G29 L F
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
bed_mesh_t z_values; // G29
@ -716,10 +720,13 @@ void MarlinSettings::postprocess() {
#if ENABLED(EEPROM_SETTINGS)
#define EEPROM_ASSERT(TST,ERR) do{ if (!(TST)) { SERIAL_ERROR_MSG(ERR); eeprom_error = true; } }while(0)
#define EEPROM_ASSERT(TST,ERR) do{ if (!(TST)) { SERIAL_ERROR_MSG(ERR); eeprom_error = ERR_EEPROM_SIZE; } }while(0)
#define TWO_BYTE_HASH(A,B) uint16_t((uint16_t(A ^ 0xC3) << 4) ^ (uint16_t(B ^ 0xC3) << 12))
#if ENABLED(DEBUG_EEPROM_READWRITE)
#define _FIELD_TEST(FIELD) \
SERIAL_ECHOLNPGM("Field: " STRINGIFY(FIELD)); \
EEPROM_ASSERT( \
eeprom_error || eeprom_index == offsetof(SettingsData, FIELD) + EEPROM_OFFSET, \
"Field " STRINGIFY(FIELD) " mismatch." \
@ -728,6 +735,14 @@ void MarlinSettings::postprocess() {
#define _FIELD_TEST(FIELD) NOOP
#endif
#if ENABLED(DEBUG_EEPROM_OBSERVE)
#define EEPROM_READ(V...) do{ SERIAL_ECHOLNPGM("READ: ", F(STRINGIFY(FIRST(V)))); EEPROM_READ_(V); }while(0)
#define EEPROM_READ_ALWAYS(V...) do{ SERIAL_ECHOLNPGM("READ: ", F(STRINGIFY(FIRST(V)))); EEPROM_READ_ALWAYS_(V); }while(0)
#else
#define EEPROM_READ(V...) EEPROM_READ_(V)
#define EEPROM_READ_ALWAYS(V...) EEPROM_READ_ALWAYS_(V)
#endif
const char version[4] = EEPROM_VERSION;
#if ENABLED(EEPROM_INIT_NOW)
@ -737,20 +752,20 @@ void MarlinSettings::postprocess() {
constexpr uint32_t build_hash = strhash32(__DATE__ __TIME__);
#endif
bool MarlinSettings::eeprom_error, MarlinSettings::validating;
bool MarlinSettings::validating;
int MarlinSettings::eeprom_index;
uint16_t MarlinSettings::working_crc;
bool MarlinSettings::size_error(const uint16_t size) {
EEPROM_Error MarlinSettings::size_error(const uint16_t size) {
if (size != datasize()) {
DEBUG_ERROR_MSG("EEPROM datasize error."
#if ENABLED(MARLIN_DEV_MODE)
" (Actual:", size, " Expected:", datasize(), ")"
#endif
);
return true;
return ERR_EEPROM_SIZE;
}
return false;
return ERR_EEPROM_NOERR;
}
/**
@ -762,18 +777,25 @@ void MarlinSettings::postprocess() {
if (!EEPROM_START(EEPROM_OFFSET)) return false;
eeprom_error = false;
EEPROM_Error eeprom_error = ERR_EEPROM_NOERR;
// Write or Skip version. (Flash doesn't allow rewrite without erase.)
TERN(FLASH_EEPROM_EMULATION, EEPROM_SKIP, EEPROM_WRITE)(ver);
#if ENABLED(EEPROM_INIT_NOW)
EEPROM_SKIP(build_hash); // Skip the hash slot
EEPROM_SKIP(build_hash); // Skip the hash slot which will be written later
#endif
EEPROM_SKIP(working_crc); // Skip the checksum slot
working_crc = 0; // clear before first "real data"
//
// Clear after skipping CRC and before writing the CRC'ed data
//
working_crc = 0;
// Write the size of the data structure for use in validation
const uint16_t data_size = datasize();
EEPROM_WRITE(data_size);
const uint8_t e_factors = DISTINCT_AXES - (NUM_AXES);
_FIELD_TEST(e_factors);
@ -875,6 +897,10 @@ void MarlinSettings::postprocess() {
EEPROM_WRITE(mesh_num_x);
EEPROM_WRITE(mesh_num_y);
// Check value for the X/Y values
const uint16_t mesh_check = TWO_BYTE_HASH(mesh_num_x, mesh_num_y);
EEPROM_WRITE(mesh_check);
#if ENABLED(MESH_BED_LEVELING)
EEPROM_WRITE(bedlevel.z_values);
#else
@ -922,6 +948,11 @@ void MarlinSettings::postprocess() {
grid_max_y = TERN(AUTO_BED_LEVELING_BILINEAR, GRID_MAX_POINTS_Y, 3);
EEPROM_WRITE(grid_max_x);
EEPROM_WRITE(grid_max_y);
// Check value for the X/Y values
const uint16_t grid_check = TWO_BYTE_HASH(grid_max_x, grid_max_y);
EEPROM_WRITE(grid_check);
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
EEPROM_WRITE(bedlevel.grid_spacing);
EEPROM_WRITE(bedlevel.grid_start);
@ -1631,7 +1662,7 @@ void MarlinSettings::postprocess() {
//
// Report final CRC and Data Size
//
if (!eeprom_error) {
if (eeprom_error == ERR_EEPROM_NOERR) {
const uint16_t eeprom_size = eeprom_index - (EEPROM_OFFSET),
final_crc = working_crc;
@ -1647,7 +1678,7 @@ void MarlinSettings::postprocess() {
// Report storage size
DEBUG_ECHO_MSG("Settings Stored (", eeprom_size, " bytes; crc ", (uint32_t)final_crc, ")");
eeprom_error |= size_error(eeprom_size);
eeprom_error = size_error(eeprom_size);
}
EEPROM_FINISH();
@ -1659,25 +1690,32 @@ void MarlinSettings::postprocess() {
store_mesh(bedlevel.storage_slot);
#endif
if (!eeprom_error) {
const bool success = (eeprom_error == ERR_EEPROM_NOERR);
if (success) {
LCD_MESSAGE(MSG_SETTINGS_STORED);
TERN_(HOST_PROMPT_SUPPORT, hostui.notify(GET_TEXT_F(MSG_SETTINGS_STORED)));
}
TERN_(EXTENSIBLE_UI, ExtUI::onSettingsStored(!eeprom_error));
TERN_(EXTENSIBLE_UI, ExtUI::onSettingsStored(success));
return !eeprom_error;
return success;
}
/**
* M501 - Retrieve Configuration
*/
bool MarlinSettings::_load() {
if (!EEPROM_START(EEPROM_OFFSET)) return false;
EEPROM_Error MarlinSettings::_load() {
EEPROM_Error eeprom_error = ERR_EEPROM_NOERR;
if (!EEPROM_START(EEPROM_OFFSET)) return eeprom_error;
char stored_ver[4];
EEPROM_READ_ALWAYS(stored_ver);
uint16_t stored_crc;
do { // A block to break out of on error
// Version has to match or defaults are used
if (strncmp(version, stored_ver, 3) != 0) {
if (stored_ver[3] != '\0') {
@ -1685,30 +1723,49 @@ void MarlinSettings::postprocess() {
stored_ver[1] = '\0';
}
DEBUG_ECHO_MSG("EEPROM version mismatch (EEPROM=", stored_ver, " Marlin=" EEPROM_VERSION ")");
LCD_MESSAGE(MSG_ERR_EEPROM_VERSION);
TERN_(HOST_PROMPT_SUPPORT, hostui.notify(GET_TEXT_F(MSG_ERR_EEPROM_VERSION)));
IF_DISABLED(EEPROM_AUTO_INIT, ui.eeprom_alert_version());
eeprom_error = true;
eeprom_error = ERR_EEPROM_VERSION;
break;
}
else {
// Optionally reset on the first boot after flashing
//
// Optionally reset on 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 false; }
if (stored_hash != build_hash) {
eeprom_error = ERR_EEPROM_CORRUPT;
break;
}
#endif
uint16_t stored_crc;
//
// Get the stored CRC to compare at the end
//
EEPROM_READ_ALWAYS(stored_crc);
//
// A temporary float for safe storage
//
float dummyf = 0;
working_crc = 0; // Init to 0. Accumulated by EEPROM_READ
_FIELD_TEST(e_factors);
//
// Init to 0. Accumulated by EEPROM_READ
//
working_crc = 0;
//
// Validate the stored size against the current data structure size
//
uint16_t stored_size;
EEPROM_READ_ALWAYS(stored_size);
if ((eeprom_error = size_error(stored_size))) break;
//
// Extruder Parameter Count
// Number of e_factors may change
//
_FIELD_TEST(e_factors);
uint8_t e_factors;
EEPROM_READ_ALWAYS(e_factors);
@ -1808,16 +1865,28 @@ void MarlinSettings::postprocess() {
//
{
uint8_t mesh_num_x, mesh_num_y;
uint16_t mesh_check;
EEPROM_READ(dummyf);
EEPROM_READ_ALWAYS(mesh_num_x);
EEPROM_READ_ALWAYS(mesh_num_y);
// Check value must correspond to the X/Y values
EEPROM_READ_ALWAYS(mesh_check);
if (mesh_check != TWO_BYTE_HASH(mesh_num_x, mesh_num_y)) {
eeprom_error = ERR_EEPROM_CORRUPT;
break;
}
#if ENABLED(MESH_BED_LEVELING)
if (!validating) bedlevel.z_offset = dummyf;
if (mesh_num_x == (GRID_MAX_POINTS_X) && mesh_num_y == (GRID_MAX_POINTS_Y)) {
// EEPROM data fits the current mesh
EEPROM_READ(bedlevel.z_values);
}
else if (mesh_num_x > (GRID_MAX_POINTS_X) || mesh_num_y > (GRID_MAX_POINTS_Y)) {
eeprom_error = ERR_EEPROM_CORRUPT;
break;
}
else {
// EEPROM data is stale
if (!validating) bedlevel.reset();
@ -1860,6 +1929,15 @@ void MarlinSettings::postprocess() {
uint8_t grid_max_x, grid_max_y;
EEPROM_READ_ALWAYS(grid_max_x); // 1 byte
EEPROM_READ_ALWAYS(grid_max_y); // 1 byte
// Check value must correspond to the X/Y values
uint16_t grid_check;
EEPROM_READ_ALWAYS(grid_check);
if (grid_check != TWO_BYTE_HASH(grid_max_x, grid_max_y)) {
eeprom_error = ERR_EEPROM_CORRUPT;
break;
}
xy_pos_t spacing, start;
EEPROM_READ(spacing); // 2 ints
EEPROM_READ(start); // 2 ints
@ -1869,6 +1947,10 @@ void MarlinSettings::postprocess() {
bedlevel.set_grid(spacing, start);
EEPROM_READ(bedlevel.z_values); // 9 to 256 floats
}
else if (grid_max_x > (GRID_MAX_POINTS_X) || grid_max_y > (GRID_MAX_POINTS_Y)) {
eeprom_error = ERR_EEPROM_CORRUPT;
break;
}
else // EEPROM data is stale
#endif // AUTO_BED_LEVELING_BILINEAR
{
@ -2623,27 +2705,22 @@ void MarlinSettings::postprocess() {
//
// Validate Final Size and CRC
//
eeprom_error = size_error(eeprom_index - (EEPROM_OFFSET));
if (eeprom_error) {
DEBUG_ECHO_MSG("Index: ", eeprom_index - (EEPROM_OFFSET), " Size: ", datasize());
IF_DISABLED(EEPROM_AUTO_INIT, ui.eeprom_alert_index());
const uint16_t eeprom_total = eeprom_index - (EEPROM_OFFSET);
if ((eeprom_error = size_error(eeprom_total))) {
// Handle below and on return
break;
}
else if (working_crc != stored_crc) {
eeprom_error = true;
DEBUG_ERROR_MSG("EEPROM CRC mismatch - (stored) ", stored_crc, " != ", working_crc, " (calculated)!");
LCD_MESSAGE(MSG_ERR_EEPROM_CRC);
TERN_(HOST_EEPROM_CHITCHAT, hostui.notify(GET_TEXT_F(MSG_ERR_EEPROM_CRC)));
IF_DISABLED(EEPROM_AUTO_INIT, ui.eeprom_alert_crc());
eeprom_error = ERR_EEPROM_CRC;
break;
}
else if (!validating) {
DEBUG_ECHO_START();
DEBUG_ECHO(version);
DEBUG_ECHOLNPGM(" stored settings retrieved (", eeprom_index - (EEPROM_OFFSET), " bytes; crc ", (uint32_t)working_crc, ")");
DEBUG_ECHOLNPGM(" stored settings retrieved (", eeprom_total, " bytes; crc ", working_crc, ")");
TERN_(HOST_EEPROM_CHITCHAT, hostui.notify(F("Stored settings retrieved")));
}
if (!validating && !eeprom_error) postprocess();
#if ENABLED(AUTO_BED_LEVELING_UBL)
if (!validating) {
bedlevel.report_state();
@ -2655,7 +2732,7 @@ void MarlinSettings::postprocess() {
#endif
}
else {
eeprom_error = true;
eeprom_error = ERR_EEPROM_CORRUPT;
#if BOTH(EEPROM_CHITCHAT, DEBUG_LEVELING_FEATURE)
DEBUG_ECHOPGM("?Can't enable ");
bedlevel.echo_name();
@ -2674,6 +2751,26 @@ void MarlinSettings::postprocess() {
}
}
#endif
} while(0);
EEPROM_FINISH();
switch (eeprom_error) {
case ERR_EEPROM_NOERR:
if (!validating) postprocess();
break;
case ERR_EEPROM_SIZE:
DEBUG_ECHO_MSG("Index: ", eeprom_index - (EEPROM_OFFSET), " Size: ", datasize());
break;
case ERR_EEPROM_CORRUPT:
DEBUG_ERROR_MSG(STR_ERR_EEPROM_CORRUPT);
break;
case ERR_EEPROM_CRC:
DEBUG_ERROR_MSG("EEPROM CRC mismatch - (stored) ", stored_crc, " != ", working_crc, " (calculated)!");
TERN_(HOST_EEPROM_CHITCHAT, hostui.notify(GET_TEXT_F(MSG_ERR_EEPROM_CRC)));
break;
default: break;
}
#if ENABLED(EEPROM_CHITCHAT) && DISABLED(DISABLE_M503)
@ -2681,9 +2778,7 @@ void MarlinSettings::postprocess() {
if (!validating && TERN1(EEPROM_BOOT_SILENT, IsRunning())) report();
#endif
EEPROM_FINISH();
return !eeprom_error;
return eeprom_error;
}
#ifdef ARCHIM2_SPI_FLASH_EEPROM_BACKUP_SIZE
@ -2693,21 +2788,25 @@ void MarlinSettings::postprocess() {
bool MarlinSettings::validate() {
validating = true;
#ifdef ARCHIM2_SPI_FLASH_EEPROM_BACKUP_SIZE
bool success = _load();
if (!success && restoreEEPROM()) {
EEPROM_Error err = _load();
if (err != ERR_EEPROM_NOERR && restoreEEPROM()) {
SERIAL_ECHOLNPGM("Recovered backup EEPROM settings from SPI Flash");
success = _load();
err = _load();
}
#else
const bool success = _load();
const EEPROM_Error err = _load();
#endif
validating = false;
return success;
if (err) ui.eeprom_alert(err);
return (err == ERR_EEPROM_NOERR);
}
bool MarlinSettings::load() {
if (validate()) {
const bool success = _load();
const EEPROM_Error err = _load();
const bool success = (err == ERR_EEPROM_NOERR);
TERN_(EXTENSIBLE_UI, ExtUI::onSettingsLoaded(success));
return success;
}

View File

@ -29,6 +29,13 @@
#if ENABLED(EEPROM_SETTINGS)
#include "../HAL/shared/eeprom_api.h"
enum EEPROM_Error : uint8_t {
ERR_EEPROM_NOERR,
ERR_EEPROM_VERSION,
ERR_EEPROM_SIZE,
ERR_EEPROM_CRC,
ERR_EEPROM_CORRUPT
};
#endif
class MarlinSettings {
@ -98,7 +105,7 @@ class MarlinSettings {
#if ENABLED(EEPROM_SETTINGS)
static bool eeprom_error, validating;
static bool validating;
#if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
// That can store is enabled
@ -106,8 +113,8 @@ class MarlinSettings {
// live at the very end of the eeprom
#endif
static bool _load();
static bool size_error(const uint16_t size);
static EEPROM_Error _load();
static EEPROM_Error size_error(const uint16_t size);
static int eeprom_index;
static uint16_t working_crc;
@ -130,16 +137,16 @@ class MarlinSettings {
}
template<typename T>
static void EEPROM_READ(T &VAR) {
static void EEPROM_READ_(T &VAR) {
persistentStore.read_data(eeprom_index, (uint8_t *) &VAR, sizeof(VAR), &working_crc, !validating);
}
static void EEPROM_READ(uint8_t *VAR, size_t sizeof_VAR) {
static void EEPROM_READ_(uint8_t *VAR, size_t sizeof_VAR) {
persistentStore.read_data(eeprom_index, VAR, sizeof_VAR, &working_crc, !validating);
}
template<typename T>
static void EEPROM_READ_ALWAYS(T &VAR) {
static void EEPROM_READ_ALWAYS_(T &VAR) {
persistentStore.read_data(eeprom_index, (uint8_t *) &VAR, sizeof(VAR), &working_crc);
}