0

I would like to encapsulate the usage of the Arduino functions EEPROM.put and EEPROM.write inside another function (which also begins and ends communication with EEPROM), so I have created these two functions:

void eeprom_save(uint addr, uint8_t *data, uint len) {
  EEPROM.begin(len);
  EEPROM.put(addr, *data);
  EEPROM.commit();
  EEPROM.end();
}

void eeprom_load(uint addr, uint8_t *data, uint len) {
  EEPROM.begin(len);
  EEPROM.get(addr, *data);
  EEPROM.end();
}

I'm calling the functions like so:

uint8_t scale_data[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
eeprom_save(0, scale_data, sizeof(scale_data));
// ... here is some code to clear the scale_data, to read back from EEPROM ...
eeprom_load(0, scale_data, sizeof(scale_data));

As far as I could analyze, it saves the values properly to EEPROM, but reading the EEPROM with my function eeprom_load does not work (returns only 0, 0, 0, 0, 0, ...)

PS: I'm using the ESP8266 Cores EEPROM implementation.

I guess I have some trouble understanding the pointers used?

How to solve this?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
John
  • 139
  • 1
  • 9
  • [The official Arduino `EEPROM` reference documentation](https://www.arduino.cc/en/Reference/EEPROM) doesn't really match your code. The official examples have no `begin`, `commit` or `end` calls. And [the `get` function](https://www.arduino.cc/en/Reference/EEPROMGet) seems to be able to read data for more complex objects, possibly including arrays. – Some programmer dude Feb 06 '21 at 13:26
  • [Arduino EEPROM write and read array?](https://stackoverflow.com/a/15474597) – 001 Feb 06 '21 at 13:28
  • @Someprogrammerdude I'm using the ESP8266 framework, see https://github.com/esp8266/Arduino/blob/master/libraries/EEPROM/EEPROM.h – John Feb 06 '21 at 13:28
  • @JohnnyMopp Don't want to use write, because I do not want to overwrite unnecessary parts of the EEPROM (because the values are equal to the already stored value), therefore I would like to use get/put. Also I'm using it with the ESP8266 core. – John Feb 06 '21 at 13:30
  • 3
    If you look at the source code you linked to, the `put` function has: `memcpy(_data + address, (const uint8_t*)&t, sizeof(T));` You are passing a `uint8_t` so `sizeof(T) = 1` and it only writes one byte. I would use a loop. – 001 Feb 06 '21 at 13:35
  • @JohnnyMopp But the put implementation seems to work fine . If I use EEPROM.get(0, scale_data), I'm getting back all correct values. Only my own encapsulation of the EEPROM.get seems to have issues? – John Feb 06 '21 at 13:39
  • if you use it on `scale_data` then sizeof(scale_data) is 16. but with pointer it stores the pointer – Juraj Feb 06 '21 at 13:49

1 Answers1

1

IMHO, the class cannot handle arrays (that have decayed to pointers). So you need to use a loop:

void eeprom_save(uint addr, uint8_t *data, uint len) {
  EEPROM.begin(len);
  for (uint i = 0; i < len; i++) {
    EEPROM.put(addr + i, data[i]);
  }
  EEPROM.commit();
  EEPROM.end();
}

void eeprom_load(uint addr, uint8_t *data, uint len) {
  EEPROM.begin(len);
  for (uint i = 0; i < len; i++) {
    EEPROM.get(addr + i, data[i]);
  }
  EEPROM.end();
}

Another option would be to extend the class to handle arrays. This is untested and I have never used that class before, but I think it should work.

class MyEEPROMClass : public EEPROMClass {
public:
    template<typename T>
    T* get(int const address, T *t, size_t len) {
        if (address < 0 || address + len > _size)
            return t;
        memcpy((uint8_t*)t, _data + address, len);
        return t;
    }

    template<typename T> 
    const T* put(int const address, const T *t, size_t len) {
        if (address < 0 || address + len > _size)
            return t;
        if (memcmp(_data + address, (const uint8_t*)t, len) != 0) {
            _dirty = true;
            memcpy(_data + address, (const uint8_t*)t, len);
        }
        return t;
    }
};
001
  • 13,291
  • 5
  • 35
  • 66
  • this could fail if the EEPROM class implementation changes. for example if wear leveling is added – Juraj Feb 06 '21 at 14:30