Search code examples
cfunctionpointersarduinoarduino-esp8266

How to encapsulate EEPROM.put and EEPROM.get in own functions (Arduino / C / ESP8266)?


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?


Solution

  • 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;
        }
    };