Skip to content

add configurable EEPROM length #127

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

Merged
merged 5 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@

void setup()
{
// You may choose to enable more or less EEPROM -
// Default length is 1024 bytes (if setLength is not called)
EEPROM.setLength(1080); // this would make the length 1080 bytes
// EEPROM.setLength(AP3_EEPROM_MAX_LENGTH); // the maximum length is 8192 bytes (AP3_EEPROM_MAX_LENGTH)
// Note: larger sizes will increase RAM usage and execution time

Serial.begin(115200);
Serial.println("EEPROM Examples");

Expand All @@ -44,25 +50,25 @@ void setup()
Serial.println("8 bit tests");
byte myValue1 = 200;
byte myValue2 = 23;
randomLocation = random(0, AP3_FLASH_EEPROM_SIZE);
randomLocation = random(0, EEPROM.length() - sizeof(myValue1));

startTime = millis();
EEPROM.write(randomLocation, myValue1); //(location, data)
endTime = millis();
EEPROM.put(randomLocation + 1, myValue2);
EEPROM.put(randomLocation + sizeof(myValue1), myValue2);

Serial.printf("Write byte time: %dms\n", endTime - startTime);

startTime = millis();
EEPROM.write(randomLocation, myValue1); //(location, data)
endTime = millis();

Serial.printf("Write identical byte to same location (should be ~1): %dms\n", endTime - startTime);
Serial.printf("Write identical byte to same location: %dms\n", endTime - startTime);

byte response1 = EEPROM.read(randomLocation);
byte response2 = EEPROM.read(randomLocation + 1);
byte response2 = EEPROM.read(randomLocation + sizeof(myValue1));
Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue1, response1);
Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 1, myValue2, response2);
Serial.printf("Location %d should be %d: %d\n\r", randomLocation + sizeof(myValue1), myValue2, response2);
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Serial.println("");
Expand All @@ -72,17 +78,17 @@ void setup()
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
uint16_t myValue3 = 3411;
int16_t myValue4 = -366;
randomLocation = random(0, AP3_FLASH_EEPROM_SIZE);
randomLocation = random(0, EEPROM.length() - sizeof(myValue3));

EEPROM.put(randomLocation, myValue3);
EEPROM.put(randomLocation + 2, myValue4);
EEPROM.put(randomLocation + sizeof(myValue3), myValue4);

uint16_t response3;
int16_t response4;
EEPROM.get(randomLocation, response3);
EEPROM.get(randomLocation + 2, response4);
EEPROM.get(randomLocation + sizeof(myValue3), response4);
Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue3, response3);
Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 2, myValue4, response4);
Serial.printf("Location %d should be %d: %d\n\r", randomLocation + sizeof(myValue3), myValue4, response4);
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Serial.println("");
Expand All @@ -93,52 +99,52 @@ void setup()
Serial.printf("Size of int: %d\n", sizeof(int));
int myValue5 = -245000;
unsigned int myValue6 = 400123;
randomLocation = random(0, AP3_FLASH_EEPROM_SIZE);
randomLocation = random(0, EEPROM.length() - sizeof(myValue5));

EEPROM.put(randomLocation, myValue5);
EEPROM.put(randomLocation + 4, myValue6);
EEPROM.put(randomLocation + sizeof(myValue5), myValue6);

int response5;
unsigned int response6;
EEPROM.get(randomLocation, response5);
EEPROM.get(randomLocation + 4, response6);
EEPROM.get(randomLocation + sizeof(myValue5), response6);
Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue5, response5);
Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 4, myValue6, response6);
Serial.printf("Location %d should be %d: %d\n\r", randomLocation + sizeof(myValue5), myValue6, response6);
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

//int32_t and uint32_t sequential test
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
int32_t myValue7 = -341002;
uint32_t myValue8 = 241544;
randomLocation = random(0, AP3_FLASH_EEPROM_SIZE);
randomLocation = random(0, EEPROM.length() - sizeof(myValue7));

EEPROM.put(randomLocation, myValue7);
EEPROM.put(randomLocation + 4, myValue8);
EEPROM.put(randomLocation + sizeof(myValue7), myValue8);

int32_t response7;
uint32_t response8;
EEPROM.get(randomLocation, response7);
EEPROM.get(randomLocation + 4, response8);
EEPROM.get(randomLocation + sizeof(myValue7), response8);
Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue7, response7);
Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 4, myValue8, response8);
Serial.printf("Location %d should be %d: %d\n\r", randomLocation + sizeof(myValue7), myValue8, response8);
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

//float (32) sequential test
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Serial.printf("Size of float: %d\n", sizeof(float));
float myValue9 = -7.35;
float myValue10 = 5.22;
randomLocation = random(0, AP3_FLASH_EEPROM_SIZE);
randomLocation = random(0, EEPROM.length() - sizeof(myValue9));

EEPROM.put(randomLocation, myValue9);
EEPROM.put(randomLocation + 4, myValue10);
EEPROM.put(randomLocation + sizeof(myValue9), myValue10);

float response9;
float response10;
EEPROM.get(randomLocation, response9);
EEPROM.get(randomLocation + 4, response10);
EEPROM.get(randomLocation + sizeof(myValue9), response10);
Serial.printf("Location %d should be %f: %f\n\r", randomLocation, myValue9, response9);
Serial.printf("Location %d should be %f: %f\n\r", randomLocation + 4, myValue10, response10);
Serial.printf("Location %d should be %f: %f\n\r", randomLocation + sizeof(myValue9), myValue10, response10);
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Serial.println("");
Expand All @@ -151,24 +157,24 @@ void setup()
double myValue12 = 384.95734987;
double myValue13 = 917.14159;
double myValue14 = 254.8877;
randomLocation = random(0, AP3_FLASH_EEPROM_SIZE);
randomLocation = random(0, EEPROM.length() - sizeof(myValue11));

startTime = millis();
EEPROM.put(randomLocation, myValue11);
endTime = millis();
Serial.printf("Time to record 64-bits: %dms\n", endTime - startTime);

EEPROM.put(randomLocation + 8, myValue12);
EEPROM.put(randomLocation + sizeof(myValue11), myValue12);
EEPROM.put(EEPROM.length() - sizeof(myValue13), myValue13); //Test end of EEPROM space

double response11;
double response12;
double response13;
EEPROM.get(randomLocation, response11);
EEPROM.get(randomLocation + 8, response12);
EEPROM.get(randomLocation + sizeof(myValue11), response12);
EEPROM.get(EEPROM.length() - sizeof(myValue13), response13);
Serial.printf("Location %d should be %lf: %lf\n", randomLocation, myValue11, response11);
Serial.printf("Location %d should be %lf: %lf\n", randomLocation + 8, myValue12, response12);
Serial.printf("Location %d should be %lf: %lf\n", randomLocation + sizeof(myValue11), myValue12, response12);
Serial.printf("Edge of EEPROM %d should be %lf: %lf\n", EEPROM.length() - sizeof(myValue13), myValue13, response13);

double response14;
Expand All @@ -183,7 +189,7 @@ void setup()
//String write test
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
char myString[19] = "How are you today?";
randomLocation = random(0, AP3_FLASH_EEPROM_SIZE);
randomLocation = random(0, EEPROM.length() - sizeof(myString));
EEPROM.put(randomLocation, myString);

char readMy[19];
Expand Down
25 changes: 16 additions & 9 deletions libraries/EEPROM/src/EEPROM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@
#include "EEPROM.h"
#include "Arduino.h"

EEPROMClass EEPROM; // the (magnificent) one and only EEPROM!!!!!

//Write a byte to a given "EEPROM" location
void write(uint16_t eepromLocation, uint8_t dataToWrite)
void write(uint16_t eepromLocation, uint8_t dataToWrite, uint16_t allowedSize)
{
writeBlockToEEPROM(eepromLocation, &dataToWrite, 1);
writeBlockToEEPROM(eepromLocation, &dataToWrite, 1, allowedSize);
}

//Read a byte from a given location in "EEPROM"
Expand All @@ -66,23 +68,23 @@ void EEPROMClass::erase()
//3) Check if new data is different from flash.
//4) Erase flash page (8k)
//5) Write SRAM back into flash
void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize)
void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize, uint16_t allowedSize)
{
//Error check
if (eepromLocation + blockSize >= AP3_FLASH_EEPROM_SIZE)
if (eepromLocation + blockSize >= allowedSize)
{
blockSize = AP3_FLASH_EEPROM_SIZE - eepromLocation;
blockSize = allowedSize - eepromLocation;
}

//Read the contents of current "EEPROM" to SRAM
//Flash is written in 32-bit words but user passes in array of bytes
//Create an array of 32-bit words but reference it a byte at a time
uint32_t flashContent[AP3_FLASH_EEPROM_SIZE / 4];
uint32_t flashContent[allowedSize / 4];

//We can't read 32bits at a time because the way flash is oriented (little endian)
//So we read a byte at a time
uint8_t *eepromContents = (uint8_t *)flashContent;
for (uint16_t x = 0; x < AP3_FLASH_EEPROM_SIZE; x++)
for (uint16_t x = 0; x < allowedSize; x++)
{
eepromContents[x] = *(uint8_t *)(AP3_FLASH_EEPROM_START + x);
}
Expand All @@ -96,7 +98,7 @@ void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uin
//Run a check here to see if the new data is the same as what's in flash. If it's the same,
//just return, don't erase flash.
bool theSame = true;
for (uint16_t x = 0; x < AP3_FLASH_EEPROM_SIZE; x++)
for (uint16_t x = 0; x < allowedSize; x++)
{
if (eepromContents[x] != *(uint8_t *)(AP3_FLASH_EEPROM_START + x))
{
Expand All @@ -116,5 +118,10 @@ void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uin
am_hal_flash_program_main(AM_HAL_FLASH_PROGRAM_KEY,
flashContent,
(uint32_t *)AP3_FLASH_EEPROM_START,
AP3_FLASH_EEPROM_SIZE / 4);
allowedSize / 4);
}

EERef &EERef::operator=(uint8_t in)
{
return write(index, in, EEPROM.length()), *this;
}
44 changes: 32 additions & 12 deletions libraries/EEPROM/src/EEPROM.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,29 @@
//The SparkFun Apollo3 linker script has been modified to limit user code space to less than 0xFE000

#define AP3_FLASH_EEPROM_START 0xFE000
#define AP3_FLASH_PAGE_SIZE 8192
#define AP3_EEPROM_MAX_LENGTH (AP3_FLASH_PAGE_SIZE - 16)

#if AP3_FLASH_EEPROM_START % 8192
#if AP3_FLASH_EEPROM_START % AP3_FLASH_PAGE_SIZE
Error : EEPROM start address must be divisble by 8192
#endif

//By limiting EEPROM size to 1024 bytes, we reduce the amount of SRAM required and
//time needed to read/write words into flash. It can be increased
//to 2048 if needed
//The size of the EEPROM may be (optionally) user-configured using the EEPROM.setLength()
//method. Valid values are in the range [0, AP3_EEPROM_MAX_LENGTH]. Reducing the size of
//EEPROM will cause data stored in the higher addresses to be lost. The default size is
//set below. See Example2_AllFunctions for a usage example.

//Operations on psuedo-EEPROM require a read-write-modify cycle on the entire
//configured memory area because flash pages cannot be partially erased. The
//larger the memory area the longer this operation will take. Here are some
//benchmarks:
//1024 = 19ms update time
//2048 = 23ms update time
const int AP3_FLASH_EEPROM_SIZE = 1024; //In bytes
const uint16_t AP3_DEFAULT_FLASH_EEPROM_SIZE = 1024; //In bytes

uint8_t read(uint16_t eepromLocation);
void write(uint16_t eepromLocation, uint8_t dataToWrite);
void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize);
void write(uint16_t eepromLocation, uint8_t dataToWrite, uint16_t allowedSize);
void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize, uint16_t allowedSize);

struct EERef
{
Expand All @@ -86,7 +94,7 @@ struct EERef

//Assignment/write members.
EERef &operator=(const EERef &ref) { return *this = *ref; }
EERef &operator=(uint8_t in) { return write(index, in), *this; }
EERef &operator=(uint8_t in);
EERef &operator+=(uint8_t in) { return *this = **this + in; }
EERef &operator-=(uint8_t in) { return *this = **this - in; }
EERef &operator*=(uint8_t in) { return *this = **this * in; }
Expand Down Expand Up @@ -163,7 +171,10 @@ struct EEPROMClass
//Basic user access methods.
EERef operator[](const int idx) { return idx; }
uint8_t read(int idx) { return EERef(idx); }
void write(int idx, uint8_t val) { (EERef(idx)) = val; }
void write(int idx, uint8_t val)
{
(EERef(idx)) = val;
}
void update(int idx, uint8_t val) { EERef(idx).update(val); }
void erase();

Expand All @@ -174,7 +185,14 @@ struct EEPROMClass
return 0x00;
}
EEPtr end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid.
uint16_t length() { return AP3_FLASH_EEPROM_SIZE; }
uint16_t length()
{
return allowedSize;
}
void setLength(uint16_t length)
{
allowedSize = (length <= AP3_EEPROM_MAX_LENGTH) ? length : AP3_EEPROM_MAX_LENGTH;
}

//Functionality to 'get' and 'put' objects to and from EEPROM.
template <typename T>
Expand All @@ -192,11 +210,13 @@ struct EEPROMClass
{
const uint8_t *ptr = (const uint8_t *)&t;

writeBlockToEEPROM(idx, ptr, sizeof(T)); //Address, data, sizeOfData
writeBlockToEEPROM(idx, ptr, sizeof(T), allowedSize); //Address, data, sizeOfData

return t;
}

uint16_t allowedSize = AP3_DEFAULT_FLASH_EEPROM_SIZE;
};

static EEPROMClass EEPROM __attribute__((unused));
extern EEPROMClass EEPROM;
#endif //_EEPROM_H