Skip to content

EEPROM emulation #145

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

Closed
tuxedo0801 opened this issue May 30, 2016 · 18 comments
Closed

EEPROM emulation #145

tuxedo0801 opened this issue May 30, 2016 · 18 comments
Assignees

Comments

@tuxedo0801
Copy link
Contributor

On can read on the official Arduino Zero page (https://www.arduino.cc/en/Main/ArduinoBoardZero):

Memory
The SAMD21 has 256 KB Flash Memory. It also has 32 KB of SRAM and up to 16 KB of EEPROM by emulation.

But there is no EEPROM emulation yet, or?!

The ESP8266 guys also have no EEPROM but flash, and implemented an EEPROM like API:

https://github.com/esp8266/Arduino/blob/master/doc/libraries.md#eeprom

How about doing the same thing for the SAMD?!

@q2dg
Copy link

q2dg commented May 30, 2016

Well, there is https://github.com/cmaglie/FlashStorage ...

@tuxedo0801
Copy link
Contributor Author

That's not very practical compared to what a usual eeprom-lib gives you w.r.t. usability.

@cmaglie
Copy link
Member

cmaglie commented Jun 6, 2016

The ESP8266 guys also have no EEPROM but flash, and implemented an EEPROM like API:

that's not a drop-in replacement for the EEPROM library, there are two fundamental difference:

  • you must call EEPROM.commit() to actually save the changes to flash. This is needed to minimize the amount of writes to the flash memory.
  • you must declare how much flash memory you want to use with EEPROM.begin(size). This is needed to allocate a RAM "buffer" to keep the pending changes waiting to be "committed".

That's not very practical compared to what a usual eeprom-lib gives you w.r.t. usability

it depends, which use case you have in mind?

@tuxedo0801
Copy link
Contributor Author

you must call EEPROM.commit()
you must declare how much flash memory you want to use with EEPROM.begin(size)

that's acceptable from my point of view

it depends, which use case you have in mind?

use case is: use the flash like an eeprom, with almost the same API.

@cmaglie
Copy link
Member

cmaglie commented Jun 8, 2016

use case is: use the flash like an eeprom, with almost the same API.

I could write a wrapper around FlashStorage to emulate the EEPROM API in a similar way to ESP, but what I want to know from you is why you think it's better? What are you trying to do?

The fact that it's almost the same API means that sketch written for the real EEPROM library cannot be used as is, at least you should carefully manage the .commit() action to not consume the Flash lifetime.

@tuxedo0801
Copy link
Contributor Author

I talked to a lot of not so experienced arduino developers. They all have no problem with the well known EEPROM API. But as soon as it's getting more complex than this, the refuse to use it. And they are all confused by the term " EEPROM by emulation", because Arduino Zero platform does not deliver anything that fits this. And adding an external eeprom just to use an API that is eeprom-like is not ideal, especially because of the already existing (flash) memory the samd already provides.

Also there are already existing libraries that makes use of the EEPROM lib. Porting them to samd with a completely different "storage" api is of course possible, but from my point of view it makes no sense that each and every developer has to create it's own "eeprom api adapter" that is able to deal with the EEPROM api and something completely different on Arduino Zero.

Adding those "begin" and "commit" function with a "#ifdef ..." is not a big thing and keeps the difference between an atmega arduino and the samd arduino at minimum.

From my point of view, the API like the ESP8266 guys created is the best achievable way to adapt "non-eeprom-hardware" to the well known eeprom api. All you have to know/add is those two functions, wrapped by an "#ifdef". Very simple, even for an arduino noob.

@spiderkeys
Copy link
Contributor

I've read the samd21 datasheet from beginning to end and have lived in the weeds of each subsystem for the past year writing custom drivers that are wrapped to emulate the Arduino API to keep them arduino developer friendly. At this point, I agree with @cmaglie that the flash storage interface cannot be used as a drop in replacement for the EEPROM and would suggest that it not even have an official wrapper that emulates the EEPROM API. While it might not be immediately accessible for the less experienced developers you talked to, I would argue that the most prudent route forward would be to expose the storage interface using its own library accompanied by documentation that explains how the flash storage subsystem of these ARM chips works. It ultimately doesn'the serve anyone's interests to implement a crippled or potentially life-shortening interface to the storage simply to keep people from reading a couple paragraphs on how to modify their code to use it pragmatically. If you want such a wrapper library, it is definitely possible, but there are several downsides, as @cmaglie points out.

@q2dg
Copy link

q2dg commented Jun 9, 2016

I suppose leveraging up an ARM emulated-EPPROM library as an "official" library, side by side the AVR's one is a fool idea, isn't? I say it because maybe in the future (who knows the future?) there will be more Genuino boards based in ARM than in AVR...Nowadays the result is AVR 3 - ARM 2

@tuxedo0801
Copy link
Contributor Author

I had again a look at this issue and the code by @cmaglie ...
I came up with the idea to simply have a 1k byte[] in a struct and save this to flash with the recommended lib.

pro: use the flash like an eeprom
con: "waste" 1k of RAM

With help of that, it's wrote wrapper (which uses cmaglie's FlashStorage code) that is very similar to the well EEPROM.h API.

There are three new methods:

init() --> call on startup to initially read "eeprom data" from flash
commit() --> write the "eeprom data" to flash: Do this after "bulk eeprom updates" only to keep write-cycles to flash as low as possible
isValid() --> returns true, if "eeprom data" has been written at least once, otherwise will return false (f.i. just after sketch upload, when flash is empty)

By using #ifdef one can call this new methods on samd21 systems only ...

I've not created a project/repository so far. So here's the quick'n'dirty code (feel free to use it or ignore it):

Samd21Eeprom.h

/*
  Copyright (c) 2015 Arduino LLC.  All right reserved.
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the GNU Lesser General Public License for more details.
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


  EEPROM like API that uses Arduino Zero's flash memory. 
  Requirements: cmaglie's Flash Storage: https://github.com/cmaglie/FlashStorage
  (c) 2016, A. Christian
*/

#ifndef EEPROM_h
#define EEPROM_h

#include <FlashStorage.h>

#ifndef EEPROM_EMULATION_SIZE
#define EEPROM_EMULATION_SIZE 1024
#endif

typedef struct {
  byte data[EEPROM_EMULATION_SIZE];
  boolean valid;  
} EEPROM_EMULATION;


class EEPROMClass {

  public:
    EEPROMClass(void);
    uint8_t read(int);
    void write(int, uint8_t);
    void update(int, uint8_t);
    bool isValid();
    void init();
    void commit();

  protected:
    EEPROM_EMULATION _eeprom;
    bool _dirty;
    FlashStorageClass<EEPROM_EMULATION> *_flash;

};

extern EEPROMClass EEPROM;

#endif

Samd21Eeprom.cpp

/*
  Copyright (c) 2015 Arduino LLC.  All right reserved.
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the GNU Lesser General Public License for more details.
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


  EEPROM like API that uses Arduino Zero's flash memory. 
  Requirements: cmaglie's Flash Storage: https://github.com/cmaglie/FlashStorage
  (c) 2016, A. Christian
*/

#include "Arduino.h"
#include "Samd21Eeprom.h"

FlashStorage(my_flash_ptr, EEPROM_EMULATION); 

EEPROMClass::EEPROMClass(void) {
  _dirty = false;
  _eeprom.valid = false;  


  _flash = &my_flash_ptr;
}

uint8_t EEPROMClass::read(int address)
{
  return _eeprom.data[address]; 
}

void EEPROMClass::write(int address, uint8_t value)
{
  _dirty = true;
  _eeprom.data[address] = value; 
}

void EEPROMClass::update(int address, uint8_t value)
{
  _eeprom.data[address] = value; 
}

void EEPROMClass::init()
{
  _eeprom = _flash->read();
}

bool EEPROMClass::isValid()
{
  return _eeprom.valid;
}

void EEPROMClass::commit()
{
  if (_dirty) {
    _eeprom.valid=true;
    _flash->write(_eeprom);
  }
}

EEPROMClass EEPROM;

Issue is now solved to me.

@q2dg
Copy link

q2dg commented Sep 29, 2016

Well,I wouldn't close this until this piece of code (of similar) gets merged into official EEPROM library repository (https://github.com/arduino/Arduino/tree/8385aedc642d6cd76b50ac5167307121007e5045/hardware/arduino/avr/libraries/EEPROM, which should be moved then to another folder architecture's agnostic). I think some official solution should be given

@tuxedo0801
Copy link
Contributor Author

Sorry, I don't get it... First, you say that creating such an eeprom like api is a fool idea, and now you want to have it merged into official EEPROM lib repo?

@q2dg
Copy link

q2dg commented Sep 29, 2016

I'm not from Arduino crew. I only expressed a personal opinion

El 29 sept. 2016 17:44, "Alex" [email protected] escribió:

Sorry, I don't get it... First, you say that creating such an eeprom like
api is a fool idea, and now you want to have it merged into official EEPROM
lib repo?


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#145 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AG8Belv6R_pnsAZeh3Ml9ym15G2DGN4uks5qu9zCgaJpZM4Ipuoq
.

@tuxedo0801
Copy link
Contributor Author

Sure. but that does not solve my confusion. Why you changed your mind about eeprom lib for samd that is using flash memory?

@q2dg
Copy link

q2dg commented Sep 29, 2016

Well...taking EEPROM memory as an software abstraction of "data" memory vs. regular "program" memory is fine, but if (far) future is based on ARM devices, maybe the concept of EEPROM as a physically separated memory will vanish, so in that moment, people maybe will ask about what kind of memory we are talking really. What I want to say, definitely, is that the idea is fine but maybe the name of EEPROM as the static class should be avoided (in favour of something more generic as "FlashStorage" or something similar. So, until this problem doesn't get resolved ("will a official storage-only flash library be finally implemented on ARM devices? and, if it will, how?") I'd keep open this issue

@tuxedo0801
Copy link
Contributor Author

Name can be changed. All I wanted to do, is to write a binary blob that I receive via UART to memory and read/write parts of that blob byte by byte. And therefore (and among other things), the "EEPROM API" is the best solution for me.

If you name it EEPROM or "byte-wise-flash-storage"... I don't care. But anyhow, it's a "EEPROM-like API".

@PaulStoffregen
Copy link

nothing delays software quite like indecision can

@human890209
Copy link

Hi,
I get an ARM Arduino lately and study these EEPROM emulation topics.
My question is: Is it better to place the EEPROM on the end part of FLASH?
I'm an Arduino beginner. I don't know how the FLASH usage management works. An HDD hard drive got the software managing the data storage. Make "wear out" to be split evenly. How did Arduino's Flash be managed? Every time I upload the simple Blink example, did it stored at the beginning of the Flash area?
And if I use the end part of Flash to simulate EEPROM and it "wear out completely". Is it okay to continue using it? is 512k turn to be 511k if I just wear out the last 1k? Then I just use the last 1k of 511k? I guess if the beginning is worn out, the Arduino will be doomed. right?

@cmaglie
Copy link
Member

cmaglie commented Jul 4, 2018

Is it okay to continue using it? is 512k turn to be 511k if I just wear out the last 1k? Then I just use the last 1k of 511k? I guess if the beginning is worn out, the Arduino will be doomed. right?

It should be as you said, BTW I guess that nobody has a direct experience to confirm it, I never experienced a wear-out of flash memory in real life.

Also you should "detect" in some way that the latest 1k has worn out (maybe re-read the written to check if the write was successful?).

There is someone that has tried to purposely wear out a flash cmaglie/FlashStorage#19 maybe you want to continue the discussion in that thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants