Repository navigation
eeprom
EEPROM keeps settings in MCU flash under 32-bit keys, for example a setpoint, a calibration or a counter. The microcontroller has no EEPROM of its own, so the library emulates one in flash. Like PDB, it never changes what is written: a new value goes into a new slot, and reading takes the newest one.
- The store takes an even number of flash pages and splits them into two halves, A and B. One half takes writes, the other stays erased.
- Every write adds one 8-byte slot: the key and the value, 4 bytes each. A key written again takes a new slot, and the newest one wins.
- A rewritten half starts with a BEGIN tag and ends with a marker carrying its generation, a counter that grows with every rewrite.
- The four highest keys,
0xFFFFFFFCand up, belong to EEPROM itself, and a write with one of them is refused.
When the active half is full, EEPROM rewrites it into the other one, in this order:
- The BEGIN tag.
- The newest value of every key, one slot each.
- The marker with the next generation.
- Only then the full half is erased.
The history of a key shrinks to a single slot, and writing goes on in the new half. A key that does not fit in the half is lost in the rewrite, so the set of keys has to be well below the size of a half.
Power can go out at any moment. At the next start EEPROM_Init reads both halves and tells what was going on:
- Cut while writing: the slot is not finished, so it does not count, and its key keeps the old value.
- Cut during a rewrite, before the marker: the new half has a BEGIN tag but no marker, so it is erased and the rewrite runs again.
- Cut after the marker, before the full half is erased: both halves are complete, the higher generation wins and the other half is erased.
- Cut late in an erase: the page can read erased without being erased whole, so EEPROM erases a half whole before it writes there, even one that reads erased.
A cut during this recovery is handled the same way at the next start. After a cut at any moment every key reads its last written value, and the key being written its old value or the new one. Tests on the computer cut the power at every flash cycle of a long run of writes and rewrites, and during the recovery itself.
Three cases stay outside this guarantee:
- A value kept under two keys, a 64-bit one for example, is two writes, so a cut between them leaves its parts from two different writes.
-
EEPROM_Clearcut halfway can leave old values readable. - The newest slot counts only when it reads back clean, so a key written once loses its value if a bit of that slot flips with age.
A store of its own: two pages and a key for every setting, the same in every firmware version.
enum { KEY_Setpoint = 1, KEY_Hysteresis = 2 };
// Two pages outside the program and the board stores
static EEPROM_t settings = { .page_start = 50, .page_count = 2 };After every start EEPROM_Init goes first, and every read gives a default for a key not written yet.
static uint32_t setpoint, hysteresis;
void settings_init(void)
{
EEPROM_Init(&settings); // recovers whatever a power cut left
// A key not written yet reads as its default
setpoint = EEPROM_Read(&settings, KEY_Setpoint, 1500);
hysteresis = EEPROM_Read(&settings, KEY_Hysteresis, 50);
}
void setpoint_set(uint32_t value)
{
if(EEPROM_Write(&settings, KEY_Setpoint, value) == OK) setpoint = value;
}