Mikrodenetleyicinin EEPROM'unda aşınma seviyelendirme


15

Örneğin: ATtiny2313 için veri sayfası (çoğu Atmel AVR veri sayfası gibi) şunları belirtir:

128 Bayt Sistem İçi Programlanabilir EEPROM Dayanıklılığı: 100.000 Yazma / Silme Döngüsü

Bir programın bazı yapılandırmaları saklamak için sadece iki bayt gerektirdiğini, diğer 126 baytın etkili bir şekilde boşa harcandığını düşünün. Beni ilgilendiren şey, iki yapılandırma baytının düzenli olarak güncellenmesinin cihazın EEPROM'unu yıpratması ve işe yaramaz hale getirmesidir. Tüm cihaz güvenilir olmayacaktır, çünkü belirli bir anda EEPROM'daki hangi baytların güvenilir olmadığını takip edemezsiniz.

Mevcut 128'den yalnızca bir veya iki bayt etkin bir şekilde kullandığınızda mikrodenetleyicinin EEPROM'unda aşınma dengelemesi yapmanın akıllı bir yolu var mı?


1
100 bin yazma çevrimi bir kısıtlama olsaydı, bunun yerine başka bir teknoloji kullanmak mantıklı olurdu? Ya dahili olarak düzleştirmeyi içeren bir mekanizma mı, yoksa daha büyük veya daha fazla dayanıklılığa sahip bir şey mi?
Anindo Ghosh

1
@AnindoGhosh Sadece kavram kanıtını test ettiğim için EEPROM'u giydiğim için küçük mikrodenetleyiciler stokumu boşa harcamak istemiyorum. Denetleyiciyi yeniden kullanırken önceki bir projede hangi baytı kullandığım konusunda endişelenmek istemiyorum. Ve mevcut donanımı en iyi şekilde kullandığımı bilmek iyi hissettiriyor.
jippie


1
Belki stackoverflow'daki cevabıma bir göz atın .
JimmyB

TI'nın MSP430 FRAM serisine bir göz atın ... 10 ^ 13 yazıyor !!!
geometrikal

Yanıtlar:


19

Normalde kullandığım teknik, verilerin en büyük sayının en son / geçerli değeri temsil ettiği 4 baytlık yuvarlanma sekansı numarasına önek eklemektir. Toplam 6 bayt verecek 2 bayt gerçek verinin saklanması ve daha sonra dairesel bir kuyruk düzenlemesi oluşturmam durumunda 128 bayt EEPROM için 21 giriş içerecek ve dayanıklılığı 21 kat artıracaktır.

Daha sonra önyükleme yapılırken hem kullanılacak sonraki sıra numarasını hem de sıranın geçerli kuyruğunu belirlemek için en büyük sıra numarası kullanılabilir. Aşağıdaki C sözde kodu gösterir, bu ilk programlama üzerine EEPROM alanı 0xFF değerlerine silindiğini varsayar, bu nedenle 0xFFFF sıra numarasını yok sayıyorum:

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;
}

Daha küçük bir EEPROM için, 3 baytlık bir sekans daha verimli olacaktır, ancak standart veri türlerini kullanmak yerine biraz bit dilimleme gerektirecektir.


+1, Güzel yaklaşım. Depolama daha az "etiket" bayt kullanılarak ve muhtemelen ek dağıtım sağlamak için bir çeşit karma kova mekanizmasına bağlı olarak biraz optimize edilebilir mi? Seviyelendirme ile yaklaşımınız arasındaki bir melez mi?
Anindo Ghosh

@AnindoGhosh, evet yapabileceğine inanıyorum. Normalde bu yaklaşımı kod sadeliği için küçük mikronlarda kullandım ve kişisel olarak daha çok DataFLASH gibi daha büyük cihazlarda kullandım. Akla gelen bir başka basit fikir de, sıra numaralarının daha küçük değerlere tutmak için periyodik olarak düşürülebilmesidir.
PeterJ

@ M.Alin tarafından belirtilen Atmel uygulama notunun akıllı bir sadeleştirmesi vardır: Bir RESET'ten sonra, [...] arabelleğine bakmak, son [...] tampon elemanını bulmak mümkündür . bir tampon elemanı ile bir sonraki tampon elemanı arasındaki fark 1'den büyüktür .
jippie

Write_value (), girdiyi queue_tail * sizeof (QUEUE_ENTRY) alanına koymamalı mı? ben ilk kez doğru olacak, ama birden fazla yazma varsa ilerlemeye devam etmemeli? i load_queue () dışında artırılmaz.
Marshall Eubanks

2
@ DWORD32: Evet, bu teknik olarak doğru, ancak pratikte ilgisiz. Bu zamana kadar, EEPROM üzerindeki aşınma limiti 2000 kat aşılmış olacak!
Dave Tweed

5

Aşağıda kovalar ve kova başına yaklaşık bir havai bayt kullanan bir yöntem verilmiştir. Kova baytları ve havai baytlar yaklaşık aynı miktarda aşınma elde eder. Eldeki örnekte, 128 EEPROM bayt verildiğinde bu yöntem 42 2 baytlık kova ve 44 durum baytı tahsis ederek yaklaşık 42 kat aşınma kapasitesini arttırır.

Yöntem:

EEPROM adres alanını k = ⌊ E / ( n +1) ⌋ olan k kovalarına bölün, n = setup-data-array boyutu = grup boyutu ve E ile = EEPROM boyutu (veya daha genel olarak EEPROM sayısı ile) bu veri yapısına ayrılacak hücreler).

M = En · k ile k olarak ayarlanmış bir m bayt dizisi başlatın . Cihazınız başlatıldığında, k girişine eşit olmayan bir bayt olan geçerli girişi bulana kadar dizinde okur . [Tüm dizin girişleri k'ye eşitse , ilk dizin girişini 0 olarak başlatın ve oradan devam edin.]

Geçerli dizin girdisi içerdiğinde j , kova j güncel verileri içeriyor. Yeni bir kurulum veri girişi yazmanız gerektiğinde , geçerli dizin girişine j +1 depolarsınız ; bu k'ye eşit olursa , sonraki dizin girişini 0 olarak başlatın ve oradan devam edin.

Dizin baytlarının, 2 · k > mk olduğu için kova baytlarıyla yaklaşık aynı miktarda aşınma elde ettiğine dikkat edin .

(Ben yukarıda uyarlanan Arduino SE sorusuna 34189 cevabım , EEPROM ömrünü artırmak için nasıl? .)


2

Bunun için bir haddeleme sırası numarası kullandım (Peter'ın cevabına benzer). Sıra numarası, işaretteki elemanların sayısının tek olması koşuluyla 1 bit kadar az olabilir. Baş ve kuyruk daha sonra 2 ardışık 1 veya 0 ile işaretlenir

Örneğin, 5 öğeden geçmek istiyorsanız sıra numaraları şu şekilde olur:

{01010} (0'a yaz) {11010} (1'e yaz) {10010} (2'ye yaz) {10110} (3'e yaz) {10100} (4'e yaz) {10101} (5'e yaz)


1

Sahip olduğunuz EEPROM türüne ve verilerinizin boyutuna bağlı olarak birkaç seçenek vardır.

  1. EEPROM'unuzda ayrı ayrı silinebilir sayfalar varsa ve 1 sayfa (veya daha fazla) kullanıyorsanız, kullanımda olanlar dışındaki tüm sayfaları silin ve dairesel bir şekilde yeniden kullanın.

  2. Bir kerede silinmesi gereken bir sayfanın yalnızca bir kısmını kullanıyorsanız, bu sayfayı veri girişlerine bölün. Her yazarken temiz bir giriş kullanın ve temiz girişler bittiğinde silin.

Gerekirse temiz ve kirli girişler arasında söylemek için "kirli" bir bit kullanın (genellikle, kirli girişleri izlemek için kullanılabilen, 0xFF'den farklı olduğu garanti edilen en az bir baytınız vardır).

EEPROM kitaplığınız silme işlevini (Arduino gibi) göstermezse, algoritma # 2 için temiz bir numara : ilk EEPROM girişiniz her zaman kullanıldığından, "kirli" bitin değerini okuyarak belirleyebilirsiniz. Daha sonra temiz girdileriniz bittiğinde, ilk girişten yeniden başlayıp "kirli" biti tersine çevirirsiniz ve girişlerin geri kalanı otomatik olarak "temiz" olarak işaretlenir.

Sıralı numaralar ve kataloglar, kötü sayfaları izlemek veya EEPROM verilerinizin farklı bölümlerini bağımsız olarak güncellemek istemediğiniz sürece alan kaybıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.