Jak zničit externí EEPROM

Zápisník experimentátora

Hierarchy: Externá EEPROM

V předchozím​ článku jsme se zaměřili na data z externí EEPROM. Byla to jen zvědavost. Skutečným důvodem pro získání paměti EEPROM byl test paměti. V dnešním článku podrobíme paměť zničujícímu testu, ve kterém do ni budeme zapisovat, dokud nepřestane plnit svou roli.

Použité součástky

Na tento experiment stačí pouze pár součástek:

  • Arduino Pro Mini (link) - Použil jsem to proto, že se vejde na nejmenší breadboard.
  • Breadboard 400 Holes (link) - Máme na něm dost místa na dva mikrospínače.
  • Převodník CP2102 USB to Serial (link) - Převodník slouží k naprogramování Arduina.
  • EEPROM 24C32WP
  • SOIC8 to DIP8 adaptér (link) - Protože EEPROM je v pouzdře SOIC8, je potřebný adaptér, abychom si ji mohli zapojit na breadboard.
  • OLED displej 0.96 (link) - Během testu se na displeji zobrazí aktuální stav testu. Displej je zapojen podle tohoto​ článku.

Arduino je upraveno tak, že má na I2C (nachází se netradičně na extra pinech uprostřed Arduina) připájenou pin lištu s otvory, aby se pomocí dvou propojovacích vodičů dalo snadno propojit s EEPROM.

EEPROM je připojena k napájení a adresové piny A0, A1 a A2 jsou nezapojené. To se týká pouze tohoto typu EEPROM. Ostatní musí obvykle připojit tyto piny na GND nebo na VCC, čímž si nastaví I2C adresu. Je třeba si vždy zkontrolovat datasheet ke konkrétnímu typu a nastavit to podle něj.

Fyzikální hranice EEPROM

EEPROM paměti jsou navrženy tak, aby se do nich dalo bezpečně zapsat několikrát a výrobce přitom garantuje počet zápisů a čas, během kterého si paměť v sobě uchová uložené informace. Obvykle se jedná o 1 milion Erase/Write cyklů a 40-100 let uchování dat (data retention). Za normálních podmínek je to víc než dostačující. Na to, abyste paměť poškodili, byste museli přepisovat stejné místo alespoň milionkrát. Ale není to tak jednoduché, že milionkrát přepíšete buňku a je po ní. Uvnitř paměti se skrývá množství konkrétně přizpůsobených tranzistorů, které dokáží ve své struktuře uchovávat elektrický náboj a fyzikální podmínky během přepisování způsobují, že materiál tranzistorů postupně degraduje, až se náboj nedokáže v tranzistorech uchovat.

Na uchování údajů působí více faktorů, ale podle výrobců je tím nejdůležitějším parametrem teplota. Se zvyšující se teplotou množství přepisů klesá. V tomto testu se podíváme na možnosti simulování takového postupného ničení a zjistíme, kde je realita.

Program

Jelikož jsem netušil, kolik času bude trvat zničení paměti a jaký přesně bude průběh, navrhl jsem zapojení s OLED displejem. Na displeji se zobrazuje:

  • čas
  • počet cyklů
  • počet zjištěných chyb

Takto je možné jednoduchým zhlédnutím na displej zjistit, co se s pamětí děje. OLED displej je zapojen v konfuguraci, která se mi jevila nejrozumnější pro Arduino Pro Mini a dva minibreadboardy. Zapojení to nebudu popisovat, je to naprosto stejné jako v článku o zapojení OLED displeje.

Popišme si pár proměnných v programu. Na vypisování na displej používám proměnné tbuffer, sbuffer a ebuffer. V zdrojáky je formálně vyznačeno i jak vypadají konkrétní údaje v nich. Proměnné step, errors a steperrors zase sklízejí údaje o konkrétním cyklu a množství zjištěných chyb. Pole data0 a data1 zase obsahují vzorové údaje, které se do EEPROM zapisují.

#include <U8g2lib.h>
#include <extEEPROM.h>

U8G2_SSD1306_128X64_NONAME_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ A3, /* dc=*/ A2, /* reset=*/ A1);
char tbuffer[]="t:xxx:xx:xx.xxx";
char sbuffer[]="s:10000000";
char ebuffer[]="e:10/1000000";
unsigned long step=0;
unsigned long errors=0;
int steperrors;
extEEPROM eep(kbits_32, 1, 16);
unsigned char data0[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char data1[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
unsigned char d[10];
int datpos=0;

Ve funkci setup se inicializuje displej a připojí se EEPROM. Pokud se nelze připojit, program se zastaví v nekonečné smyčce.

void setup() {
  u8g2.begin();
  u8g2.setFont(u8g2_font_ncenB10_tr);
  uint8_t eepStatus = eep.begin(twiClock400kHz);
  if(eepStatus) {
    while (1);
  }
}

Ve funkci loop na střídačku měním údaje v paměti. Přepíši prvních 10 bajtů, aby test skončil v rozumném čase. Každé zvýšení počtu přepisování buněk by totiž výrazně natáhlo výsledný čas.

void loop() {
  //eeprom 1st 10 bytes
  steperrors=0;
  eep.write(0, datpos==0 ? data0 : data1, 10);
  eep.read(0,d,10);
  for(int i=0;i<10;i++) {
    unsigned char *data = datpos==0 ? data0 : data1;
    if(d[i]!=data[i]) {
      steperrors++;
      errors++;
    }
  }
  datpos++;
  datpos%=2;

  // update display
  step++;
  if(step%100==0)
    drawFrame();
}

Poslední funkce vypíše na displej tři řádky. První řádek obsahuje údaj v hodinách, minutách, sekundách a milisekundách. Hodiny mohou mít i více než 24 hodin. Ve funkci stojí za zmínku to, jak je z interních milisekund počítán čas pro konkrétní položku. Používám výpis pomocí funkce sprintf, co je ve světě Arduina prakticky neznámá funkce, ale v ve světě c++ je to naprosto běžná funkce s proměnným počtem parametrů. Výstup se zapisuje do pole znaků a dá se pěkně formátovat pomocí formátovacích znaků.

void drawFrame() {
  unsigned long m=millis();
  sprintf(tbuffer,"T:%02d:%02d:%02d.%03d",
          (int)(m/1000L/3600),
          (int)((m/1000L/60)%60),
          (int)((m/1000L)%60),
          (int)(m%1000L));
  sprintf(sbuffer,"S:%07lu",step);
  sprintf(ebuffer,"E:%02d/%07lu",steperrors,errors);
  u8g2.firstPage();
  do {

  u8g2.drawStr(0, 12, tbuffer);
  u8g2.drawStr(0, 24, sbuffer);
  u8g2.drawStr(0, 36, ebuffer);

  } while ( u8g2.nextPage() );
}

Jak probíhalo testování

Nebudu vás napínat, testování bylo jedna obrovská nuda. Program musel proběhnout asi 20 milionů cyklů, dokud se začaly chyby objevovat. Trvalo to dva dny, během kterých mě už propadali pochybnosti, zda někde v programu nemám chybu. A po dvou dnech se najednou začalo objevovat moře chyb. Na displeji to nebylo vidět, ale když jsem si nechal vypsat obsah EEPROM pomocí programu z předchozího článku, bylo pěkně vidět, že začali selhávat tři buňky z deseti.

Selhávání se projevovalo tak, že pár bitů přestalo být schopno držet informaci. V EEPROM se informace ukládá tak, že hodnota 1 je tranzistor bez náboje a hodnota 0 je tranzistor s nábojem. Čili pokud chcete vidět chybu, musíte zapsat do buňky hodnotu 0. Hodnota 0xFF se zapíše vždy správně, protože to jen vypustí všechen elektrický náboj z tranzistoru. Některé buňky nedokázali držet náboj hned, jiné si ho podrželi několik sekund nebo i hodin. V praxi to vypadalo tak, že hned po zápisu byl obsah buněk takový

0x0000 00 00 00 00 00 01 00 00 00 00

a po několika minutách například takový.

0x0000 00 00 00 00 00 07 01 04 00 00

Kolik vydrží EEPROM

Moje zjištění o výdrži EEPROM se v podstatě shodují s tím, co dělali jiní lidé. Například testy EEPROM přímo v mikrokontroléru ATmega328P vykazují velmi podobné chování. Počty cyklů se lišily od 10 milionů až po mých 20 milionů. Zajímavé je, že paměť se po pár dnech mírně zregenerovala a byla schopna o něco lépe držet údaje. Už to pochopitelně nebylo spolehlivé, ale něco ve struktuře křemíku způsobuje, že přerušení zapisování má blahodárný vliv na výdrž.

Zbytek buněk v EEPROM je stále v pořádku, čili teoreticky bych tuto paměť mohl stále používat.

Zdrojový kód

Zdrojový kód se nachází na serveri GitHub.


01.09.2017


Menu