@rick
According to document EEPROM.put should support power-fail recovery.
https://docs.particle.io/reference/device-os/firmware/photon/#put-
If the Photon loses power before the write finishes, the partially written data will be ignored.
But I did not find any algorithm do power-fail recovery work,for example I call EEPROM.put(a float number) and power off when only two byte write back to flash,when I read this float number when power on again something will go wrong.
// Writes a new value for a byte of EEPROM
// Performs a page swap (move all valid records to a new page)
// if the current page is full
void put(Index index, Data data)
{
writeRange(index, &data, sizeof(data));
}
// Write each byte in the range if its value has changed.
void writeRange(Index indexBegin, const Data *data, uint16_t length)
{
// don't write anything if index is out of range
Index indexEnd = indexBegin + length;
if(indexEnd > capacity())
{
return;
}
// Read existing values for range
std::unique_ptr<Data[]> existingData(new Data[length]);
// don't write anything if memory is full
if(!existingData)
{
return;
}
Address writeAddressBegin;
// Read the data and make sure there are no previous invalid
// records before starting to write
bool success = readRangeAndFindEmpty(getActivePage(),
existingData.get(), indexBegin, length, writeAddressBegin);
// Write records for all new values
success = success && writeRangeChanged(writeAddressBegin, indexBegin, data, existingData.get(), length);
// If any writes failed because the page was full or a marginal
// write error occured, do a page swap then write all the
// records
if(!success)
{
swapPagesAndWrite(indexBegin, data, length);
}
}
// Write new records backwards in Flash. This ensures data
// consistency if writeRange is interrupted by a reset since reads
// stop at the first non-valid record.
bool writeRangeChanged(Address writeAddressBegin, Index indexBegin, const uint8_t *data, const uint8_t *existingData, uint16_t length)
{
bool success = true;
// Count changed values
uint16_t changedCount = 0;
for(uint16_t i = 0; i < length && success; i++)
{
if(existingData[i] != data[i])
{
changedCount++;
}
}
// Write all changed values, backwards from the end
if(changedCount > 0)
{
Address writeAddress = writeAddressBegin + changedCount * sizeof(Record);
Address endAddress = getPageEnd(getActivePage());
// There must be an empty record after the position where the
// last record will be written to act as a separator for the
// valid record detection algorithm to work well
if(writeAddress < endAddress)
{
Record separatorRecord;
store.read(writeAddress, &separatorRecord, sizeof(separatorRecord));
success = separatorRecord.empty();
}
for(uint16_t i = 0; i < length && success; i++)
{
if(existingData[i] != data[i])
{
Index index = indexBegin + i;
writeAddress -= sizeof(Record);
success = success && writeRecord(
writeAddress, endAddress, Record(index, data[i]));
}
}
}
return success;
}
One Record save one byte,So only one byte can be recovery after power-fail issue.Any type for example float more than one byte can not recovery after power-fail issue.Am I right?