Commit 619568db authored by lbernstone's avatar lbernstone Committed by Me No Dev

Converted EEPROM library to use nvs instead of partition. (#2678)

* Converted EEPROM library to use nvs instead of partition.  Removed eeprom partition from all partition table CSV files.
* Changed variable names, added some comments, formatting as per me-no-dev's requests
* Checks for memory on malloc
* Moved include nvs.h from header to code
* Reworked the extra example to make it more clear how to actually use the library and persist data
parent 0202ba7c
## 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.
......@@ -26,8 +26,8 @@
#include "EEPROM.h"
// Instantiate eeprom objects with parameter/argument names and size same as in the partition table
EEPROMClass NAMES("eeprom0", 0x1000);
EEPROMClass HEIGHT("eeprom1", 0x500);
EEPROMClass NAMES("eeprom0", 0x500);
EEPROMClass HEIGHT("eeprom1", 0x200);
EEPROMClass AGE("eeprom2", 0x100);
void setup() {
......
......@@ -13,78 +13,127 @@ void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("\nTesting EEPROM Library\n");
if (!EEPROM.begin(EEPROM.length())) {
if (!EEPROM.begin(1000)) {
Serial.println("Failed to initialise EEPROM");
Serial.println("Restarting...");
delay(1000);
ESP.restart();
}
int address = 0; // Same address is used through the example
int address = 0;
EEPROM.writeByte(address, -128); // -2^7
Serial.println(EEPROM.readByte(address));
address += sizeof(byte);
EEPROM.writeChar(address, 'A'); // Same as writyByte and readByte
Serial.println(char(EEPROM.readChar(address)));
address += sizeof(char);
EEPROM.writeUChar(address, 255); // 2^8 - 1
Serial.println(EEPROM.readUChar(address));
address += sizeof(unsigned char);
EEPROM.writeShort(address, -32768); // -2^15
Serial.println(EEPROM.readShort(address));
address += sizeof(short);
EEPROM.writeUShort(address, 65535); // 2^16 - 1
Serial.println(EEPROM.readUShort(address));
address += sizeof(unsigned short);
EEPROM.writeInt(address, -2147483648); // -2^31
Serial.println(EEPROM.readInt(address));
address += sizeof(int);
EEPROM.writeUInt(address, 4294967295); // 2^32 - 1
Serial.println(EEPROM.readUInt(address));
address += sizeof(unsigned int);
EEPROM.writeLong(address, -2147483648); // Same as writeInt and readInt
Serial.println(EEPROM.readLong(address));
address += sizeof(long);
EEPROM.writeULong(address, 4294967295); // Same as writeUInt and readUInt
Serial.println(EEPROM.readULong(address));
address += sizeof(unsigned long);
int64_t value = -9223372036854775808; // -2^63
EEPROM.writeLong64(address, value);
value = 0; // Clear value
address += sizeof(int64_t);
uint64_t Value = 18446744073709551615; // 2^64 - 1
EEPROM.writeULong64(address, Value);
address += sizeof(uint64_t);
EEPROM.writeFloat(address, 1234.1234);
address += sizeof(float);
EEPROM.writeDouble(address, 123456789.123456789);
address += sizeof(double);
EEPROM.writeBool(address, true);
address += sizeof(bool);
String sentence = "I love ESP32.";
EEPROM.writeString(address, sentence);
address += sentence.length() + 1;
char gratitude[21] = "Thank You Espressif!";
EEPROM.writeString(address, gratitude);
address += 21;
// See also the general purpose writeBytes() and readBytes() for BLOB in EEPROM library
EEPROM.commit();
address = 0;
Serial.println(EEPROM.readByte(address));
address += sizeof(byte);
Serial.println((char)EEPROM.readChar(address));
address += sizeof(char);
Serial.println(EEPROM.readUChar(address));
address += sizeof(unsigned char);
Serial.println(EEPROM.readShort(address));
address += sizeof(short);
Serial.println(EEPROM.readUShort(address));
address += sizeof(unsigned short);
Serial.println(EEPROM.readInt(address));
address += sizeof(int);
Serial.println(EEPROM.readUInt(address));
address += sizeof(unsigned int);
Serial.println(EEPROM.readLong(address));
address += sizeof(long);
Serial.println(EEPROM.readULong(address));
address += sizeof(unsigned long);
value = 0;
value = EEPROM.readLong64(value);
Serial.printf("0x%08X", (uint32_t)(value >> 32)); // Print High 4 bytes in HEX
Serial.printf("%08X\n", (uint32_t)value); // Print Low 4 bytes in HEX
address += sizeof(int64_t);
uint64_t Value = 18446744073709551615; // 2^64 - 1
EEPROM.writeULong64(address, Value);
Value = 0; // Clear Value
Value = EEPROM.readULong64(Value);
Serial.printf("0x%08X", (uint32_t)(Value >> 32)); // Print High 4 bytes in HEX
Serial.printf("%08X\n", (uint32_t)Value); // Print Low 4 bytes in HEX
address += sizeof(uint64_t);
EEPROM.writeFloat(address, 1234.1234);
Serial.println(EEPROM.readFloat(address), 4);
address += sizeof(float);
EEPROM.writeDouble(address, 123456789.123456789);
Serial.println(EEPROM.readDouble(address), 8);
address += sizeof(double);
EEPROM.writeBool(address, true);
Serial.println(EEPROM.readBool(address));
address += sizeof(bool);
String sentence = "I love ESP32.";
EEPROM.writeString(address, sentence);
Serial.println(EEPROM.readString(address));
address += sentence.length() + 1;
char gratitude[] = "Thank You Espressif!";
EEPROM.writeString(address, gratitude);
Serial.println(EEPROM.readString(address));
// See also the general purpose writeBytes() and readBytes() for BLOB in EEPROM library
// To avoid data overwrite, next address should be chosen/offset by using "address =+ sizeof(previousData)"
address += 21;
}
void loop() {
// put your main code here, to run repeatedly:
}
\ No newline at end of file
}
/*
EEPROM.h -ported by Paolo Becchi to Esp32 from esp8266 EEPROM
-Modified by Elochukwu Ifediora <ifedioraelochukwuc@gmail.com>
-Converted to nvs lbernstone@gmail.com
Uses a one sector flash partition defined in partition table
OR
Multiple sector flash partitions defined by the name column in the partition table
Uses a nvs byte array to emulate EEPROM
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
......@@ -25,39 +24,37 @@
*/
#include "EEPROM.h"
#include <nvs.h>
#include <esp_log.h>
EEPROMClass::EEPROMClass(uint32_t sector)
: _sector(sector)
, _data(0)
EEPROMClass::EEPROMClass(void)
: _data(0)
, _size(0)
, _dirty(false)
, _mypart(NULL)
, _handle(NULL)
, _name("eeprom")
, _user_defined_size(0)
{
}
EEPROMClass::EEPROMClass(const char* name, uint32_t user_defined_size)
: _sector(0)
, _data(0)
EEPROMClass::EEPROMClass(uint32_t sector)
// Only for compatiility, no sectors in nvs!
: _data(0)
, _size(0)
, _dirty(false)
, _mypart(NULL)
, _name(name)
, _user_defined_size(user_defined_size)
, _handle(NULL)
, _name("eeprom")
, _user_defined_size(0)
{
}
EEPROMClass::EEPROMClass(void)
: _sector(0)// (((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE))
, _data(0)
EEPROMClass::EEPROMClass(const char* name, uint32_t user_defined_size)
: _data(0)
, _size(0)
, _dirty(false)
, _mypart(NULL)
, _name("eeprom")
, _user_defined_size(0)
, _handle(NULL)
, _name(name)
, _user_defined_size(user_defined_size)
{
}
......@@ -66,31 +63,76 @@ EEPROMClass::~EEPROMClass() {
}
bool EEPROMClass::begin(size_t size) {
if (size <= 0) {
return false;
if (!size) {
return false;
}
if (size > SPI_FLASH_SEC_SIZE) {
size = SPI_FLASH_SEC_SIZE;
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;
}
// _mypart = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,ESP_PARTITION_SUBTYPE_ANY, EEPROM_FLASH_PARTITION_NAME);
_mypart = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, _name);
if (_mypart == NULL) {
return false;
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, 0, 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);
}
size = (size + 3) & (~3);
if (_data) {
delete[] _data;
}
_data = new uint8_t[size];
_size = size;
bool ret = false;
if (esp_partition_read (_mypart, 0, (void *) _data, _size) == ESP_OK) {
ret = true;
}
return ret;
nvs_get_blob(_handle, _name, _data, &_size);
return true;
}
void EEPROMClass::end() {
......@@ -134,29 +176,21 @@ void EEPROMClass::write(int address, uint8_t value) {
bool EEPROMClass::commit() {
bool ret = false;
if (!_size)
return false;
if (!_dirty)
return true;
if (!_data)
return false;
if (esp_partition_erase_range(_mypart, 0, SPI_FLASH_SEC_SIZE) != ESP_OK)
{
log_e( "partition erase err.");
if (!_size) {
return false;
}
else
{
if (esp_partition_write(_mypart, 0, (void *)_data, _size) == ESP_ERR_INVALID_SIZE)
{
log_e( "error in Write");
}
else
{
if (!_data) {
return false;
}
if (!_dirty) {
return true;
}
if (ESP_OK != nvs_set_blob(_handle, _name, _data, _size)) {
log_e( "error in write");
} else {
_dirty = false;
ret = true;
}
}
return ret;
......
/*
EEPROM.h -ported by Paolo Becchi to Esp32 from esp8266 EEPROM
-Modified by Elochukwu Ifediora <ifedioraelochukwuc@gmail.com>
-Converted to nvs lbernstone@gmail.com
Uses a one sector flash partition defined in partition table
OR
Multiple sector flash partitions defined by the name column in the partition table
Uses a nvs byte array to emulate EEPROM
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
......@@ -30,19 +29,9 @@
#define EEPROM_FLASH_PARTITION_NAME "eeprom"
#endif
#include <Arduino.h>
extern "C" {
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <esp_partition.h>
}
//
// need to define AT LEAST a flash partition for EEPROM with above name
//
// eeprom , data , 0x99, start address, 0x1000
//
typedef uint32_t nvs_handle;
class EEPROMClass {
public:
EEPROMClass(uint32_t sector);
......@@ -117,11 +106,10 @@ class EEPROMClass {
template <class T> T writeAll (int address, const T &);
protected:
uint32_t _sector;
nvs_handle _handle;
uint8_t* _data;
size_t _size;
bool _dirty;
const esp_partition_t * _mypart;
const char* _name;
uint32_t _user_defined_size;
};
......
......@@ -3,5 +3,4 @@ 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,
spiffs, data, spiffs, 0x290000,0x170000,
......@@ -3,5 +3,4 @@ nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x640000,
app1, app, ota_1, 0x650000,0x640000,
eeprom, data, 0x99, 0xc90000,0x1000,
spiffs, data, spiffs, 0xc91000,0x36F000,
\ No newline at end of file
spiffs, data, spiffs, 0xc90000,0x370000,
......@@ -3,5 +3,4 @@ nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x330000,
app1, app, ota_1, 0x340000,0x330000,
eeprom, data, 0x99, 0x670000,0x1000,
spiffs, data, spiffs, 0x671000,0x18F000,
spiffs, data, spiffs, 0x670000,0x190000,
......@@ -3,5 +3,4 @@ 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,
ffat, data, fat, 0x291000,0x16F000,
ffat, data, fat, 0x291000,0x170000,
......@@ -3,6 +3,5 @@ nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x200000,
app1, app, ota_1, 0x210000,0x200000,
eeprom, data, 0x99, 0x410000,0x1000,
ffat, data, fat, 0x411000,0xBEE000,
ffat, data, fat, 0x410000,0xBEF000,
# to create/use ffat, see https://github.com/marcmerlin/esp32_fatfsimage
......@@ -2,5 +2,4 @@
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x300000,
eeprom, data, 0x99, 0x310000,0x1000,
spiffs, data, spiffs, 0x311000,0xEF000,
spiffs, data, spiffs, 0x310000,0xF0000,
......@@ -3,5 +3,4 @@ nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x480000,
app1, app, ota_1, 0x490000,0x480000,
eeprom, data, 0x99, 0x910000,0x1000,
spiffs, data, spiffs, 0x911000,0x6EF000,
\ No newline at end of file
spiffs, data, spiffs, 0x910000,0x6F0000,
......@@ -3,5 +3,4 @@ nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x1E0000,
app1, app, ota_1, 0x1F0000,0x1E0000,
eeprom, data, 0x99, 0x3D0000,0x1000,
spiffs, data, spiffs, 0x3D1000,0x2F000,
spiffs, data, spiffs, 0x3D0000,0x30000,
......@@ -2,5 +2,4 @@
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x140000,
eeprom, data, 0x99, 0x150000, 0x1000,
spiffs, data, spiffs, 0x151000, 0xAF000,
spiffs, data, spiffs, 0x150000, 0xB0000,
......@@ -2,5 +2,4 @@
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x200000,
eeprom, data, 0x99, 0x210000,0x1000,
spiffs, data, spiffs, 0x211000,0x1EF000,
spiffs, data, spiffs, 0x210000,0x1F0000,
......@@ -2,5 +2,4 @@
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x100000,
eeprom, data, 0x99, 0x110000,0x1000,
spiffs, data, spiffs, 0x111000,0x2EF000,
spiffs, data, spiffs, 0x110000,0x2F0000,
......@@ -2,6 +2,5 @@
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x100000,
eeprom, data, 0x99, 0x110000,0x1000,
ffat, data, fat, 0x111000,0x2EF000,
ffat, data, fat, 0x110000,0x2F0000,
# to create/use ffat, see https://github.com/marcmerlin/esp32_fatfsimage
......@@ -2,6 +2,5 @@
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x200000,
eeprom, data, 0x99, 0x210000,0x1000,
ffat, data, fat, 0x211000,0x1EF000,
ffat, data, fat, 0x210000,0x1F0000,
# to create/use ffat, see https://github.com/marcmerlin/esp32_fatfsimage
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment