-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Converted EEPROM library to use nvs instead of partition. #2678
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
20f9f83
6a4b337
d3b9524
e262520
1c13541
ea34660
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
## 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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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(); | ||
|
||
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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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: | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,9 @@ | ||
/* | ||
EEPROM.h -ported by Paolo Becchi to Esp32 from esp8266 EEPROM | ||
-Modified by Elochukwu Ifediora <[email protected]> | ||
-Converted to nvs [email protected] | ||
|
||
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); | ||
me-no-dev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this whole block of code needs some comments to explain exactly what is going on :) I got lost with all those reads, writes and erases. What data is where... you need 2 blobs to hold the default 4K EEPROM, but reading through your code I got lost. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no way to expand a key, so in order to do so, it tests for free space, then holds the data while it deletes the key. If it is a new key, it just fills with zeros. I think changing the variable name to key_data will make it clearer. |
||
} | ||
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; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this actually compile? Shouldn't it be
println((char)EEPROM.readChar(address));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
travis would have complained :) not sure how Make will like it though