improved EEPROM-Initialize and recovery, renamed typo in varname and comments by ChatGPT
This commit is contained in:
@@ -1,27 +1,26 @@
|
|||||||
/**
|
/**
|
||||||
* @file config.h
|
* @file config.h
|
||||||
|
* @brief Configuration structures and EEPROM API for ChainLube firmware.
|
||||||
*
|
*
|
||||||
* @brief Header file for configuration settings and EEPROM operations in the ChainLube application.
|
* Defines EEPROM layout versions, configuration and persistence data structures,
|
||||||
|
* and the public functions for storing, loading, formatting and validating
|
||||||
|
* configuration/persistence records.
|
||||||
*
|
*
|
||||||
* This file defines configuration settings for the ChainLube project, including default values,
|
* Notes:
|
||||||
* EEPROM structures, and functions for EEPROM operations. It also defines enums for different sources
|
* - The system always boots with defaults in RAM; EEPROM is optional.
|
||||||
* of speed input, GPS baud rates, and CAN bus sources. Additionally, it includes functions for EEPROM handling
|
* - DTC handling for EEPROM availability and integrity is centralized in EEPROM_Process().
|
||||||
* such as storing, retrieving, and formatting configuration data.
|
|
||||||
*
|
|
||||||
* @author Marcel Peterkau
|
|
||||||
* @date 09.01.2024
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _CONFIG_H_
|
#ifndef _CONFIG_H_
|
||||||
#define _CONFIG_H_
|
#define _CONFIG_H_
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <stdint.h>
|
||||||
#include <Wire.h>
|
|
||||||
#include <I2C_eeprom.h>
|
#include <I2C_eeprom.h>
|
||||||
#include "dtc.h"
|
#include "dtc.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define EEPROM_STRUCTURE_REVISION 4 // Increment this version when changing EEPROM structures
|
// Increment when EEPROM structure changes
|
||||||
|
#define EEPROM_STRUCTURE_REVISION 4
|
||||||
|
|
||||||
#if PCB_REV == 1 || PCB_REV == 2 || PCB_REV == 3
|
#if PCB_REV == 1 || PCB_REV == 2 || PCB_REV == 3
|
||||||
#define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC64
|
#define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC64
|
||||||
@@ -29,9 +28,14 @@
|
|||||||
#define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC256
|
#define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief EEPROM request state machine codes.
|
||||||
|
*
|
||||||
|
* Used by globals.requestEEAction to schedule EEPROM operations.
|
||||||
|
*/
|
||||||
typedef enum EERequest_e
|
typedef enum EERequest_e
|
||||||
{
|
{
|
||||||
EE_IDLE,
|
EE_IDLE = 0,
|
||||||
EE_CFG_SAVE,
|
EE_CFG_SAVE,
|
||||||
EE_CFG_LOAD,
|
EE_CFG_LOAD,
|
||||||
EE_CFG_FORMAT,
|
EE_CFG_FORMAT,
|
||||||
@@ -39,11 +43,13 @@ typedef enum EERequest_e
|
|||||||
EE_PDS_LOAD,
|
EE_PDS_LOAD,
|
||||||
EE_PDS_FORMAT,
|
EE_PDS_FORMAT,
|
||||||
EE_FORMAT_ALL,
|
EE_FORMAT_ALL,
|
||||||
EE_ALL_SAVE
|
EE_ALL_SAVE,
|
||||||
|
EE_REINITIALIZE
|
||||||
} EERequest_t;
|
} EERequest_t;
|
||||||
|
|
||||||
// Structure for persistence data stored in EEPROM
|
/**
|
||||||
|
* @brief Wear-levelled persistence data block.
|
||||||
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint16_t writeCycleCounter;
|
uint16_t writeCycleCounter;
|
||||||
@@ -54,7 +60,9 @@ typedef struct
|
|||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
} persistenceData_t;
|
} persistenceData_t;
|
||||||
|
|
||||||
// Structure for configuration settings stored in EEPROM
|
/**
|
||||||
|
* @brief User configuration stored in EEPROM.
|
||||||
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t EEPROM_Version;
|
uint8_t EEPROM_Version;
|
||||||
@@ -85,7 +93,9 @@ typedef struct
|
|||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
} LubeConfig_t;
|
} LubeConfig_t;
|
||||||
|
|
||||||
// Default configuration settings
|
/**
|
||||||
|
* @brief Factory defaults for configuration (in RAM).
|
||||||
|
*/
|
||||||
const LubeConfig_t LubeConfig_defaults = {
|
const LubeConfig_t LubeConfig_defaults = {
|
||||||
0, 8000, 4000, 320, DEFAULT_PUMP_DOSE, 30, 1, 150, 70, 18, 2000, 25, 500, 10, SOURCE_IMPULSE,
|
0, 8000, 4000, 320, DEFAULT_PUMP_DOSE, 30, 1, 150, 70, 18, 2000, 25, 500, 10, SOURCE_IMPULSE,
|
||||||
BAUD_115200,
|
BAUD_115200,
|
||||||
@@ -100,21 +110,31 @@ const LubeConfig_t LubeConfig_defaults = {
|
|||||||
true,
|
true,
|
||||||
0};
|
0};
|
||||||
|
|
||||||
|
/* ==== Public API ==== */
|
||||||
|
|
||||||
|
// Initialization & main process
|
||||||
void InitEEPROM();
|
void InitEEPROM();
|
||||||
void EEPROM_Process();
|
void EEPROM_Process();
|
||||||
|
|
||||||
|
// Config & persistence access
|
||||||
void StoreConfig_EEPROM();
|
void StoreConfig_EEPROM();
|
||||||
void GetConfig_EEPROM();
|
void GetConfig_EEPROM();
|
||||||
void StorePersistence_EEPROM();
|
void StorePersistence_EEPROM();
|
||||||
void GetPersistence_EEPROM();
|
void GetPersistence_EEPROM();
|
||||||
void FormatConfig_EEPROM();
|
void FormatConfig_EEPROM();
|
||||||
void FormatPersistence_EEPROM();
|
void FormatPersistence_EEPROM();
|
||||||
|
void MovePersistencePage_EEPROM(boolean reset);
|
||||||
|
|
||||||
|
// Utilities
|
||||||
uint32_t Checksum_EEPROM(uint8_t const *data, size_t len);
|
uint32_t Checksum_EEPROM(uint8_t const *data, size_t len);
|
||||||
void dumpEEPROM(uint16_t memoryAddress, uint16_t length);
|
void dumpEEPROM(uint16_t memoryAddress, uint16_t length);
|
||||||
void MovePersistencePage_EEPROM(boolean reset);
|
|
||||||
uint32_t ConfigSanityCheck(bool autocorrect = false);
|
uint32_t ConfigSanityCheck(bool autocorrect = false);
|
||||||
bool validateWiFiString(char *string, size_t size);
|
bool validateWiFiString(char *string, size_t size);
|
||||||
|
|
||||||
|
/* ==== Externals ==== */
|
||||||
|
|
||||||
extern LubeConfig_t LubeConfig;
|
extern LubeConfig_t LubeConfig;
|
||||||
extern persistenceData_t PersistenceData;
|
extern persistenceData_t PersistenceData;
|
||||||
extern uint16_t eePersistenceMarker;
|
extern uint16_t eePersistenceAddress;
|
||||||
|
|
||||||
#endif // _CONFIG_H_
|
#endif // _CONFIG_H_
|
||||||
|
@@ -27,7 +27,7 @@ typedef struct Globals_s
|
|||||||
EERequest_t requestEEAction = EE_IDLE; /**< EEPROM-related request */
|
EERequest_t requestEEAction = EE_IDLE; /**< EEPROM-related request */
|
||||||
char DeviceName[33]; /**< Device name */
|
char DeviceName[33]; /**< Device name */
|
||||||
char FlashVersion[10]; /**< Flash version */
|
char FlashVersion[10]; /**< Flash version */
|
||||||
uint16_t eePersistanceAdress; /**< EEPROM persistence address */
|
uint16_t eePersistenceAddress; /**< EEPROM persistence address */
|
||||||
uint8_t TankPercentage; /**< Tank percentage */
|
uint8_t TankPercentage; /**< Tank percentage */
|
||||||
bool hasDTC; /**< Flag indicating the presence of Diagnostic Trouble Codes (DTC) */
|
bool hasDTC; /**< Flag indicating the presence of Diagnostic Trouble Codes (DTC) */
|
||||||
bool measurementActive; /**< Flag indicating active measurement */
|
bool measurementActive; /**< Flag indicating active measurement */
|
||||||
|
@@ -143,7 +143,7 @@ void sendCANDebugMessage()
|
|||||||
data[5] = (0x01 & globals.hasDTC) | ((0x01 & globals.measurementActive) << 1);
|
data[5] = (0x01 & globals.hasDTC) | ((0x01 & globals.measurementActive) << 1);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
memcpy(&data[1], &globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress));
|
memcpy(&data[1], &globals.eePersistenceAddress, sizeof(globals.eePersistenceAddress));
|
||||||
memcpy(&data[3], &PersistenceData.tankRemain_microL, sizeof(PersistenceData.tankRemain_microL));
|
memcpy(&data[3], &PersistenceData.tankRemain_microL, sizeof(PersistenceData.tankRemain_microL));
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
@@ -1,56 +1,181 @@
|
|||||||
/**
|
/**
|
||||||
* @file config.cpp
|
* @file config.cpp
|
||||||
* @brief Implementation of EEPROM and configuration-related functions.
|
* @brief EEPROM handling and configuration storage for the ChainLube firmware.
|
||||||
*
|
*
|
||||||
* This file contains functions for managing EEPROM storage and handling configuration data.
|
* Responsibilities:
|
||||||
* It includes the definitions of configuration structures, EEPROM access, and utility functions.
|
* - Bring-up of the external I²C EEPROM
|
||||||
|
* - Robust availability checks with optional bus recovery
|
||||||
|
* - Central processing of EEPROM requests (save/load/format/move page)
|
||||||
|
* - CRC32 utilities and debug dump helpers
|
||||||
|
*
|
||||||
|
* Design notes:
|
||||||
|
* - The device boots with sane in-RAM defaults so the system stays operable
|
||||||
|
* even when EEPROM is missing. Actual lube execution is gated by DTCs elsewhere.
|
||||||
|
* - The DTC DTC_NO_EEPROM_FOUND is set/cleared only in EEPROM_Process(), never here ad-hoc.
|
||||||
|
* - Background recovery is non-blocking and driven by millis().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "debugger.h"
|
#include "debugger.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
// Instance of I2C_eeprom for EEPROM access
|
// Recovery edge flag: set when availability changes 0 -> 1
|
||||||
|
static bool eeRecoveredOnce = false;
|
||||||
|
// Non-blocking retry scheduling
|
||||||
|
static uint32_t eeNextTryMs = 0;
|
||||||
|
static uint32_t eeRetryIntervalMs = 2000; // ms between background attempts
|
||||||
|
|
||||||
|
// I²C EEPROM instance
|
||||||
I2C_eeprom ee(0x50, EEPROM_SIZE_BYTES);
|
I2C_eeprom ee(0x50, EEPROM_SIZE_BYTES);
|
||||||
|
|
||||||
// Configuration and persistence data structures
|
// Configuration and persistence data
|
||||||
LubeConfig_t LubeConfig;
|
LubeConfig_t LubeConfig;
|
||||||
persistenceData_t PersistenceData;
|
persistenceData_t PersistenceData;
|
||||||
|
|
||||||
// EEPROM version identifier
|
// EEPROM structure version (bumped when layout changes)
|
||||||
const uint16_t eeVersion = EEPROM_STRUCTURE_REVISION;
|
const uint16_t eeVersion = EEPROM_STRUCTURE_REVISION;
|
||||||
|
|
||||||
// Flag indicating whether EEPROM is available
|
// Latched availability flag
|
||||||
boolean eeAvailable = false;
|
static bool eeAvailable = false;
|
||||||
|
|
||||||
// Offsets within EEPROM for LubeConfig and PersistenceData
|
// EEPROM layout offsets
|
||||||
const uint16_t startofLubeConfig = 16;
|
const uint16_t startofLubeConfig = 16;
|
||||||
const uint16_t startofPersistence = 16 + sizeof(LubeConfig) + (sizeof(LubeConfig) % 16);
|
const uint16_t startofPersistence = 16 + sizeof(LubeConfig) + (sizeof(LubeConfig) % 16);
|
||||||
|
|
||||||
// Function prototype to check EEPROM availability
|
// availability probe
|
||||||
boolean checkEEPROMavailable();
|
bool EEPROM_Available(bool recover = false, uint8_t attempts = 3, uint16_t delay_ms = 25);
|
||||||
|
|
||||||
|
// Robust EEPROM handling (internal helpers)
|
||||||
|
void I2C_BusReset();
|
||||||
|
bool TryRecoverEEPROM(uint8_t attempts = 5, uint16_t delay_ms = 50);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes EEPROM and checks its availability.
|
* @brief Initialize I²C and EEPROM driver, load in-RAM defaults.
|
||||||
*
|
*
|
||||||
* This function initializes the EEPROM using the I2C_eeprom instance and checks if it's available.
|
* Loads defaults into RAM to keep the application operational.
|
||||||
|
* Availability is checked but no DTC is set here—EEPROM_Process() is the single place
|
||||||
|
* that sets/clears DTC_NO_EEPROM_FOUND.
|
||||||
*/
|
*/
|
||||||
void InitEEPROM()
|
void InitEEPROM()
|
||||||
{
|
{
|
||||||
LubeConfig = LubeConfig_defaults;
|
LubeConfig = LubeConfig_defaults;
|
||||||
PersistenceData = {0};
|
PersistenceData = {0};
|
||||||
|
|
||||||
|
Wire.begin();
|
||||||
ee.begin();
|
ee.begin();
|
||||||
checkEEPROMavailable();
|
|
||||||
|
eeAvailable = ee.isConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Processes EEPROM actions based on the request from the global state.
|
* @brief Try to free a stuck I²C bus and enforce a STOP condition.
|
||||||
*
|
*
|
||||||
* This function processes EEPROM actions based on the request from the global state.
|
* Pulses SCL up to 9 times to release a held SDA, then issues a STOP (SDA ↑ while SCL ↑).
|
||||||
* It performs actions such as saving, loading, and formatting EEPROM data for both configuration and persistence.
|
* Finally returns control to Wire.
|
||||||
|
*/
|
||||||
|
void I2C_BusReset()
|
||||||
|
{
|
||||||
|
pinMode(SCL, OUTPUT_OPEN_DRAIN);
|
||||||
|
pinMode(SDA, INPUT_PULLUP);
|
||||||
|
|
||||||
|
for (int i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
digitalWrite(SCL, LOW);
|
||||||
|
delayMicroseconds(5);
|
||||||
|
digitalWrite(SCL, HIGH);
|
||||||
|
delayMicroseconds(5);
|
||||||
|
}
|
||||||
|
pinMode(SDA, OUTPUT_OPEN_DRAIN);
|
||||||
|
digitalWrite(SDA, LOW);
|
||||||
|
delayMicroseconds(5);
|
||||||
|
digitalWrite(SCL, HIGH);
|
||||||
|
delayMicroseconds(5);
|
||||||
|
digitalWrite(SDA, HIGH);
|
||||||
|
delayMicroseconds(5);
|
||||||
|
|
||||||
|
pinMode(SCL, INPUT);
|
||||||
|
pinMode(SDA, INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Attempt to recover EEPROM connectivity.
|
||||||
|
*
|
||||||
|
* Sequence per attempt:
|
||||||
|
* - I²C bus reset
|
||||||
|
* - Wire.begin()
|
||||||
|
* - ee.begin()
|
||||||
|
* - short settle delay
|
||||||
|
*
|
||||||
|
* On first successful probe (0->1) the eeRecoveredOnce flag is raised.
|
||||||
|
*
|
||||||
|
* @param attempts Number of attempts
|
||||||
|
* @param delay_ms Delay between attempts (after ee.begin())
|
||||||
|
* @return true if EEPROM is reachable after recovery, false otherwise
|
||||||
|
*/
|
||||||
|
bool TryRecoverEEPROM(uint8_t attempts, uint16_t delay_ms)
|
||||||
|
{
|
||||||
|
for (uint8_t n = 0; n < attempts; n++)
|
||||||
|
{
|
||||||
|
I2C_BusReset();
|
||||||
|
|
||||||
|
// ESP8266 core: Wire.end() is not available; re-begin is sufficient
|
||||||
|
Wire.begin();
|
||||||
|
delay(2);
|
||||||
|
|
||||||
|
ee.begin();
|
||||||
|
delay(delay_ms);
|
||||||
|
|
||||||
|
if (ee.isConnected())
|
||||||
|
{
|
||||||
|
if (!eeAvailable)
|
||||||
|
eeRecoveredOnce = true; // edge 0 -> 1
|
||||||
|
eeAvailable = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eeAvailable = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Central EEPROM task: background recovery, DTC handling, and request dispatch.
|
||||||
|
*
|
||||||
|
* Called periodically from the main loop. Non-blocking by design.
|
||||||
|
* - Schedules gentle recovery tries based on millis()
|
||||||
|
* - Sets DTC_NO_EEPROM_FOUND when unavailable
|
||||||
|
* - On successful recovery edge, clears DTC and reloads CFG/PDS exactly once
|
||||||
|
* - Executes requested actions (save/load/format/move)
|
||||||
*/
|
*/
|
||||||
void EEPROM_Process()
|
void EEPROM_Process()
|
||||||
{
|
{
|
||||||
|
// Background recovery (single soft attempt per interval)
|
||||||
|
const uint32_t now = millis();
|
||||||
|
if (!EEPROM_Available() && now >= eeNextTryMs)
|
||||||
|
{
|
||||||
|
(void)TryRecoverEEPROM(1, 10);
|
||||||
|
eeNextTryMs = now + eeRetryIntervalMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Central DTC handling
|
||||||
|
if (!EEPROM_Available())
|
||||||
|
{
|
||||||
|
MaintainDTC(DTC_NO_EEPROM_FOUND, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recovery edge: clear DTC and reload persisted data exactly once
|
||||||
|
if (EEPROM_Available() && eeRecoveredOnce)
|
||||||
|
{
|
||||||
|
MaintainDTC(DTC_NO_EEPROM_FOUND, false);
|
||||||
|
GetConfig_EEPROM();
|
||||||
|
GetPersistence_EEPROM();
|
||||||
|
eeRecoveredOnce = false;
|
||||||
|
Debug_pushMessage("EEPROM recovered – reloaded CFG/PDS\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request dispatcher
|
||||||
switch (globals.requestEEAction)
|
switch (globals.requestEEAction)
|
||||||
{
|
{
|
||||||
case EE_CFG_SAVE:
|
case EE_CFG_SAVE:
|
||||||
@@ -58,33 +183,39 @@ void EEPROM_Process()
|
|||||||
globals.requestEEAction = EE_IDLE;
|
globals.requestEEAction = EE_IDLE;
|
||||||
Debug_pushMessage("Stored EEPROM CFG\n");
|
Debug_pushMessage("Stored EEPROM CFG\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EE_CFG_LOAD:
|
case EE_CFG_LOAD:
|
||||||
GetConfig_EEPROM();
|
GetConfig_EEPROM();
|
||||||
globals.requestEEAction = EE_IDLE;
|
globals.requestEEAction = EE_IDLE;
|
||||||
Debug_pushMessage("Loaded EEPROM CFG\n");
|
Debug_pushMessage("Loaded EEPROM CFG\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EE_CFG_FORMAT:
|
case EE_CFG_FORMAT:
|
||||||
FormatConfig_EEPROM();
|
FormatConfig_EEPROM();
|
||||||
globals.requestEEAction = EE_IDLE;
|
globals.requestEEAction = EE_IDLE;
|
||||||
GetConfig_EEPROM();
|
GetConfig_EEPROM();
|
||||||
Debug_pushMessage("Formatted EEPROM CFG\n");
|
Debug_pushMessage("Formatted EEPROM CFG\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EE_PDS_SAVE:
|
case EE_PDS_SAVE:
|
||||||
StorePersistence_EEPROM();
|
StorePersistence_EEPROM();
|
||||||
globals.requestEEAction = EE_IDLE;
|
globals.requestEEAction = EE_IDLE;
|
||||||
Debug_pushMessage("Stored EEPROM PDS\n");
|
Debug_pushMessage("Stored EEPROM PDS\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EE_PDS_LOAD:
|
case EE_PDS_LOAD:
|
||||||
GetPersistence_EEPROM();
|
GetPersistence_EEPROM();
|
||||||
globals.requestEEAction = EE_IDLE;
|
globals.requestEEAction = EE_IDLE;
|
||||||
Debug_pushMessage("Loaded EEPROM PDS\n");
|
Debug_pushMessage("Loaded EEPROM PDS\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EE_PDS_FORMAT:
|
case EE_PDS_FORMAT:
|
||||||
FormatPersistence_EEPROM();
|
FormatPersistence_EEPROM();
|
||||||
globals.requestEEAction = EE_IDLE;
|
globals.requestEEAction = EE_IDLE;
|
||||||
GetPersistence_EEPROM();
|
GetPersistence_EEPROM();
|
||||||
Debug_pushMessage("Formatted EEPROM PDS\n");
|
Debug_pushMessage("Formatted EEPROM PDS\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EE_FORMAT_ALL:
|
case EE_FORMAT_ALL:
|
||||||
FormatConfig_EEPROM();
|
FormatConfig_EEPROM();
|
||||||
FormatPersistence_EEPROM();
|
FormatPersistence_EEPROM();
|
||||||
@@ -93,73 +224,93 @@ void EEPROM_Process()
|
|||||||
globals.requestEEAction = EE_IDLE;
|
globals.requestEEAction = EE_IDLE;
|
||||||
Debug_pushMessage("Formatted EEPROM ALL\n");
|
Debug_pushMessage("Formatted EEPROM ALL\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EE_ALL_SAVE:
|
case EE_ALL_SAVE:
|
||||||
StorePersistence_EEPROM();
|
StorePersistence_EEPROM();
|
||||||
StoreConfig_EEPROM();
|
StoreConfig_EEPROM();
|
||||||
globals.requestEEAction = EE_IDLE;
|
globals.requestEEAction = EE_IDLE;
|
||||||
Debug_pushMessage("Stored EEPROM ALL\n");
|
Debug_pushMessage("Stored EEPROM ALL\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EE_REINITIALIZE:
|
||||||
|
{
|
||||||
|
// quick burst of attempts
|
||||||
|
const bool ok = TryRecoverEEPROM(5, 20);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
// Edge & reload are handled by the block above
|
||||||
|
Debug_pushMessage("EEPROM reinitialize OK\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MaintainDTC(DTC_NO_EEPROM_FOUND, true);
|
||||||
|
Debug_pushMessage("EEPROM reinitialize FAILED\n");
|
||||||
|
}
|
||||||
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case EE_IDLE:
|
case EE_IDLE:
|
||||||
default:
|
default:
|
||||||
globals.requestEEAction = EE_IDLE;
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stores the configuration data in EEPROM.
|
* @brief Store configuration to EEPROM (with CRC and sanity report).
|
||||||
*
|
*
|
||||||
* This function calculates the checksum for the configuration data, updates it, and stores it in EEPROM.
|
* Writes only if EEPROM is available. On completion, DTC_EEPROM_CFG_SANITY is
|
||||||
* It also performs a sanity check on the configuration and raises a diagnostic trouble code (DTC) if needed.
|
* raised if any config fields are out of plausible bounds (bitmask payload).
|
||||||
*/
|
*/
|
||||||
void StoreConfig_EEPROM()
|
void StoreConfig_EEPROM()
|
||||||
{
|
{
|
||||||
LubeConfig.checksum = 0;
|
LubeConfig.checksum = 0;
|
||||||
LubeConfig.checksum = Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig));
|
LubeConfig.checksum = Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig));
|
||||||
|
|
||||||
if (!checkEEPROMavailable())
|
if (!EEPROM_Available())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ee.updateBlock(startofLubeConfig, (uint8_t *)&LubeConfig, sizeof(LubeConfig));
|
ee.updateBlock(startofLubeConfig, (uint8_t *)&LubeConfig, sizeof(LubeConfig));
|
||||||
|
|
||||||
uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false);
|
const uint32_t sanity = ConfigSanityCheck(false);
|
||||||
|
if (sanity > 0)
|
||||||
if (ConfigSanityCheckResult > 0)
|
|
||||||
{
|
{
|
||||||
MaintainDTC(DTC_EEPROM_CFG_SANITY, true, ConfigSanityCheckResult);
|
MaintainDTC(DTC_EEPROM_CFG_SANITY, true, sanity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieves the configuration data from EEPROM.
|
* @brief Load configuration from EEPROM and validate.
|
||||||
*
|
*
|
||||||
* This function reads the configuration data from EEPROM, performs a checksum validation,
|
* Performs CRC check and sanity validation and raises the respective DTCs:
|
||||||
* and conducts a sanity check on the configuration. It raises a diagnostic trouble code (DTC) if needed.
|
* - DTC_EEPROM_CFG_BAD if CRC fails
|
||||||
|
* - DTC_EEPROM_CFG_SANITY with bitmask payload if values are out of bounds
|
||||||
*/
|
*/
|
||||||
void GetConfig_EEPROM()
|
void GetConfig_EEPROM()
|
||||||
{
|
{
|
||||||
if (!checkEEPROMavailable())
|
if (!EEPROM_Available())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ee.readBlock(startofLubeConfig, (uint8_t *)&LubeConfig, sizeof(LubeConfig));
|
ee.readBlock(startofLubeConfig, (uint8_t *)&LubeConfig, sizeof(LubeConfig));
|
||||||
|
|
||||||
uint32_t checksum = LubeConfig.checksum;
|
const uint32_t checksum = LubeConfig.checksum;
|
||||||
LubeConfig.checksum = 0;
|
LubeConfig.checksum = 0;
|
||||||
|
|
||||||
MaintainDTC(DTC_EEPROM_CFG_BAD, (Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig)) != checksum));
|
MaintainDTC(DTC_EEPROM_CFG_BAD,
|
||||||
|
(Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig)) != checksum));
|
||||||
|
|
||||||
LubeConfig.checksum = checksum;
|
LubeConfig.checksum = checksum;
|
||||||
|
|
||||||
uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false);
|
const uint32_t sanity = ConfigSanityCheck(false);
|
||||||
|
MaintainDTC(DTC_EEPROM_CFG_SANITY, (sanity > 0), sanity);
|
||||||
MaintainDTC(DTC_EEPROM_CFG_SANITY, (ConfigSanityCheckResult > 0), ConfigSanityCheckResult);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stores the persistence data in EEPROM.
|
* @brief Store persistence record to EEPROM (wear-levelled page).
|
||||||
*
|
*
|
||||||
* This function increments the write cycle counter, performs a checksum calculation on the persistence data,
|
* Increments the write-cycle counter and moves the page if close to the limit.
|
||||||
* and stores it in EEPROM. It also handles EEPROM page movement when needed.
|
* Writes only if EEPROM is available.
|
||||||
*/
|
*/
|
||||||
void StorePersistence_EEPROM()
|
void StorePersistence_EEPROM()
|
||||||
{
|
{
|
||||||
@@ -171,28 +322,27 @@ void StorePersistence_EEPROM()
|
|||||||
PersistenceData.checksum = 0;
|
PersistenceData.checksum = 0;
|
||||||
PersistenceData.checksum = Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData));
|
PersistenceData.checksum = Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData));
|
||||||
|
|
||||||
if (!checkEEPROMavailable())
|
if (!EEPROM_Available())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ee.updateBlock(globals.eePersistanceAdress, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
|
ee.updateBlock(globals.eePersistenceAddress, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieves the persistence data from EEPROM.
|
* @brief Load persistence record, validating address range and CRC.
|
||||||
*
|
*
|
||||||
* This function reads the EEPROM to get the start address of the persistence data.
|
* If the stored start address is out of range, the persistence partition is reset,
|
||||||
* If the start address is out of range, it resets and stores defaults. Otherwise,
|
* formatted, and DTC_EEPROM_PDSADRESS_BAD is raised.
|
||||||
* it reads from EEPROM and checks if the data is correct.
|
* Otherwise, the record is read and checked; DTC_EEPROM_PDS_BAD is raised on CRC failure.
|
||||||
*/
|
*/
|
||||||
void GetPersistence_EEPROM()
|
void GetPersistence_EEPROM()
|
||||||
{
|
{
|
||||||
if (!checkEEPROMavailable())
|
if (!EEPROM_Available())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ee.readBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress));
|
ee.readBlock(0, (uint8_t *)&globals.eePersistenceAddress, sizeof(globals.eePersistenceAddress));
|
||||||
// if we got the StartAdress of Persistance and it's out of Range - we Reset it and store defaults
|
|
||||||
// otherwise we Read from eeprom and check if everything is correct
|
if (globals.eePersistenceAddress < startofPersistence || globals.eePersistenceAddress > ee.getDeviceSize())
|
||||||
if (globals.eePersistanceAdress < startofPersistence || globals.eePersistanceAdress > ee.getDeviceSize())
|
|
||||||
{
|
{
|
||||||
MovePersistencePage_EEPROM(true);
|
MovePersistencePage_EEPROM(true);
|
||||||
FormatPersistence_EEPROM();
|
FormatPersistence_EEPROM();
|
||||||
@@ -200,74 +350,65 @@ void GetPersistence_EEPROM()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ee.readBlock(globals.eePersistanceAdress, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
|
ee.readBlock(globals.eePersistenceAddress, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
|
||||||
|
|
||||||
uint32_t checksum = PersistenceData.checksum;
|
const uint32_t checksum = PersistenceData.checksum;
|
||||||
PersistenceData.checksum = 0;
|
PersistenceData.checksum = 0;
|
||||||
|
|
||||||
MaintainDTC(DTC_EEPROM_PDS_BAD, (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum));
|
MaintainDTC(DTC_EEPROM_PDS_BAD,
|
||||||
|
(Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum));
|
||||||
|
|
||||||
PersistenceData.checksum = checksum;
|
PersistenceData.checksum = checksum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Formats the configuration partition in EEPROM.
|
* @brief Reset the configuration partition to defaults and write it.
|
||||||
*
|
|
||||||
* This function resets the configuration data to defaults and stores it in EEPROM.
|
|
||||||
*/
|
*/
|
||||||
void FormatConfig_EEPROM()
|
void FormatConfig_EEPROM()
|
||||||
{
|
{
|
||||||
Debug_pushMessage("Formatting Config-Partition\n");
|
Debug_pushMessage("Formatting Config partition\n");
|
||||||
LubeConfig = LubeConfig_defaults;
|
LubeConfig = LubeConfig_defaults;
|
||||||
LubeConfig.EEPROM_Version = eeVersion;
|
LubeConfig.EEPROM_Version = eeVersion;
|
||||||
StoreConfig_EEPROM();
|
StoreConfig_EEPROM();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Formats the persistence partition in EEPROM.
|
* @brief Reset the persistence partition and write an empty record.
|
||||||
*
|
|
||||||
* This function resets the persistence data to defaults and stores it in EEPROM.
|
|
||||||
*/
|
*/
|
||||||
void FormatPersistence_EEPROM()
|
void FormatPersistence_EEPROM()
|
||||||
{
|
{
|
||||||
Debug_pushMessage("Formatting Persistance-Partition\n");
|
Debug_pushMessage("Formatting Persistence partition\n");
|
||||||
PersistenceData = {0};
|
PersistenceData = {0};
|
||||||
// memset(&PersistenceData, 0, sizeof(PersistenceData));
|
|
||||||
StorePersistence_EEPROM();
|
StorePersistence_EEPROM();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Moves the persistence page in EEPROM.
|
* @brief Advance the persistence page (wear levelling) and store the new start address.
|
||||||
*
|
*
|
||||||
* This function adjusts the persistence page address and resets the write cycle counter.
|
* When end-of-device (or reset=true), wrap back to startofPersistence.
|
||||||
|
* Requires EEPROM availability.
|
||||||
*
|
*
|
||||||
* @param reset If true, the function resets the persistence page address to the start of the partition.
|
* @param reset If true, force wrap to the start of the partition.
|
||||||
*/
|
*/
|
||||||
void MovePersistencePage_EEPROM(boolean reset)
|
void MovePersistencePage_EEPROM(boolean reset)
|
||||||
{
|
{
|
||||||
if (!checkEEPROMavailable())
|
if (!EEPROM_Available())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
globals.eePersistanceAdress += sizeof(PersistenceData);
|
globals.eePersistenceAddress += sizeof(PersistenceData);
|
||||||
PersistenceData.writeCycleCounter = 0;
|
PersistenceData.writeCycleCounter = 0;
|
||||||
|
|
||||||
// Check if we reached the end of the EEPROM and start over at the beginning
|
if ((globals.eePersistenceAddress + sizeof(PersistenceData)) > ee.getDeviceSize() || reset)
|
||||||
if ((globals.eePersistanceAdress + sizeof(PersistenceData)) > ee.getDeviceSize() || reset)
|
|
||||||
{
|
{
|
||||||
globals.eePersistanceAdress = startofPersistence;
|
globals.eePersistenceAddress = startofPersistence;
|
||||||
}
|
}
|
||||||
|
|
||||||
ee.updateBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress));
|
ee.updateBlock(0, (uint8_t *)&globals.eePersistenceAddress, sizeof(globals.eePersistenceAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calculate CRC-32 checksum for a block of data.
|
* @brief Compute CRC-32 (poly 0xEDB88320) over a byte buffer.
|
||||||
*
|
|
||||||
* This function implements the CRC-32 algorithm.
|
|
||||||
*
|
|
||||||
* @param data Pointer to the data block.
|
|
||||||
* @param len Length of the data block in bytes.
|
|
||||||
* @return CRC-32 checksum.
|
|
||||||
*/
|
*/
|
||||||
uint32_t Checksum_EEPROM(uint8_t const *data, size_t len)
|
uint32_t Checksum_EEPROM(uint8_t const *data, size_t len)
|
||||||
{
|
{
|
||||||
@@ -275,55 +416,43 @@ uint32_t Checksum_EEPROM(uint8_t const *data, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint32_t crc = 0xFFFFFFFF;
|
uint32_t crc = 0xFFFFFFFF;
|
||||||
uint32_t mask;
|
|
||||||
|
|
||||||
while (len--)
|
while (len--)
|
||||||
{
|
{
|
||||||
crc ^= *data++;
|
crc ^= *data++;
|
||||||
|
|
||||||
for (uint8_t k = 0; k < 8; k++)
|
for (uint8_t k = 0; k < 8; k++)
|
||||||
{
|
crc = (crc >> 1) ^ (0xEDB88320 & (-(int32_t)(crc & 1)));
|
||||||
mask = -(crc & 1);
|
|
||||||
crc = (crc >> 1) ^ (0xEDB88320 & mask);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ~crc;
|
return ~crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Dump a portion of EEPROM contents for debugging.
|
* @brief Print a hex/ASCII dump of a region of the EEPROM for debugging.
|
||||||
*
|
*
|
||||||
* This function prints the contents of a specified portion of EEPROM in a formatted way.
|
* Output format:
|
||||||
*
|
* Address 00 01 02 ... 0F ASCII
|
||||||
* @param memoryAddress Starting address in EEPROM.
|
* 0x00000: XX XX ... .....
|
||||||
* @param length Number of bytes to dump.
|
|
||||||
*/
|
*/
|
||||||
void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
|
void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
|
||||||
{
|
{
|
||||||
#define BLOCK_TO_LENGTH 16
|
#define BLOCK_TO_LENGTH 16
|
||||||
|
|
||||||
if (!checkEEPROMavailable())
|
if (!EEPROM_Available())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char ascii_buf[BLOCK_TO_LENGTH + 1];
|
char ascii_buf[BLOCK_TO_LENGTH + 1];
|
||||||
sprintf(ascii_buf, "%*s", BLOCK_TO_LENGTH, "ASCII");
|
sprintf(ascii_buf, "%*s", BLOCK_TO_LENGTH, "ASCII");
|
||||||
|
|
||||||
// Print column headers
|
|
||||||
Debug_pushMessage(PSTR("\nAddress "));
|
Debug_pushMessage(PSTR("\nAddress "));
|
||||||
for (int x = 0; x < BLOCK_TO_LENGTH; x++)
|
for (int x = 0; x < BLOCK_TO_LENGTH; x++)
|
||||||
Debug_pushMessage("%3d", x);
|
Debug_pushMessage("%3d", x);
|
||||||
|
|
||||||
// Align address and length to BLOCK_TO_LENGTH boundaries
|
memoryAddress = (memoryAddress / BLOCK_TO_LENGTH) * BLOCK_TO_LENGTH;
|
||||||
memoryAddress = memoryAddress / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
|
length = ((length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH) * BLOCK_TO_LENGTH;
|
||||||
length = (length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
|
|
||||||
|
|
||||||
// Iterate through the specified portion of EEPROM
|
|
||||||
for (unsigned int i = 0; i < length; i++)
|
for (unsigned int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
int blockpoint = memoryAddress % BLOCK_TO_LENGTH;
|
const int blockpoint = memoryAddress % BLOCK_TO_LENGTH;
|
||||||
|
|
||||||
// Print ASCII representation header for each block
|
|
||||||
if (blockpoint == 0)
|
if (blockpoint == 0)
|
||||||
{
|
{
|
||||||
ascii_buf[BLOCK_TO_LENGTH] = 0;
|
ascii_buf[BLOCK_TO_LENGTH] = 0;
|
||||||
@@ -331,55 +460,54 @@ void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
|
|||||||
Debug_pushMessage("\n0x%05X:", memoryAddress);
|
Debug_pushMessage("\n0x%05X:", memoryAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and print each byte
|
|
||||||
ascii_buf[blockpoint] = ee.readByte(memoryAddress);
|
ascii_buf[blockpoint] = ee.readByte(memoryAddress);
|
||||||
Debug_pushMessage(" %02X", ascii_buf[blockpoint]);
|
Debug_pushMessage(" %02X", ascii_buf[blockpoint]);
|
||||||
|
|
||||||
// Replace non-printable characters with dots in ASCII representation
|
|
||||||
if (ascii_buf[blockpoint] < 0x20 || ascii_buf[blockpoint] > 0x7E)
|
if (ascii_buf[blockpoint] < 0x20 || ascii_buf[blockpoint] > 0x7E)
|
||||||
ascii_buf[blockpoint] = '.';
|
ascii_buf[blockpoint] = '.';
|
||||||
|
|
||||||
memoryAddress++;
|
memoryAddress++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print a new line at the end of the dump
|
|
||||||
Debug_pushMessage("\n");
|
Debug_pushMessage("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if EEPROM is available and connected.
|
* @brief Unified availability probe with optional recovery.
|
||||||
*
|
*
|
||||||
* This function checks if the EEPROM is available and connected. If not, it triggers
|
* Fast path returns the latched availability flag. If not available,
|
||||||
* a diagnostic trouble code (DTC) indicating the absence of EEPROM.
|
* performs a direct probe and, optionally, a recovery sequence.
|
||||||
*
|
*
|
||||||
|
* @param recover If true, attempt recovery when not available (default: false).
|
||||||
|
* @param attempts Recovery attempts (default: 3).
|
||||||
|
* @param delay_ms Delay between attempts in ms (default: 25).
|
||||||
* @return true if EEPROM is available, false otherwise.
|
* @return true if EEPROM is available, false otherwise.
|
||||||
*/
|
*/
|
||||||
boolean checkEEPROMavailable()
|
bool EEPROM_Available(bool recover, uint8_t attempts, uint16_t delay_ms)
|
||||||
{
|
{
|
||||||
// Check if EEPROM is connected
|
if (eeAvailable)
|
||||||
if (!ee.isConnected())
|
return true;
|
||||||
|
|
||||||
|
if (ee.isConnected())
|
||||||
{
|
{
|
||||||
// Trigger DTC for no EEPROM found
|
eeAvailable = true;
|
||||||
MaintainDTC(DTC_NO_EEPROM_FOUND, true);
|
eeRecoveredOnce = true; // edge 0 -> 1
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear DTC for no EEPROM found since it's available now
|
if (recover)
|
||||||
MaintainDTC(DTC_NO_EEPROM_FOUND, false);
|
{
|
||||||
|
return TryRecoverEEPROM(attempts, delay_ms);
|
||||||
|
}
|
||||||
|
|
||||||
// EEPROM is available
|
return false;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Perform sanity check on configuration settings.
|
* @brief Validate config fields; return bitmask of invalid entries.
|
||||||
*
|
*
|
||||||
* This function checks the validity of various configuration settings and returns a bitmask
|
* If autocorrect is true, invalid fields are reset to default values.
|
||||||
* indicating which settings need to be reset. If autocorrect is enabled, it resets the settings
|
* Each bit in the returned mask identifies a specific field-group that was out-of-bounds.
|
||||||
* to their default values.
|
|
||||||
*
|
|
||||||
* @param autocorrect If true, automatically correct invalid settings by resetting to defaults.
|
|
||||||
* @return A bitmask indicating which settings need to be reset.
|
|
||||||
*/
|
*/
|
||||||
uint32_t ConfigSanityCheck(bool autocorrect)
|
uint32_t ConfigSanityCheck(bool autocorrect)
|
||||||
{
|
{
|
||||||
@@ -513,22 +641,17 @@ uint32_t ConfigSanityCheck(bool autocorrect)
|
|||||||
if (autocorrect)
|
if (autocorrect)
|
||||||
strncpy(LubeConfig.wifi_client_password, LubeConfig_defaults.wifi_client_password, sizeof(LubeConfig.wifi_client_password));
|
strncpy(LubeConfig.wifi_client_password, LubeConfig_defaults.wifi_client_password, sizeof(LubeConfig.wifi_client_password));
|
||||||
}
|
}
|
||||||
// Return the bitmask indicating which settings need to be reset
|
|
||||||
return setting_reset_bits;
|
return setting_reset_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Validates whether a given string contains only characters allowed in WiFi SSIDs and passwords.
|
* @brief Validate that a string contains only characters allowed for Wi‑Fi SSIDs/passwords.
|
||||||
*
|
*
|
||||||
* This function checks each character in the provided string to ensure
|
* Allowed: A‑Z, a‑z, 0‑9 and the printable ASCII punctuation: ! " # $ % & ' ( ) * + , - . / : ;
|
||||||
* that it contains only characters allowed in WiFi SSIDs and passwords.
|
* < = > ? @ [ \ ] ^ _ ` { | } ~
|
||||||
* It considers characters from 'A' to 'Z', 'a' to 'z', '0' to '9', as well as
|
|
||||||
* the following special characters: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
|
|
||||||
*
|
*
|
||||||
* @param string Pointer to the string to be validated.
|
* @return true if valid (or empty), false otherwise.
|
||||||
* @param size Size of the string including the null-terminator.
|
|
||||||
* @return true if the string contains only allowed characters or is NULL,
|
|
||||||
* false otherwise.
|
|
||||||
*/
|
*/
|
||||||
bool validateWiFiString(char *string, size_t size)
|
bool validateWiFiString(char *string, size_t size)
|
||||||
{
|
{
|
||||||
@@ -539,10 +662,8 @@ bool validateWiFiString(char *string, size_t size)
|
|||||||
{
|
{
|
||||||
char c = string[i];
|
char c = string[i];
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
{
|
return true; // reached end with valid chars
|
||||||
// Reached the end of the string, all characters were valid WiFi characters.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
|
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
|
||||||
(c >= '0' && c <= '9') || c == '!' || c == '"' || c == '#' ||
|
(c >= '0' && c <= '9') || c == '!' || c == '"' || c == '#' ||
|
||||||
c == '$' || c == '%' || c == '&' || c == '\'' || c == '(' ||
|
c == '$' || c == '%' || c == '&' || c == '\'' || c == '(' ||
|
||||||
@@ -552,11 +673,9 @@ bool validateWiFiString(char *string, size_t size)
|
|||||||
c == '\\' || c == ']' || c == '^' || c == '_' || c == '`' ||
|
c == '\\' || c == ']' || c == '^' || c == '_' || c == '`' ||
|
||||||
c == '{' || c == '|' || c == '}' || c == '~'))
|
c == '{' || c == '|' || c == '}' || c == '~'))
|
||||||
{
|
{
|
||||||
// Found a character that is not a valid WiFi character.
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the loop completes without finding a null terminator, the string is invalid.
|
// No NUL within buffer: treat as invalid
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -314,6 +314,8 @@ static const std::map<String, DebugCmdHandler> &getCmdMap()
|
|||||||
}
|
}
|
||||||
dumpEEPROM(start, len);
|
dumpEEPROM(start, len);
|
||||||
}},
|
}},
|
||||||
|
{"reinitEE", [](const String &args)
|
||||||
|
{ globals.requestEEAction = EE_REINITIALIZE; }},
|
||||||
{"resetPageEE", [](const String &)
|
{"resetPageEE", [](const String &)
|
||||||
{ MovePersistencePage_EEPROM(true); }},
|
{ MovePersistencePage_EEPROM(true); }},
|
||||||
{"dumpCFG", [](const String &)
|
{"dumpCFG", [](const String &)
|
||||||
@@ -462,7 +464,7 @@ void Debug_dumpGlobals()
|
|||||||
Debug_pushMessage("requestEEAction: %d\n", globals.requestEEAction);
|
Debug_pushMessage("requestEEAction: %d\n", globals.requestEEAction);
|
||||||
Debug_pushMessage("DeviceName: %s\n", globals.DeviceName);
|
Debug_pushMessage("DeviceName: %s\n", globals.DeviceName);
|
||||||
Debug_pushMessage("FlashVersion: %s\n", globals.FlashVersion);
|
Debug_pushMessage("FlashVersion: %s\n", globals.FlashVersion);
|
||||||
Debug_pushMessage("eePersistanceAdress: %d\n", globals.eePersistanceAdress);
|
Debug_pushMessage("eePersistanceAdress: %d\n", globals.eePersistenceAddress);
|
||||||
Debug_pushMessage("TankPercentage: %d\n", globals.TankPercentage);
|
Debug_pushMessage("TankPercentage: %d\n", globals.TankPercentage);
|
||||||
Debug_pushMessage("hasDTC: %d\n", globals.hasDTC);
|
Debug_pushMessage("hasDTC: %d\n", globals.hasDTC);
|
||||||
}
|
}
|
||||||
@@ -476,7 +478,7 @@ void Debug_dumpPersistance()
|
|||||||
Debug_pushMessage("tankRemain_microL: %d\n", PersistenceData.tankRemain_microL);
|
Debug_pushMessage("tankRemain_microL: %d\n", PersistenceData.tankRemain_microL);
|
||||||
Debug_pushMessage("TravelDistance_highRes_mm: %d\n", PersistenceData.TravelDistance_highRes_mm);
|
Debug_pushMessage("TravelDistance_highRes_mm: %d\n", PersistenceData.TravelDistance_highRes_mm);
|
||||||
Debug_pushMessage("checksum: %d\n", PersistenceData.checksum);
|
Debug_pushMessage("checksum: %d\n", PersistenceData.checksum);
|
||||||
Debug_pushMessage("PSD Adress: 0x%04X\n", globals.eePersistanceAdress);
|
Debug_pushMessage("PSD Adress: 0x%04X\n", globals.eePersistenceAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -479,7 +479,7 @@ void WebServerEEJSON_Callback(AsyncWebServerRequest *request)
|
|||||||
generateJsonObject_PersistenceData(persis);
|
generateJsonObject_PersistenceData(persis);
|
||||||
|
|
||||||
JsonObject eepart = json["eepart"].to<JsonObject>();
|
JsonObject eepart = json["eepart"].to<JsonObject>();
|
||||||
sprintf(buffer, "0x%04X", globals.eePersistanceAdress);
|
sprintf(buffer, "0x%04X", globals.eePersistenceAddress);
|
||||||
eepart["PersistanceAddress"] = buffer;
|
eepart["PersistanceAddress"] = buffer;
|
||||||
|
|
||||||
serializeJsonPretty(json, *response);
|
serializeJsonPretty(json, *response);
|
||||||
|
Reference in New Issue
Block a user