Skip to content

Commit 619568d

Browse files
lbernstoneme-no-dev
authored andcommitted
Converted EEPROM library to use nvs instead of partition. (espressif#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
1 parent 0202ba7 commit 619568d

18 files changed

+189
-127
lines changed

Diff for: libraries/EEPROM/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## EEPROM
2+
3+
EEPROM is deprecated. For new applications on ESP32, use Preferences. EEPROM is provided for backwards compatibility with existing Arduino applications.
4+
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.

Diff for: libraries/EEPROM/examples/eeprom_class/eeprom_class.ino

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
#include "EEPROM.h"
2727

2828
// Instantiate eeprom objects with parameter/argument names and size same as in the partition table
29-
EEPROMClass NAMES("eeprom0", 0x1000);
30-
EEPROMClass HEIGHT("eeprom1", 0x500);
29+
EEPROMClass NAMES("eeprom0", 0x500);
30+
EEPROMClass HEIGHT("eeprom1", 0x200);
3131
EEPROMClass AGE("eeprom2", 0x100);
3232

3333
void setup() {

Diff for: libraries/EEPROM/examples/eeprom_extra/eeprom_extra.ino

+74-25
Original file line numberDiff line numberDiff line change
@@ -13,78 +13,127 @@ void setup() {
1313
// put your setup code here, to run once:
1414
Serial.begin(115200);
1515
Serial.println("\nTesting EEPROM Library\n");
16-
if (!EEPROM.begin(EEPROM.length())) {
16+
if (!EEPROM.begin(1000)) {
1717
Serial.println("Failed to initialise EEPROM");
1818
Serial.println("Restarting...");
1919
delay(1000);
2020
ESP.restart();
2121
}
2222

23-
int address = 0; // Same address is used through the example
23+
int address = 0;
2424

2525
EEPROM.writeByte(address, -128); // -2^7
26-
Serial.println(EEPROM.readByte(address));
26+
address += sizeof(byte);
2727

2828
EEPROM.writeChar(address, 'A'); // Same as writyByte and readByte
29-
Serial.println(char(EEPROM.readChar(address)));
29+
address += sizeof(char);
3030

3131
EEPROM.writeUChar(address, 255); // 2^8 - 1
32-
Serial.println(EEPROM.readUChar(address));
32+
address += sizeof(unsigned char);
3333

3434
EEPROM.writeShort(address, -32768); // -2^15
35-
Serial.println(EEPROM.readShort(address));
35+
address += sizeof(short);
3636

3737
EEPROM.writeUShort(address, 65535); // 2^16 - 1
38-
Serial.println(EEPROM.readUShort(address));
38+
address += sizeof(unsigned short);
3939

4040
EEPROM.writeInt(address, -2147483648); // -2^31
41-
Serial.println(EEPROM.readInt(address));
41+
address += sizeof(int);
4242

4343
EEPROM.writeUInt(address, 4294967295); // 2^32 - 1
44-
Serial.println(EEPROM.readUInt(address));
44+
address += sizeof(unsigned int);
4545

4646
EEPROM.writeLong(address, -2147483648); // Same as writeInt and readInt
47-
Serial.println(EEPROM.readLong(address));
47+
address += sizeof(long);
4848

4949
EEPROM.writeULong(address, 4294967295); // Same as writeUInt and readUInt
50-
Serial.println(EEPROM.readULong(address));
50+
address += sizeof(unsigned long);
5151

5252
int64_t value = -9223372036854775808; // -2^63
5353
EEPROM.writeLong64(address, value);
54-
value = 0; // Clear value
54+
address += sizeof(int64_t);
55+
56+
uint64_t Value = 18446744073709551615; // 2^64 - 1
57+
EEPROM.writeULong64(address, Value);
58+
address += sizeof(uint64_t);
59+
60+
EEPROM.writeFloat(address, 1234.1234);
61+
address += sizeof(float);
62+
63+
EEPROM.writeDouble(address, 123456789.123456789);
64+
address += sizeof(double);
65+
66+
EEPROM.writeBool(address, true);
67+
address += sizeof(bool);
68+
69+
String sentence = "I love ESP32.";
70+
EEPROM.writeString(address, sentence);
71+
address += sentence.length() + 1;
72+
73+
char gratitude[21] = "Thank You Espressif!";
74+
EEPROM.writeString(address, gratitude);
75+
address += 21;
76+
77+
// See also the general purpose writeBytes() and readBytes() for BLOB in EEPROM library
78+
EEPROM.commit();
79+
address = 0;
80+
81+
Serial.println(EEPROM.readByte(address));
82+
address += sizeof(byte);
83+
84+
Serial.println((char)EEPROM.readChar(address));
85+
address += sizeof(char);
86+
87+
Serial.println(EEPROM.readUChar(address));
88+
address += sizeof(unsigned char);
89+
90+
Serial.println(EEPROM.readShort(address));
91+
address += sizeof(short);
92+
93+
Serial.println(EEPROM.readUShort(address));
94+
address += sizeof(unsigned short);
95+
96+
Serial.println(EEPROM.readInt(address));
97+
address += sizeof(int);
98+
99+
Serial.println(EEPROM.readUInt(address));
100+
address += sizeof(unsigned int);
101+
102+
Serial.println(EEPROM.readLong(address));
103+
address += sizeof(long);
104+
105+
Serial.println(EEPROM.readULong(address));
106+
address += sizeof(unsigned long);
107+
108+
value = 0;
55109
value = EEPROM.readLong64(value);
56110
Serial.printf("0x%08X", (uint32_t)(value >> 32)); // Print High 4 bytes in HEX
57111
Serial.printf("%08X\n", (uint32_t)value); // Print Low 4 bytes in HEX
112+
address += sizeof(int64_t);
58113

59-
uint64_t Value = 18446744073709551615; // 2^64 - 1
60-
EEPROM.writeULong64(address, Value);
61114
Value = 0; // Clear Value
62115
Value = EEPROM.readULong64(Value);
63116
Serial.printf("0x%08X", (uint32_t)(Value >> 32)); // Print High 4 bytes in HEX
64117
Serial.printf("%08X\n", (uint32_t)Value); // Print Low 4 bytes in HEX
118+
address += sizeof(uint64_t);
65119

66-
EEPROM.writeFloat(address, 1234.1234);
67120
Serial.println(EEPROM.readFloat(address), 4);
121+
address += sizeof(float);
68122

69-
EEPROM.writeDouble(address, 123456789.123456789);
70123
Serial.println(EEPROM.readDouble(address), 8);
124+
address += sizeof(double);
71125

72-
EEPROM.writeBool(address, true);
73126
Serial.println(EEPROM.readBool(address));
127+
address += sizeof(bool);
74128

75-
String sentence = "I love ESP32.";
76-
EEPROM.writeString(address, sentence);
77129
Serial.println(EEPROM.readString(address));
130+
address += sentence.length() + 1;
78131

79-
char gratitude[] = "Thank You Espressif!";
80-
EEPROM.writeString(address, gratitude);
81132
Serial.println(EEPROM.readString(address));
82-
83-
// See also the general purpose writeBytes() and readBytes() for BLOB in EEPROM library
84-
// To avoid data overwrite, next address should be chosen/offset by using "address =+ sizeof(previousData)"
133+
address += 21;
85134
}
86135

87136
void loop() {
88137
// put your main code here, to run repeatedly:
89138

90-
}
139+
}

Diff for: libraries/EEPROM/src/EEPROM.cpp

+90-56
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
/*
22
EEPROM.h -ported by Paolo Becchi to Esp32 from esp8266 EEPROM
33
-Modified by Elochukwu Ifediora <ifedioraelochukwuc@gmail.com>
4+
-Converted to nvs lbernstone@gmail.com
45
5-
Uses a one sector flash partition defined in partition table
6-
OR
7-
Multiple sector flash partitions defined by the name column in the partition table
6+
Uses a nvs byte array to emulate EEPROM
87
98
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
109
This file is part of the esp8266 core for Arduino environment.
@@ -25,39 +24,37 @@
2524
*/
2625

2726
#include "EEPROM.h"
28-
27+
#include <nvs.h>
2928
#include <esp_log.h>
3029

31-
EEPROMClass::EEPROMClass(uint32_t sector)
32-
: _sector(sector)
33-
, _data(0)
30+
EEPROMClass::EEPROMClass(void)
31+
: _data(0)
3432
, _size(0)
3533
, _dirty(false)
36-
, _mypart(NULL)
34+
, _handle(NULL)
3735
, _name("eeprom")
3836
, _user_defined_size(0)
3937
{
4038
}
4139

42-
EEPROMClass::EEPROMClass(const char* name, uint32_t user_defined_size)
43-
: _sector(0)
44-
, _data(0)
40+
EEPROMClass::EEPROMClass(uint32_t sector)
41+
// Only for compatiility, no sectors in nvs!
42+
: _data(0)
4543
, _size(0)
4644
, _dirty(false)
47-
, _mypart(NULL)
48-
, _name(name)
49-
, _user_defined_size(user_defined_size)
45+
, _handle(NULL)
46+
, _name("eeprom")
47+
, _user_defined_size(0)
5048
{
5149
}
5250

53-
EEPROMClass::EEPROMClass(void)
54-
: _sector(0)// (((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE))
55-
, _data(0)
51+
EEPROMClass::EEPROMClass(const char* name, uint32_t user_defined_size)
52+
: _data(0)
5653
, _size(0)
5754
, _dirty(false)
58-
, _mypart(NULL)
59-
, _name("eeprom")
60-
, _user_defined_size(0)
55+
, _handle(NULL)
56+
, _name(name)
57+
, _user_defined_size(user_defined_size)
6158
{
6259
}
6360

@@ -66,31 +63,76 @@ EEPROMClass::~EEPROMClass() {
6663
}
6764

6865
bool EEPROMClass::begin(size_t size) {
69-
if (size <= 0) {
70-
return false;
66+
if (!size) {
67+
return false;
7168
}
72-
if (size > SPI_FLASH_SEC_SIZE) {
73-
size = SPI_FLASH_SEC_SIZE;
69+
70+
esp_err_t res = nvs_open(_name, NVS_READWRITE, &_handle);
71+
if (res != ESP_OK) {
72+
log_e("Unable to open NVS namespace: %d", res);
73+
return false;
7474
}
75-
// _mypart = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,ESP_PARTITION_SUBTYPE_ANY, EEPROM_FLASH_PARTITION_NAME);
76-
_mypart = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, _name);
77-
if (_mypart == NULL) {
78-
return false;
75+
76+
size_t key_size = 0;
77+
res = nvs_get_blob(_handle, _name, NULL, &key_size);
78+
if(res != ESP_OK && res != ESP_ERR_NVS_NOT_FOUND) {
79+
log_e("Unable to read NVS key: %d", res);
80+
return false;
81+
}
82+
if (size < key_size) { // truncate
83+
log_w("truncating EEPROM from %d to %d", key_size, size);
84+
uint8_t* key_data = (uint8_t*) malloc(key_size);
85+
if(!key_data) {
86+
log_e("Not enough memory to truncate EEPROM!");
87+
return false;
88+
}
89+
nvs_get_blob(_handle, _name, key_data, &key_size);
90+
nvs_set_blob(_handle, _name, key_data, size);
91+
nvs_commit(_handle);
92+
free(key_data);
93+
}
94+
else if (size > key_size) { // expand or new
95+
size_t expand_size = size - key_size;
96+
uint8_t* expand_key = (uint8_t*) malloc(expand_size);
97+
if(!expand_key) {
98+
log_e("Not enough memory to expand EEPROM!");
99+
return false;
100+
}
101+
// check for adequate free space
102+
if(nvs_set_blob(_handle, "expand", expand_key, expand_size)) {
103+
log_e("Not enough space to expand EEPROM from %d to %d", key_size, size);
104+
free(expand_key);
105+
return false;
106+
}
107+
free(expand_key);
108+
nvs_erase_key(_handle, "expand");
109+
uint8_t* key_data = (uint8_t*) malloc(size);
110+
if(!key_data) {
111+
log_e("Not enough memory to expand EEPROM!");
112+
return false;
113+
}
114+
memset(key_data, 0, size);
115+
if(key_size) {
116+
log_i("Expanding EEPROM from %d to %d", key_size, size);
117+
// hold data while key is deleted
118+
nvs_get_blob(_handle, _name, key_data, &key_size);
119+
nvs_erase_key(_handle, _name);
120+
} else {
121+
log_i("New EEPROM of %d bytes", size);
122+
}
123+
nvs_commit(_handle);
124+
nvs_set_blob(_handle, _name, key_data, size);
125+
free(key_data);
126+
nvs_commit(_handle);
79127
}
80-
size = (size + 3) & (~3);
81128

82129
if (_data) {
83130
delete[] _data;
84131
}
85132

86133
_data = new uint8_t[size];
87-
_size = size;
88-
bool ret = false;
89-
if (esp_partition_read (_mypart, 0, (void *) _data, _size) == ESP_OK) {
90-
ret = true;
91-
}
92-
93-
return ret;
134+
nvs_get_blob(_handle, _name, _data, &_size);
135+
return true;
94136
}
95137

96138
void EEPROMClass::end() {
@@ -134,29 +176,21 @@ void EEPROMClass::write(int address, uint8_t value) {
134176

135177
bool EEPROMClass::commit() {
136178
bool ret = false;
137-
if (!_size)
138-
return false;
139-
if (!_dirty)
140-
return true;
141-
if (!_data)
142-
return false;
143-
144-
145-
if (esp_partition_erase_range(_mypart, 0, SPI_FLASH_SEC_SIZE) != ESP_OK)
146-
{
147-
log_e( "partition erase err.");
179+
if (!_size) {
180+
return false;
148181
}
149-
else
150-
{
151-
if (esp_partition_write(_mypart, 0, (void *)_data, _size) == ESP_ERR_INVALID_SIZE)
152-
{
153-
log_e( "error in Write");
154-
}
155-
else
156-
{
182+
if (!_data) {
183+
return false;
184+
}
185+
if (!_dirty) {
186+
return true;
187+
}
188+
189+
if (ESP_OK != nvs_set_blob(_handle, _name, _data, _size)) {
190+
log_e( "error in write");
191+
} else {
157192
_dirty = false;
158193
ret = true;
159-
}
160194
}
161195

162196
return ret;

0 commit comments

Comments
 (0)