私が通常使用する手法は、データの先頭に4バイトのローリングシーケンス番号を付けることです。ここで、最大の番号は最新の値を表します。合計6バイトになる実際のデータの2バイトを保存する場合、128バイトのEEPROMに対して21エントリが含まれ、耐久性が21倍になるように、循環キュー構成になります。
次に、ブート時に最大のシーケンス番号を使用して、次に使用するシーケンス番号とキューの現在のテールの両方を決定できます。次のC擬似コードは、初期プログラミング時にEEPROMエリアが0xFFの値に消去されたため、0xFFFFのシーケンス番号を無視することを前提としています。
struct
{
uint32_t sequence_no;
uint16_t my_data;
} QUEUE_ENTRY;
#define EEPROM_SIZE 128
#define QUEUE_ENTRIES (EEPROM_SIZE / sizeof(QUEUE_ENTRY))
uint32_t last_sequence_no;
uint8_t queue_tail;
uint16_t current_value;
// Called at startup
void load_queue()
{
int i;
last_sequence_no = 0;
queue_tail = 0;
current_value = 0;
for (i=0; i < QUEUE_ENTRIES; i++)
{
// Following assumes you've written a function where the parameters
// are address, pointer to data, bytes to read
read_EEPROM(i * sizeof(QUEUE_ENTRY), &QUEUE_ENTRY, sizeof(QUEUE_ENTRY));
if ((QUEUE_ENTRY.sequence_no > last_sequence_no) && (QUEUE_ENTRY.sequence_no != 0xFFFF))
{
queue_tail = i;
last_sequence_no = QUEUE_ENTRY.sequence_no;
current_value = QUEUE_ENTRY.my_data;
}
}
}
void write_value(uint16_t v)
{
queue_tail++;
if (queue_tail >= QUEUE_ENTRIES)
queue_tail = 0;
last_sequence_no++;
QUEUE_ENTRY.sequence_no = last_sequence_no;
QUEUE_ENTRY.my_data = v;
// Following assumes you've written a function where the parameters
// are address, pointer to data, bytes to write
write_EEPROM(queue_tail * sizeof(QUEUE_ENTRY), &QUEUE_ENTRY, sizeof(QUEUE_ENTRY));
current_value = v;
}
EEPROMが小さい場合、標準のデータ型を使用する代わりにビットを少しスライスする必要がありますが、3バイトシーケンスの方が効率的です。