EepromSecureData
CRC-controlled EEPROM memory storage
Loading...
Searching...
No Matches

CRC-controlled EEPROM memory storage for Arduino framework

GitHub release (latest by date including pre-releases) PlatformIO Registry Arduino Registry

Framework AtmelAVR Teensy Esp32 Esp8266


This library provides a template class for storing objects in EEPROM memory by checking the consistency of the data using a CRC. It also manages an EEPROM memory address counter.

Supported Platforms

Validated by hardware testing with PlatformIO / Unity:

Architecture Board Platform
AVR (ATmega328P) Arduino UNO R3 atmelavr
Renesas RA4M1 Arduino UNO R4 WiFi renesas-ra
ARM Cortex-M4 Teensy 3.5 teensy
ARM Cortex-M7 Teensy 4.1 teensy
Xtensa LX6 ESP32 espressif32
Xtensa LX7 ESP32-S3 / LOLIN S3 espressif32
Xtensa L106 ESP8266 espressif8266
RISC-V (RV32IMC) ESP32-C6 (Maker Go C6 SuperMini) espressif32
RISC-V (RV32IMC) ESP32-C3 (Waveshare Zero C3, generic esp32-c3-devkitm-1) espressif32
RISC-V (RV32IMC) ESP32-H4 *(build only)* espressif32

Note: The Preferences backend is only available on ESP32 targets. All other platforms (including ESP8266) use the EEPROM backend.

Note (ESP32-C6/C3): Unit tests were validated via a USB-UART adapter on UART0 with ARDUINO_USB_CDC_ON_BOOT=0. C6 wiring: GPIO16 TX / GPIO17 RX. C3 wiring: GPIO21 TX / GPIO20 RX. Use --upload-port and --test-port to specify the two COM ports.

Note (ESP32-H4): This target uses native USB CDC as its serial interface. PlatformIO's test runner cannot reliably capture Unity output over USB CDC on Windows, so unit tests have not been validated on this board despite the library being fully functional on it.

Simplified Example (<tt>unsigned long</tt> only)

#include <Arduino.h>
#include <EepromSecureData.h>
// Stores one unsigned long + CRC in persistent storage.
void setup() {
Serial.begin(115200);
#if defined(ESP32) || defined(ESP8266)
EEPROM.begin(4096);
#endif
// Load previous value; if missing/invalid, start at 0.
bool loaded = counter.load(0UL);
unsigned long value = counter.data();
Serial.print("Loaded from storage: ");
Serial.println(loaded ? "yes" : "no (default used)");
Serial.print("Current value: ");
Serial.println(value);
// Update and save.
counter = value + 1;
if (counter.save()) {
Serial.print("Saved new value: ");
Serial.println(counter.data());
}
else {
Serial.println("Save failed");
}
}
void loop() {
// nothing to do
}
CRC-controlled EEPROM memory storage template class.
T & data()
Get the data object.
bool load(const T &defaultData=T())
Load data from EEPROM memory with CRC check.
bool save()
Save data to EEPROM memory with CRC.

Unit Tests

Tests are written with Unity and run via pio test.

test_01_eeprombase

Tests the EepromBase / EepromBaseStatic<T> address counter mechanism (7 tests):

Test Description
test_counter_initialized_to_zero Counter starts at 0 after reset
test_counter_increment_single_allocation Counter increments by sizeof(T) on first allocation
test_counter_accumulates Counter accumulates correctly across multiple allocations
test_counter_different_sizes Different struct sizes each consume the right number of bytes
test_counter_large_allocation Counter correctly handles values near the uint16_t maximum
test_counter_sequential_allocations Mixed-type sequential allocations sum to the expected total
test_template_independence Different template specializations maintain independent counters

test_02_eepromsecuredata

Tests the EepromSecureData<T> template class (11 tests):

Test Description
test_size Stored size equals sizeof(T) + 1 (CRC byte); total matches address counter
test_constructor Default and value-initialized constructors set data correctly
test_equal_op operator== works between instances and raw values
test_not_equal_op operator!= works between instances and raw values
test_assignation_op operator= from instance and from raw value
test_save_load Full EEPROM round-trip: save() then load() recovers original data
test_backend backend() returns the correct backend; consistent across instances
test_crc_enabled setCrcEnabled() toggles CRC and the state is reflected by crcEnabled()
test_cast_operators operator const T& and operator T* work correctly
test_crc_disabled Save/load round-trip succeeds with CRC disabled
test_load_default load() returns false on fresh/invalid EEPROM, true when CRC matches

Running the tests

# Run test_02 on a specific target
pio test -f test_02_eepromsecuredata -e esp32
# Run all tests on all default targets
pio test