Kenakan leveling pada EEPROM mikrokontroler

15

Sebagai contoh: Datasheet untuk ATtiny2313 (seperti halnya kebanyakan lembar data Atmel AVR) menyatakan:

128 Bytes Dalam Program Sistem EEPROM Daya Tahan: 100.000 Siklus Tulis / Hapus

Bayangkan sebuah program hanya membutuhkan dua byte untuk menyimpan beberapa konfigurasi, 126 byte lainnya secara efektif terbuang. Yang menarik perhatian saya adalah bahwa pembaruan rutin dari dua byte konfigurasi dapat merusak EEPROM perangkat dan menjadikannya tidak berguna. Seluruh perangkat akan menjadi tidak dapat diandalkan, karena pada saat tertentu Anda tidak dapat melacak byte mana di EEPROM yang tidak dapat diandalkan.

Apakah ada cara cerdas untuk melakukan perataan keausan pada EEPROM mikrokontroler ketika Anda secara efektif menggunakan hanya satu atau dua byte dari 128 yang tersedia?

jippie
sumber
1
Jika 100k siklus tulis merupakan kendala, apakah masuk akal untuk menggunakan beberapa teknologi lain? Apakah suatu mekanisme yang menggabungkan leveling secara internal, atau sesuatu dengan urutan besarnya atau daya tahan yang lebih besar?
Anindo Ghosh
1
@AnindoGhosh Saya hanya tidak ingin menyia-nyiakan stok mikrokontroler kecil saya hanya karena memakai EEPROM yang usang karena pengujian saya sebagai bukti konsep. Saya tidak ingin khawatir tentang byte mana yang telah saya gunakan pada proyek sebelumnya ketika menggunakan kembali controller. Dan rasanya senang mengetahui bahwa saya menggunakan perangkat keras secara optimal.
jippie
3
Ini mungkin membantu: AVR101: High Endurance EEPROM Storage
m.lin
1
Mungkin lihat jawaban saya di stackoverflow .
JimmyB
Lihat seri FRAM MSP430 TI ... 10 ^ 13 menulis !!!
geometrikal

Jawaban:

19

Teknik yang biasanya saya gunakan adalah untuk awalan data dengan nomor urut bergulir 4-byte di mana angka terbesar mewakili nilai terbaru / saat ini. Dalam hal menyimpan 2 byte data aktual yang akan memberikan total 6 byte dan kemudian saya bentuk menjadi pengaturan antrian melingkar sehingga untuk 128 byte EEPROM akan berisi 21 entri dan meningkatkan daya tahan 21 kali.

Kemudian ketika boot nomor urutan terbesar dapat digunakan untuk menentukan nomor urutan berikutnya yang akan digunakan dan ekor saat antrian. Kode pseudo C berikut menunjukkan, ini mengasumsikan bahwa pada pemrograman awal, area EEPROM telah dihapus ke nilai 0xFF jadi saya mengabaikan nomor urut 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;
}

Untuk EEPROM yang lebih kecil, urutan 3-byte akan lebih efisien, meskipun akan membutuhkan sedikit pengirisan daripada menggunakan tipe data standar.

PeterJ
sumber
+1, pendekatan yang bagus. Dapatkah penyimpanan dioptimalkan sedikit dengan menggunakan byte "tag" yang lebih sedikit, dan mungkin tergantung pada beberapa bentuk mekanisme hash bucket untuk menyediakan distribusi tambahan? Hibrida antara tidak naik level, dan pendekatan Anda?
Anindo Ghosh
@AnindoGhosh, ya saya yakin bisa. Saya biasanya menggunakan pendekatan ini pada micros kecil untuk kesederhanaan kode plus secara pribadi telah menggunakannya pada perangkat yang lebih besar seperti DataFLASH. Satu ide sederhana lain yang terlintas dalam pikiran juga adalah bahwa nomor urut dapat diturunkan secara berkala untuk mempertahankannya ke nilai yang lebih kecil.
PeterJ
Catatan aplikasi Atmel yang disebutkan oleh @ m.Alin memiliki penyederhanaan cerdas: Setelah RESET, maka dimungkinkan untuk melihat melalui buffer [...], menemukan elemen buffer [...] terakhir diubah dengan menemukan lokasi di mana perbedaan antara elemen buffer dan elemen buffer berikutnya lebih besar dari 1 .
jippie
Tidakkah seharusnya write_value () menempatkan entri pada queue_tail * sizeof (QUEUE_ENTRY)? saya akan benar pertama kali, tetapi tidakkah seharusnya terus maju jika ada beberapa penulisan saya tidak bertambah di luar load_queue ().
Marshall Eubanks
2
@ DWORD32: Ya, secara teknis itu benar, tetapi dalam praktiknya tidak relevan. Pada saat itu terjadi, batas keausan pada EEPROM akan telah dilampaui oleh faktor 2000!
Dave Tweed
5

Berikut ini adalah metode yang menggunakan bucket dan sekitar satu byte overhead per bucket. Byte ember dan overhead byte mendapatkan jumlah keausan yang sama. Pada contoh yang ada, diberikan 128 byte EEPROM metode ini mengalokasikan 42 bucket 2-byte dan 44 byte status, meningkatkan kemampuan keausan sekitar 42 kali lipat.

Metode:

Bagilah ruang alamat EEPROM menjadi k ember, di mana k = ⌊ E / ( n +1) ⌋, dengan n = ukuran array-data-susunan = ukuran bucket, dan E = ukuran EEPROM (atau, lebih umum, jumlah EEPROM sel yang akan dikhususkan untuk struktur data ini).

Inisialisasi direktori, array m byte semua diatur ke k , dengan m = En · k . Ketika perangkat Anda mulai, itu membaca melalui direktori sampai menemukan entri saat ini, yang merupakan byte tidak sama dengan k . [Jika semua entri direktori sama dengan k , inisialisasi entri direktori pertama menjadi 0, dan lanjutkan dari sana.]

Ketika entri direktori saat ini berisi j , ember j berisi data saat ini. Saat Anda perlu menulis entri data pengaturan baru, Anda menyimpan j +1 ke dalam entri direktori saat ini; jika itu sama dengan k , inisialisasi entri direktori berikutnya menjadi 0, dan lanjutkan dari sana.

Perhatikan bahwa byte direktori mendapatkan jumlah keausan yang sama dengan bucket, karena 2 · k > mk .

(Saya mengadaptasi hal di atas dari jawaban saya untuk pertanyaan Arduino SE 34189 , Bagaimana cara meningkatkan kehidupan EEPROM? )

James Waldby - jwpat7
sumber
2

Saya telah menggunakan nomor urut bergulir untuk ini (mirip dengan jawaban Peter). Nomor urut sebenarnya bisa sesedikit 1 bit, memberikan jumlah elemen dalam isyarat aneh. Kepala dan ekornya kemudian ditandai dengan 2 1 atau 0 berturut-turut

Misalnya jika ingin menelusuri 5 elemen, nomor urutnya adalah:

{01010} (tulis ke 0) {11010} (tulis ke 1) {10010} (tulis ke 2) {10110} (tulis ke 3) {10100} (tulis ke 4) {10101} (tulis ke 5)

Mick Clift
sumber
1

Ada beberapa opsi tergantung pada jenis EEPROM yang Anda miliki dan ukuran data Anda.

  1. Jika EEPROM Anda memiliki halaman yang dapat dihapus secara individual dan Anda menggunakan 1 halaman (atau lebih), cukup simpan semua halaman kecuali yang sedang digunakan, dan gunakan kembali halaman secara melingkar.

  2. Jika Anda hanya menggunakan sebagian kecil dari halaman yang harus dihapus sekaligus, partisi halaman itu menjadi entri data. Gunakan entri bersih setiap kali Anda menulis, dan hapus setelah Anda kehabisan entri bersih.

Gunakan bit "kotor" untuk membedakan antara entri yang bersih dan kotor jika perlu (biasanya, Anda memiliki setidaknya satu byte yang dijamin berbeda dari 0xFF, yang dapat digunakan untuk melacak entri yang kotor).

Jika pustaka EEPROM Anda tidak mengekspos fungsi hapus (seperti Arduino), inilah yang rapi trik yang untuk algoritma # 2: karena entri EEPROM pertama Anda selalu digunakan, Anda dapat menentukan nilai bit "kotor" dengan membacanya. Kemudian setelah Anda kehabisan entri bersih, Anda baru mulai lagi dari entri pertama, membalikkan bit "kotor", dan sisa entri Anda secara otomatis ditandai sebagai "bersih".

Nomor urut dan katalog adalah pemborosan ruang kecuali jika Anda ingin dapat melacak halaman yang buruk atau memperbarui bagian berbeda dari data EEPROM Anda secara mandiri.

Dmitry Grigoryev
sumber