From 80e864f991051ebc7f0c5e5e98395e315ed076c1 Mon Sep 17 00:00:00 2001 From: fedy0 Date: Fri, 21 Jul 2023 04:26:14 +0200 Subject: [PATCH 1/2] rebase eeprom lib and add partition --- .../examples/eeprom_class/eeprom_class.ino | 57 +++-- .../examples/eeprom_class/partitions.csv | 9 + .../examples/eeprom_extra/eeprom_extra.ino | 19 +- .../examples/eeprom_extra/partitions.csv | 7 + .../examples/eeprom_write/partitions.csv | 7 + libraries/EEPROM/src/EEPROM.cpp | 227 +++++------------- libraries/EEPROM/src/EEPROM.h | 28 ++- 7 files changed, 146 insertions(+), 208 deletions(-) create mode 100644 libraries/EEPROM/examples/eeprom_class/partitions.csv create mode 100644 libraries/EEPROM/examples/eeprom_extra/partitions.csv create mode 100644 libraries/EEPROM/examples/eeprom_write/partitions.csv diff --git a/libraries/EEPROM/examples/eeprom_class/eeprom_class.ino b/libraries/EEPROM/examples/eeprom_class/eeprom_class.ino index 5d2961e1237..efee4e30e36 100644 --- a/libraries/EEPROM/examples/eeprom_class/eeprom_class.ino +++ b/libraries/EEPROM/examples/eeprom_class/eeprom_class.ino @@ -1,50 +1,64 @@ /* - ESP32 eeprom_class example with EEPROM library + ESP32 eeprom_class example with EEPROM library and custom partiton + This simple example demonstrates using EEPROM library to store different data in - ESP32 Flash memory in a multiple user-defined EEPROM class objects. + ESP32 Flash memory in a multiple user-defined EEPROM partition (0x1000 or 4KB max size or less). + Note: You must maintain a minimum sector address/offset of 4KB between partitions + Usage: EEPROMClass ANY_OBJECT_NAME("partition_name", size); + + Partition example created in the same sketch folder as this example + (See ./eeprom_class/partitions.csv) + #Name, Type, SubType, Offset, Size, Flags + nvs, data, nvs, 0x9000, 0x5000, + otadata, data, ota, 0xe000, 0x2000, + app0, app, ota_0, 0x10000, 0x140000, + app1, app, ota_1, 0x150000, 0x140000, + eeprom0, data, 0x99, 0x290000, 0x1000, + eeprom1, data, 0x9a, 0x291000, 0x500, + eeprom2, data, 0x9b, 0x292000, 0x100, + spiffs, data, spiffs, 0x293000, 0x16d000, + Created for arduino-esp32 on 25 Dec, 2017 by Elochukwu Ifediora (fedy0) - converted to nvs by lbernstone - 06/22/2019 */ #include "EEPROM.h" -// Instantiate eeprom objects with parameter/argument names and sizes -EEPROMClass NAMES("eeprom0"); -EEPROMClass HEIGHT("eeprom1"); -EEPROMClass AGE("eeprom2"); +// Instantiate eeprom objects with parameter/argument names and size same as in the partition table +EEPROMClass NAMES("eeprom0", 0x1000); +EEPROMClass HEIGHT("eeprom1", 0x500); +EEPROMClass AGE("eeprom2", 0x100); void setup() { + // put your setup code here, to run once: Serial.begin(115200); - delay(1000); Serial.println("Testing EEPROMClass\n"); - if (!NAMES.begin(0x500)) { + if (!NAMES.begin(NAMES.length())) { Serial.println("Failed to initialise NAMES"); Serial.println("Restarting..."); delay(1000); ESP.restart(); } - if (!HEIGHT.begin(0x200)) { + if (!HEIGHT.begin(HEIGHT.length())) { Serial.println("Failed to initialise HEIGHT"); Serial.println("Restarting..."); delay(1000); ESP.restart(); } - if (!AGE.begin(0x100)) { + if (!AGE.begin(AGE.length())) { Serial.println("Failed to initialise AGE"); Serial.println("Restarting..."); delay(1000); ESP.restart(); } - const char* name = "Teo Swee Ann"; - char rname[32]; + char* name = "Teo Swee Ann"; double height = 5.8; uint32_t age = 47; - // Write: Variables ---> EEPROM stores - NAMES.writeString(0, name); + // Write: Variables ---> EEPROM partitions + NAMES.put(0, name); HEIGHT.put(0, height); AGE.put(0, age); Serial.print("name: "); Serial.println(name); @@ -53,19 +67,19 @@ void setup() { Serial.println("------------------------------------\n"); // Clear variables - rname[0] = '\0'; + name = NULL; height = 0; age = 0; - Serial.print("name: "); Serial.println(rname); + Serial.print("name: "); Serial.println(name); Serial.print("height: "); Serial.println(height); Serial.print("age: "); Serial.println(age); Serial.println("------------------------------------\n"); - // Read: Variables <--- EEPROM stores - NAMES.get(0, rname); + // Read: Variables <--- EEPROM partitions + NAMES.get(0, name); HEIGHT.get(0, height); AGE.get(0, age); - Serial.print("name: "); Serial.println(rname); + Serial.print("name: "); Serial.println(name); Serial.print("height: "); Serial.println(height); Serial.print("age: "); Serial.println(age); @@ -73,5 +87,6 @@ void setup() { } void loop() { - delay(0xFFFFFFFF); + // put your main code here, to run repeatedly: + } diff --git a/libraries/EEPROM/examples/eeprom_class/partitions.csv b/libraries/EEPROM/examples/eeprom_class/partitions.csv new file mode 100644 index 00000000000..5889c7b1807 --- /dev/null +++ b/libraries/EEPROM/examples/eeprom_class/partitions.csv @@ -0,0 +1,9 @@ +#Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x140000, +app1, app, ota_1, 0x150000, 0x140000, +eeprom0, data, 0x99, 0x290000, 0x1000, +eeprom1, data, 0x9a, 0x291000, 0x500, +eeprom2, data, 0x9b, 0x292000, 0x100, +spiffs, data, spiffs, 0x293000, 0x16d000, diff --git a/libraries/EEPROM/examples/eeprom_extra/eeprom_extra.ino b/libraries/EEPROM/examples/eeprom_extra/eeprom_extra.ino index 5ae01fb2268..80f2747a705 100644 --- a/libraries/EEPROM/examples/eeprom_extra/eeprom_extra.ino +++ b/libraries/EEPROM/examples/eeprom_extra/eeprom_extra.ino @@ -1,7 +1,12 @@ /* ESP32 eeprom_extra example with EEPROM library - This simple example demonstrates using other EEPROM library resources + This simple example demonstrates using other EEPROM library resources. + + You need to define AT LEAST a flash partition for EEPROM with the name below + eeprom, data, 0x99, "start address", 0x1000 + + Note: For this Arduino sketch, "eeprom" is already defined in ./eeprom_extra/partitions.csv Created for arduino-esp32 on 25 Dec, 2017 by Elochukwu Ifediora (fedy0) @@ -13,7 +18,7 @@ void setup() { // put your setup code here, to run once: Serial.begin(115200); Serial.println("\nTesting EEPROM Library\n"); - if (!EEPROM.begin(1000)) { + if (!EEPROM.begin(0x1000)) { // Default Size = 4KB Serial.println("Failed to initialise EEPROM"); Serial.println("Restarting..."); delay(1000); @@ -22,7 +27,7 @@ void setup() { int address = 0; - EEPROM.writeByte(address, -128); // -2^7 + EEPROM.writeByte(address, 128); // 2^7 address += sizeof(byte); EEPROM.writeChar(address, 'A'); // Same as writyByte and readByte @@ -49,11 +54,11 @@ void setup() { EEPROM.writeULong(address, 4294967295); // Same as writeUInt and readUInt address += sizeof(unsigned long); - int64_t value = -1223372036854775808LL; // -2^63 + int64_t value = -9223372036854775808; // -2^63 EEPROM.writeLong64(address, value); address += sizeof(int64_t); - uint64_t Value = 18446744073709551615ULL; // 2^64 - 1 + uint64_t Value = 18446744073709551615; // 2^64 - 1 EEPROM.writeULong64(address, Value); address += sizeof(uint64_t); @@ -75,6 +80,7 @@ void setup() { address += 21; // See also the general purpose writeBytes() and readBytes() for BLOB in EEPROM library + EEPROM.commit(); address = 0; @@ -127,10 +133,9 @@ void setup() { address += sizeof(bool); Serial.println(EEPROM.readString(address)); - address += sentence.length() + 1; + address += sentence.length() + 1; // To skip NULL termination in the string Serial.println(EEPROM.readString(address)); - address += 21; } void loop() { diff --git a/libraries/EEPROM/examples/eeprom_extra/partitions.csv b/libraries/EEPROM/examples/eeprom_extra/partitions.csv new file mode 100644 index 00000000000..6cbdaaafddb --- /dev/null +++ b/libraries/EEPROM/examples/eeprom_extra/partitions.csv @@ -0,0 +1,7 @@ +#Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x140000, +app1, app, ota_1, 0x150000, 0x140000, +eeprom, data, 0x99, 0x290000, 0x1000, +spiffs, data, spiffs, 0x291000, 0x16F000, diff --git a/libraries/EEPROM/examples/eeprom_write/partitions.csv b/libraries/EEPROM/examples/eeprom_write/partitions.csv new file mode 100644 index 00000000000..6cbdaaafddb --- /dev/null +++ b/libraries/EEPROM/examples/eeprom_write/partitions.csv @@ -0,0 +1,7 @@ +#Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x140000, +app1, app, ota_1, 0x150000, 0x140000, +eeprom, data, 0x99, 0x290000, 0x1000, +spiffs, data, spiffs, 0x291000, 0x16F000, diff --git a/libraries/EEPROM/src/EEPROM.cpp b/libraries/EEPROM/src/EEPROM.cpp index 356255cbf24..d6ad04a3cad 100644 --- a/libraries/EEPROM/src/EEPROM.cpp +++ b/libraries/EEPROM/src/EEPROM.cpp @@ -1,9 +1,10 @@ /* EEPROM.h -ported by Paolo Becchi to Esp32 from esp8266 EEPROM - -Modified by Elochukwu Ifediora - -Converted to nvs lbernstone@gmail.com + -Modified by Elochukwu Ifediora - Uses a nvs byte array to emulate EEPROM + Uses a one sector flash partition defined in partition table + OR + Multiple sector flash partitions defined by the name column in the partition table Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. This file is part of the esp8266 core for Arduino environment. @@ -24,118 +25,60 @@ */ #include "EEPROM.h" -#include -#include + #include -EEPROMClass::EEPROMClass(void) - : _handle(0) - , _data(0) - , _size(0) - , _dirty(false) - , _name("eeprom") -{ -} -EEPROMClass::EEPROMClass(uint32_t sector) -// Only for compatiility, no sectors in nvs! - : _handle(0) - , _data(0) +EEPROMClass::EEPROMClass(const char* name, uint32_t user_defined_size) + : _data(0) , _size(0) , _dirty(false) - , _name("eeprom") + , _mypart(NULL) + , _name(name) + , _user_defined_size(user_defined_size) { } -EEPROMClass::EEPROMClass(const char* name) - : _handle(0) - , _data(0) +EEPROMClass::EEPROMClass(void) + : _data(0) , _size(0) , _dirty(false) - , _name(name) + , _mypart(NULL) + , _name(EEPROM_FLASH_PARTITION_NAME) + , _user_defined_size(0x1000) { } EEPROMClass::~EEPROMClass() { - end(); + // end(); } bool EEPROMClass::begin(size_t size) { - if (!size) { - return false; + if (size <= 0) { + return false; } - - esp_err_t res = nvs_open(_name, NVS_READWRITE, &_handle); - if (res != ESP_OK) { - log_e("Unable to open NVS namespace: %d", res); - return false; + if (size > SPI_FLASH_SEC_SIZE) { + size = SPI_FLASH_SEC_SIZE; } - size_t key_size = 0; - res = nvs_get_blob(_handle, _name, NULL, &key_size); - if(res != ESP_OK && res != ESP_ERR_NVS_NOT_FOUND) { - log_e("Unable to read NVS key: %d", res); - return false; - } - if (size < key_size) { // truncate - log_w("truncating EEPROM from %d to %d", key_size, size); - uint8_t* key_data = (uint8_t*) malloc(key_size); - if(!key_data) { - log_e("Not enough memory to truncate EEPROM!"); - return false; - } - nvs_get_blob(_handle, _name, key_data, &key_size); - nvs_set_blob(_handle, _name, key_data, size); - nvs_commit(_handle); - free(key_data); - } - else if (size > key_size) { // expand or new - size_t expand_size = size - key_size; - uint8_t* expand_key = (uint8_t*) malloc(expand_size); - if(!expand_key) { - log_e("Not enough memory to expand EEPROM!"); - return false; - } - // check for adequate free space - if(nvs_set_blob(_handle, "expand", expand_key, expand_size)) { - log_e("Not enough space to expand EEPROM from %d to %d", key_size, size); - free(expand_key); - return false; - } - free(expand_key); - nvs_erase_key(_handle, "expand"); - uint8_t* key_data = (uint8_t*) malloc(size); - if(!key_data) { - log_e("Not enough memory to expand EEPROM!"); - return false; - } - memset(key_data, 0xFF, size); - if(key_size) { - log_i("Expanding EEPROM from %d to %d", key_size, size); - // hold data while key is deleted - nvs_get_blob(_handle, _name, key_data, &key_size); - nvs_erase_key(_handle, _name); - } else { - log_i("New EEPROM of %d bytes", size); - } - nvs_commit(_handle); - nvs_set_blob(_handle, _name, key_data, size); - free(key_data); - nvs_commit(_handle); + _mypart = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, _name); + if (_mypart == NULL) { + return false; } + size = (size + 3) & (~3); if (_data) { delete[] _data; } - _data = (uint8_t*) malloc(size); - if(!_data) { - log_e("Not enough memory for %d bytes in EEPROM", size); - return false; - } + _data = new uint8_t[size]; _size = size; - nvs_get_blob(_handle, _name, _data, &_size); - return true; + bool ret = false; + if (esp_partition_read (_mypart, 0, (void *) _data, _size) == ESP_OK) { + ret = true; + } + + return ret; } void EEPROMClass::end() { @@ -149,9 +92,6 @@ void EEPROMClass::end() { } _data = 0; _size = 0; - - nvs_close(_handle); - _handle = 0; } uint8_t EEPROMClass::read(int address) { @@ -182,22 +122,29 @@ void EEPROMClass::write(int address, uint8_t value) { bool EEPROMClass::commit() { bool ret = false; - if (!_size) { - return false; - } - if (!_data) { + if (!_size) return false; - } - if (!_dirty) { + if (!_dirty) return true; - } + if (!_data) + return false; - esp_err_t err = nvs_set_blob(_handle, _name, _data, _size); - if (err != ESP_OK) { - log_e("error in write: %s", esp_err_to_name(err)); - } else { - _dirty = false; - ret = true; + + if (esp_partition_erase_range(_mypart, 0, SPI_FLASH_SEC_SIZE) != ESP_OK) + { + log_e( "partition erase err."); + } + else + { + if (esp_partition_write(_mypart, 0, (void *)_data, _size) == ESP_ERR_INVALID_SIZE) + { + log_e( "error in Write"); + } + else + { + _dirty = false; + ret = true; + } } return ret; @@ -213,68 +160,7 @@ uint8_t * EEPROMClass::getDataPtr() { */ uint16_t EEPROMClass::length () { - return _size; -} - -/* - Convert EEPROM partition into nvs blob - Call convert before you call begin -*/ -uint16_t EEPROMClass::convert (bool clear, const char* EEPROMname, const char* nvsname) -{ - uint16_t result = 0; - const esp_partition_t* mypart = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, EEPROMname); - if (mypart == NULL) { - log_i("EEPROM partition not found for conversion"); - return result; - } - - size_t size = mypart->size; - uint8_t* data = (uint8_t*) malloc(size); - if (!data) { - log_e("Not enough memory to convert EEPROM!"); - goto exit; - } - - if (esp_partition_read (mypart, 0, (void *) data, size) != ESP_OK) { - log_e("Unable to read EEPROM partition"); - goto exit; - } - - bool empty; - empty = true; - for (int x=0; x _size) return 0; - if (len > maxLen) - return 0; //Maybe return part of the string instead? - memcpy((uint8_t*) value, _data + address, len); value[len] = 0; return len; @@ -391,7 +274,7 @@ size_t EEPROMClass::readString (int address, char* value, size_t maxLen) String EEPROMClass::readString (int address) { if (address < 0 || address > _size) - return String(); + return String(0); uint16_t len; for (len = 0; len <= _size; len++) @@ -399,7 +282,7 @@ String EEPROMClass::readString (int address) break; if (address + len > _size) - return String(); + return String(0); char value[len+1]; memcpy((uint8_t*) value, _data + address, len); @@ -521,6 +404,7 @@ size_t EEPROMClass::writeString (int address, const char* value) memcpy(_data + address, (const uint8_t*) value, len + 1); _dirty = true; + return strlen(value); } @@ -539,6 +423,7 @@ size_t EEPROMClass::writeBytes (int address, const void* value, size_t len) memcpy(_data + address, (const void*) value, len); _dirty = true; + return len; } diff --git a/libraries/EEPROM/src/EEPROM.h b/libraries/EEPROM/src/EEPROM.h index b4e849f536b..3d3edb6b527 100644 --- a/libraries/EEPROM/src/EEPROM.h +++ b/libraries/EEPROM/src/EEPROM.h @@ -1,9 +1,10 @@ /* EEPROM.h -ported by Paolo Becchi to Esp32 from esp8266 EEPROM - -Modified by Elochukwu Ifediora - -Converted to nvs lbernstone@gmail.com + -Modified by Elochukwu Ifediora - Uses a nvs byte array to emulate EEPROM + Uses one sector flash partition defined in partition table + OR + Multiple sector flash partitions defined by the name column in the partition table Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. This file is part of the esp8266 core for Arduino environment. @@ -29,17 +30,26 @@ #define EEPROM_FLASH_PARTITION_NAME "eeprom" #endif #include +extern "C" { -typedef uint32_t nvs_handle; +#include +#include +#include +#include +} + +/* + You need to define AT LEAST a flash partition for EEPROM with the name below + eeprom, data, 0x99, "start address", 0x1000 +*/ class EEPROMClass { public: - EEPROMClass(uint32_t sector); - EEPROMClass(const char* name); + EEPROMClass(const char* name, uint32_t user_defined_size=0x1000); EEPROMClass(void); ~EEPROMClass(void); - bool begin(size_t size); + bool begin(size_t size=0x1000); uint8_t read(int address); void write(int address, uint8_t val); uint16_t length(); @@ -47,7 +57,6 @@ class EEPROMClass { void end(); uint8_t * getDataPtr(); - uint16_t convert(bool clear, const char* EEPROMname = "eeprom", const char* nvsname = "eeprom"); template T &get(int address, T &t) { @@ -107,11 +116,12 @@ class EEPROMClass { template T writeAll (int address, const T &); protected: - nvs_handle _handle; uint8_t* _data; size_t _size; bool _dirty; + const esp_partition_t * _mypart; const char* _name; + uint32_t _user_defined_size; }; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM) From bff5dc189012096c3dcc94c6d60ede10856e5a5f Mon Sep 17 00:00:00 2001 From: fedy0 Date: Fri, 21 Jul 2023 04:41:09 +0200 Subject: [PATCH 2/2] remove deprecation readme.md --- libraries/EEPROM/README.md | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 libraries/EEPROM/README.md diff --git a/libraries/EEPROM/README.md b/libraries/EEPROM/README.md deleted file mode 100644 index 896ca5b3019..00000000000 --- a/libraries/EEPROM/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## EEPROM - -EEPROM is deprecated. For new applications on ESP32, use Preferences. EEPROM is provided for backwards compatibility with existing Arduino applications. -EEPROM is implemented using a single blob within NVS, so it is a container within a container. As such, it is not going to be a high performance storage method. Preferences will directly use nvs, and store each entry as a single object therein.