ESP8266's EEPROM - Does commit check if data is different before write?

I have ESP8266 (https://en.wikipedia.org/wiki/ESP8266) NodeMCU boards and I am using Arduino IDE to program it.

Looking at EEPROM library the write and put functions (https://www.arduino.cc/en/Tutorial/EEPROMPut) first check if data is different and then only write it which is great because EEPROM only has so many writes.

The wrinkle is that ESP8266 has no real EEPROM but uses a piece of FLASH memory instead. So, EEPROM's get and put functions only write to RAM and you have to call EEPROM.commit() to write RAM contents to FLASH (to persist).

My two questions - 1. In ESP8266's case, is FLASH similar in terms of limited writes to the EEPROM? 2. If the answer for 1. is yes, then does anyone know if EEPROM.commit() will also check if the RAM contents are different than FLASH and only then would write it? Or do I need to do this check on my own to avoid unnecessarily writing the same data and using up my limited writes?

Thanks!

  1. This page speaks to the memory write limit.

  2. I don't think so, I don"t see an EEPROM read anywhere to get the value to compare to. Here is the source for commit.

bool EEPROMClass::commit() {
  bool ret = false;
  if (!_size)
    return false;
  if(!_dirty)
    return true;
  if(!_data)
    return false;

  noInterrupts();
  if(spi_flash_erase_sector(_sector) == SPI_FLASH_RESULT_OK) {
    if(spi_flash_write(_sector * SPI_FLASH_SEC_SIZE, reinterpret_cast(_data), _size) == SPI_FLASH_RESULT_OK) {
      _dirty = false;
      ret = true;
    }
  }
  interrupts();

  return ret;
}

And write:

void EEPROMClass::write(int address, uint8_t value) {
  if (address < 0 || (size_t)address >= _size)
    return;
  if(!_data)
    return;

  _data[address] = value;
  _dirty = true;
}

matrixIII: 1. In ESP8266's case, is FLASH similar in terms of limited writes to the EEPROM?

Yes. I'm not sure what the number of writes it's rated for. It's tricky because the ESP8266 chip doesn't have any internal flash memory. The ESP8266 modules use an external flash chip. So you can't use the ESP8266 datasheet. You need to figure out the model number of the flash chip and those are usually hidden under a metal can. But we do know that we should avoid excessive numbers of writes.

matrixIII: 2. If the answer for 1. is yes, then does anyone know if EEPROM.commit() will also check if the RAM contents are different than FLASH and only then would write it? Or do I need to do this check on my own to avoid unnecessarily writing the same data and using up my limited writes?

It does check so you don't need to do that. What happens is that every time you call EEPROM.write() it checks if the data is different from what's already in flash. If it is different then it sets the _dirty flag. When you call EEPROM.commit() if the _dirty flag has not been set then it just returns without doing a write.

Thanks for pointing me in the right direction! I did a search in my libraries and following is what I have. It seems like write does set _dirty only when it is being changed and commit does not do anything if _dirty isn't set.

void EEPROMClass::write(int address, uint8_t value) {
  if (address < 0 || (size_t)address >= _size)
    return;
  if(!_data)
    return;

  // Optimise _dirty. Only flagged if data written is different.
  uint8_t* pData = &_data[address];
  if (*pData != value)
  {
    *pData = value;
    _dirty = true;
  }
}

bool EEPROMClass::commit() {
  bool ret = false;
  if (!_size)
    return false;
  if(!_dirty)
    return true;
  if(!_data)
    return false;

  noInterrupts();
  if(spi_flash_erase_sector(_sector) == SPI_FLASH_RESULT_OK) {
    if(spi_flash_write(_sector * SPI_FLASH_SEC_SIZE, reinterpret_cast(_data), _size) == SPI_FLASH_RESULT_OK) {
      _dirty = false;
      ret = true;
    }
  }
  interrupts();

  return ret;
}

I’m not that good at English and that’s why there’s one point I’m not sure about: Does EEPROM.commit override ALL flash-values even if only one value changed or does it only override that parts of the flash where the data has changed?

I hope you’re able to understand my question!