Add EEPROMClass and examples (#1034)

* enchanced EEPROMClass

* Added eeprom examles and modified partition

* added eeprom class and extra examples

* No changes

* No changes

* added eeprom class and examples

* fixed typo

* length() returns user-defined sector size

* updated and annotated example
This commit is contained in:
Ifediora Elochukwu C 2018-03-04 20:22:48 +01:00 committed by Me No Dev
parent 694c3a453f
commit 3310e2e31d
7 changed files with 592 additions and 66 deletions

View File

@ -65,4 +65,4 @@ void setup() {
void loop() { void loop() {
ArduinoOTA.handle(); ArduinoOTA.handle();
} }

View File

@ -1,7 +1,10 @@
/* /*
EEPROM.cpp -ported by Paolo Becchi to Esp32 EEPROM.h -ported by Paolo Becchi to Esp32 from esp8266 EEPROM
Op -Modified by Elochukwu Ifediora <ifedioraelochukwuc@gmail.com>
from esp8266 EEPROM emulation
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. Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment. This file is part of the esp8266 core for Arduino environment.
@ -29,21 +32,37 @@
static const char* TAG = "eeprom"; static const char* TAG = "eeprom";
EEPROMClass::EEPROMClass(uint32_t sector) EEPROMClass::EEPROMClass(uint32_t sector)
: _sector(sector) : _sector(sector)
, _data(0) , _data(0)
, _size(0) , _size(0)
, _dirty(false) , _dirty(false)
, _name("eeprom")
{
}
EEPROMClass::EEPROMClass(const char* name, uint32_t user_defined_size)
: _sector(0)
, _data(0)
, _size(0)
, _dirty(false)
, _name(name)
, _user_defined_size(user_defined_size)
{ {
} }
EEPROMClass::EEPROMClass(void) EEPROMClass::EEPROMClass(void)
: _sector(0)// (((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE)) : _sector(0)// (((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE))
, _data(0) , _data(0)
, _size(0) , _size(0)
, _dirty(false) , _dirty(false)
, _name("eeprom")
{ {
} }
EEPROMClass::~EEPROMClass() {
// end();
}
bool EEPROMClass::begin(size_t size) { bool EEPROMClass::begin(size_t size) {
if (size <= 0) { if (size <= 0) {
return false; return false;
@ -51,7 +70,8 @@ bool EEPROMClass::begin(size_t size) {
if (size > SPI_FLASH_SEC_SIZE) { if (size > SPI_FLASH_SEC_SIZE) {
size = SPI_FLASH_SEC_SIZE; size = SPI_FLASH_SEC_SIZE;
} }
_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, EEPROM_FLASH_PARTITION_NAME);
_mypart = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, _name);
if (_mypart == NULL) { if (_mypart == NULL) {
return false; return false;
} }
@ -62,12 +82,12 @@ bool EEPROMClass::begin(size_t size) {
} }
_data = new uint8_t[size]; _data = new uint8_t[size];
_size = size; _size = size;
bool ret = false; bool ret = false;
if (esp_partition_read (_mypart,0, (void *) _data,_size)==ESP_OK) { if (esp_partition_read (_mypart, 0, (void *) _data, _size) == ESP_OK) {
ret=true; ret = true;
} }
return ret; return ret;
} }
@ -98,7 +118,7 @@ uint8_t EEPROMClass::read(int address) {
void EEPROMClass::write(int address, uint8_t value) { void EEPROMClass::write(int address, uint8_t value) {
if (address < 0 || (size_t)address >= _size) if (address < 0 || (size_t)address >= _size)
return; return;
if(!_data) if (!_data)
return; return;
// Optimise _dirty. Only flagged if data written is different. // Optimise _dirty. Only flagged if data written is different.
@ -121,20 +141,20 @@ bool EEPROMClass::commit() {
if (esp_partition_erase_range(_mypart, 0, SPI_FLASH_SEC_SIZE) != ESP_OK) if (esp_partition_erase_range(_mypart, 0, SPI_FLASH_SEC_SIZE) != ESP_OK)
{ {
log_e( "partition erase err."); log_e( "partition erase err.");
} }
else else
{ {
if (esp_partition_write(_mypart, 0, (void *)_data, _size) == ESP_ERR_INVALID_SIZE) if (esp_partition_write(_mypart, 0, (void *)_data, _size) == ESP_ERR_INVALID_SIZE)
{ {
log_e( "error in Write"); log_e( "error in Write");
} }
else else
{ {
_dirty = false; _dirty = false;
ret = true; ret = true;
} }
} }
return ret; return ret;
@ -145,6 +165,286 @@ uint8_t * EEPROMClass::getDataPtr() {
return &_data[0]; return &_data[0];
} }
/*
Get EEPROM total size in byte defined by the user
*/
uint16_t EEPROMClass::length ()
{
return _user_defined_size;
}
/*
Read 'value' from 'address'
*/
uint8_t EEPROMClass::readByte (int address)
{
uint8_t value;
return EEPROMClass::readAll (address, value);
}
int8_t EEPROMClass::readChar (int address)
{
int8_t value;
return EEPROMClass::readAll (address, value);
}
uint8_t EEPROMClass::readUChar (int address)
{
uint8_t value;
return EEPROMClass::readAll (address, value);
}
int16_t EEPROMClass::readShort (int address)
{
int16_t value;
return EEPROMClass::readAll (address, value);
}
uint16_t EEPROMClass::readUShort (int address)
{
uint16_t value;
return EEPROMClass::readAll (address, value);
}
int32_t EEPROMClass::readInt (int address)
{
int32_t value;
return EEPROMClass::readAll (address, value);
}
uint32_t EEPROMClass::readUInt (int address)
{
uint32_t value;
return EEPROMClass::readAll (address, value);
}
int32_t EEPROMClass::readLong (int address)
{
int32_t value;
return EEPROMClass::readAll (address, value);
}
uint32_t EEPROMClass::readULong (int address)
{
uint32_t value;
return EEPROMClass::readAll (address, value);
}
int64_t EEPROMClass::readLong64 (int address)
{
int64_t value;
return EEPROMClass::readAll (address, value);
}
uint64_t EEPROMClass::readULong64 (int address)
{
uint64_t value;
return EEPROMClass::readAll (address, value);
}
float_t EEPROMClass::readFloat (int address)
{
float_t value;
return EEPROMClass::readAll (address, value);
}
double_t EEPROMClass::readDouble (int address)
{
double_t value;
return EEPROMClass::readAll (address, value);
}
bool EEPROMClass::readBool (int address)
{
int8_t value;
return EEPROMClass::readAll (address, value) ? 1 : 0;
}
size_t EEPROMClass::readString (int address, char* value, size_t maxLen)
{
if (!value)
return 0;
if (address < 0 || address + maxLen > _size)
return 0;
uint16_t len;
for (len = 0; len <= _size; len++)
if (_data[address + len] == 0)
break;
if (address + len > _size)
return 0;
memcpy((uint8_t*) value, _data + address, len);
return len;
}
String EEPROMClass::readString (int address)
{
if (address < 0 || address > _size)
return String(0);
uint16_t len;
for (len = 0; len <= _size; len++)
if (_data[address + len] == 0)
break;
if (address + len > _size)
return String(0);
char value[len + 1];
memcpy((uint8_t*) value, _data + address, len);
value[len + 1] = 0;
return String(value);
}
size_t EEPROMClass::readBytes (int address, void* value, size_t maxLen)
{
if (!value || !maxLen)
return 0;
if (address < 0 || address + maxLen > _size)
return 0;
memcpy((void*) value, _data + address, maxLen);
return maxLen;
}
template <class T> T EEPROMClass::readAll (int address, T &value)
{
if (address < 0 || address + sizeof(T) > _size)
return value;
memcpy((uint8_t*) &value, _data + address, sizeof(T));
return value;
}
/*
Write 'value' to 'address'
*/
size_t EEPROMClass::writeByte (int address, uint8_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeChar (int address, int8_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeUChar (int address, uint8_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeShort (int address, int16_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeUShort (int address, uint16_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeInt (int address, int32_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeUInt (int address, uint32_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeLong (int address, int32_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeULong (int address, uint32_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeLong64 (int address, int64_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeULong64 (int address, uint64_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeFloat (int address, float_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeDouble (int address, double_t value)
{
return EEPROMClass::writeAll (address, value);
}
size_t EEPROMClass::writeBool (int address, bool value)
{
int8_t Bool;
value ? Bool = 1 : Bool = 0;
return EEPROMClass::writeAll (address, Bool);
}
size_t EEPROMClass::writeString (int address, const char* value)
{
if (!value)
return 0;
if (address < 0 || address > _size)
return 0;
uint16_t len;
for (len = 0; len <= _size; len++)
if (value[len] == 0)
break;
if (address + len > _size)
return 0;
memcpy(_data + address, (const uint8_t*) value, len + 1);
_dirty = true;
return strlen(value);
}
size_t EEPROMClass::writeString (int address, String value)
{
return EEPROMClass::writeString (address, value.c_str());
}
size_t EEPROMClass::writeBytes (int address, const void* value, size_t len)
{
if (!value || !len)
return 0;
if (address < 0 || address + len > _size)
return 0;
memcpy(_data + address, (const void*) value, len);
_dirty = true;
return len;
}
template <class T> T EEPROMClass::writeAll (int address, const T &value)
{
if (address < 0 || address + sizeof(T) > _size)
return value;
memcpy(_data + address, (const uint8_t*) &value, sizeof(T));
_dirty = true;
return sizeof (value);
}
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM) #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM)
EEPROMClass EEPROM; EEPROMClass EEPROM;
#endif #endif

View File

@ -1,13 +1,14 @@
/* /*
EEPROM.h -ported by Paolo Becchi to Esp32 EEPROM.h -ported by Paolo Becchi to Esp32 from esp8266 EEPROM
-Modified by Elochukwu Ifediora <ifedioraelochukwuc@gmail.com>
use a one sector flash partition defined in partition table Uses a one sector flash partition defined in partition table
OR
from esp8266 EEPROM Multiple sector flash partitions defined by the name column in the partition table
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment. This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
@ -26,7 +27,7 @@
#ifndef EEPROM_h #ifndef EEPROM_h
#define EEPROM_h #define EEPROM_h
#ifndef EEPROM_FLASH_PARTITION_NAME #ifndef EEPROM_FLASH_PARTITION_NAME
#define EEPROM_FLASH_PARTITION_NAME "eeprom" #define EEPROM_FLASH_PARTITION_NAME "eeprom"
#endif #endif
extern "C" { extern "C" {
@ -37,48 +38,91 @@ extern "C" {
} }
// //
// need to define a flash partition for EEPROM with above name // need to define AT LEAST a flash partition for EEPROM with above name
// //
// eeprom , data , 0x99, start address, 0x1000 // eeprom , data , 0x99, start address, 0x1000
// //
class EEPROMClass { class EEPROMClass {
public: public:
EEPROMClass(uint32_t sector); EEPROMClass(uint32_t sector);
EEPROMClass(void); EEPROMClass(const char* name, uint32_t user_defined_size);
EEPROMClass(void);
~EEPROMClass(void);
bool begin(size_t size); bool begin(size_t size);
uint8_t read(int address); uint8_t read(int address);
void write(int address, uint8_t val); void write(int address, uint8_t val);
bool commit(); uint16_t length();
void end(); bool commit();
void end();
uint8_t * getDataPtr(); uint8_t * getDataPtr();
template<typename T> template<typename T>
T &get(int address, T &t) { T &get(int address, T &t) {
if (address < 0 || address + sizeof(T) > _size) if (address < 0 || address + sizeof(T) > _size)
return t;
memcpy((uint8_t*) &t, _data + address, sizeof(T));
return t; return t;
}
memcpy((uint8_t*) &t, _data + address, sizeof(T)); template<typename T>
return t; const T &put(int address, const T &t) {
} if (address < 0 || address + sizeof(T) > _size)
return t;
template<typename T> memcpy(_data + address, (const uint8_t*) &t, sizeof(T));
const T &put(int address, const T &t) { _dirty = true;
if (address < 0 || address + sizeof(T) > _size)
return t; return t;
}
memcpy(_data + address, (const uint8_t*) &t, sizeof(T)); uint8_t readByte(int address);
_dirty = true; int8_t readChar(int address);
return t; uint8_t readUChar(int address);
} int16_t readShort(int address);
uint16_t readUShort(int address);
int32_t readInt(int address);
uint32_t readUInt(int address);
int32_t readLong(int address);
uint32_t readULong(int address);
int64_t readLong64(int address);
uint64_t readULong64(int address);
float_t readFloat(int address);
double_t readDouble(int address);
bool readBool(int address);
size_t readString(int address, char* value, size_t maxLen);
String readString(int address);
size_t readBytes(int address, void * value, size_t maxLen);
template <class T> T readAll (int address, T &);
protected: size_t writeByte(int address, uint8_t value);
uint32_t _sector; size_t writeChar(int address, int8_t value);
uint8_t* _data; size_t writeUChar(int address, uint8_t value);
size_t _size; size_t writeShort(int address, int16_t value);
bool _dirty; size_t writeUShort(int address, uint16_t value);
const esp_partition_t * _mypart; size_t writeInt(int address, int32_t value);
size_t writeUInt(int address, uint32_t value);
size_t writeLong(int address, int32_t value);
size_t writeULong(int address, uint32_t value);
size_t writeLong64(int address, int64_t value);
size_t writeULong64(int address, uint64_t value);
size_t writeFloat(int address, float_t value);
size_t writeDouble(int address, double_t value);
size_t writeBool(int address, bool value);
size_t writeString(int address, const char* value);
size_t writeString(int address, String value);
size_t writeBytes(int address, const void* value, size_t len);
template <class T> T writeAll (int address, const T &);
protected:
uint32_t _sector;
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) #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM)
@ -86,4 +130,3 @@ extern EEPROMClass EEPROM;
#endif #endif
#endif #endif

View File

@ -0,0 +1,92 @@
/*
ESP32 eeprom_class example with EEPROM library
This simple example demonstrates using EEPROM library to store different data in
ESP32 Flash memory in a multiple user-defined EEPROM partition (0x1000 or 4KB max size or less).
Install 'ESP32 Partiton Manager' ONCE from https://github.com/francis94c/ESP32Partitions
And generate different partitions with 'partition_name'
Usage: EEPROMClass ANY_OBJECT_NAME("partition_name", size);
Generated partition that would work perfectly with this example
#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)
*/
#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 AGE("eeprom2", 0x100);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Testing EEPROMClass\n");
if (!NAMES.begin(NAMES.length())) {
Serial.println("Failed to initialise NAMES");
Serial.println("Restarting...");
delay(1000);
ESP.restart();
}
if (!HEIGHT.begin(HEIGHT.length())) {
Serial.println("Failed to initialise HEIGHT");
Serial.println("Restarting...");
delay(1000);
ESP.restart();
}
if (!AGE.begin(AGE.length())) {
Serial.println("Failed to initialise AGE");
Serial.println("Restarting...");
delay(1000);
ESP.restart();
}
char* name = "Teo Swee Ann";
double height = 5.8;
uint32_t age = 47;
// Write: Variables ---> EEPROM partitions
NAMES.put(0, name);
HEIGHT.put(0, height);
AGE.put(0, age);
Serial.print("name: "); Serial.println(name);
Serial.print("height: "); Serial.println(height);
Serial.print("age: "); Serial.println(age);
Serial.println("------------------------------------\n");
// Clear variables
name = '\0';
height = 0;
age = 0;
Serial.print("name: "); Serial.println(name);
Serial.print("height: "); Serial.println(height);
Serial.print("age: "); Serial.println(age);
Serial.println("------------------------------------\n");
// Read: Variables <--- EEPROM partitions
NAMES.get(0, name);
HEIGHT.get(0, height);
AGE.get(0, age);
Serial.print("name: "); Serial.println(name);
Serial.print("height: "); Serial.println(height);
Serial.print("age: "); Serial.println(age);
Serial.println("Done!");
}
void loop() {
// put your main code here, to run repeatedly:
}

View File

@ -0,0 +1,90 @@
/*
ESP32 eeprom_extra example with EEPROM library
This simple example demonstrates using other EEPROM library resources
Created for arduino-esp32 on 25 Dec, 2017
by Elochukwu Ifediora (fedy0)
*/
#include "EEPROM.h"
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("\nTesting EEPROM Library\n");
if (!EEPROM.begin(EEPROM.length())) {
Serial.println("Failed to initialise EEPROM");
Serial.println("Restarting...");
delay(1000);
ESP.restart();
}
int address = 0; // Same address is used through the example
EEPROM.writeByte(address, -128); // -2^7
Serial.println(EEPROM.readByte(address));
EEPROM.writeChar(address, 'A'); // Same as writyByte and readByte
Serial.println(char(EEPROM.readChar(address)));
EEPROM.writeUChar(address, 255); // 2^8 - 1
Serial.println(EEPROM.readUChar(address));
EEPROM.writeShort(address, -32768); // -2^15
Serial.println(EEPROM.readShort(address));
EEPROM.writeUShort(address, 65535); // 2^16 - 1
Serial.println(EEPROM.readUShort(address));
EEPROM.writeInt(address, -2147483648); // -2^31
Serial.println(EEPROM.readInt(address));
EEPROM.writeUInt(address, 4294967295); // 2^32 - 1
Serial.println(EEPROM.readUInt(address));
EEPROM.writeLong(address, -2147483648); // Same as writeInt and readInt
Serial.println(EEPROM.readLong(address));
EEPROM.writeULong(address, 4294967295); // Same as writeUInt and readUInt
Serial.println(EEPROM.readULong(address));
int64_t value = -9223372036854775808; // -2^63
EEPROM.writeLong64(address, value);
value = 0; // Clear value
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
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
EEPROM.writeFloat(address, 1234.1234);
Serial.println(EEPROM.readFloat(address), 4);
EEPROM.writeDouble(address, 123456789.123456789);
Serial.println(EEPROM.readDouble(address), 8);
EEPROM.writeBool(address, true);
Serial.println(EEPROM.readBool(address));
String sentence = "I love ESP32.";
EEPROM.writeString(address, sentence);
Serial.println(EEPROM.readString(address));
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)"
}
void loop() {
// put your main code here, to run repeatedly:
}

View File

@ -7,6 +7,7 @@
####################################### #######################################
EEPROM KEYWORD1 EEPROM KEYWORD1
EEPROMClass KEYWORD1
####################################### #######################################
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)

Binary file not shown.