Ako zničiť externú EEPROM

Zápisník experimentátora

Hierarchy: Externá EEPROM

V predchádzajúcom článku sme sa zaoberali čítaním údajov z externej EEPROM. To bolo len zo zvedavosti. Skutočný dôvod získania EEPROM bol test výdrže pamäte. V dnešnom článku pamäť podrobíme zničujúcemu testu, v ktorom budeme do nej zapisovať dovtedy, pokiaľ neprestane plniť svoju úlohu.

Použité súčiastky

Na tento experiment stačí iba pár súčiastok:

  • Arduino Pro Mini (link) - Použil som ho preto, lebo sa zmestí aj na najmenšie skúšobné pole.
  • Breadboard 400 Holes (link) - Na ňom máme dosť miesta na dva mikrospínače.
  • Prevodník CP2102 USB to Serial (link) - Prevodník slúži na naprogramovanie Arduina.
  • EEPROM 24C32WP
  • SOIC8 to DIP8 adaptér (link) - Pretože EEPROM je v púzdre SOIC8, je potrebný adaptér, aby sme si ju mohli zapojiť na breadboard.
  • OLED displej 0.96 (link) - Počas testu sa displeji zobrazuje aktuálny stav testu. Displej je zapojený podľa tohto článku.

Arduino je upravené tak, že má na I2C (nachádza sa netradične na extra pinoch uprostred Arduina) prispájkovanú pin lištu s otvormi, aby sa pomocou dvoch prepojovacích vodičov dalo ľahko prepojiť s EEPROM.

EEPROM je pripojená na napájanie a adresové piny A0, A1 a A2 sú nezapojené. To platí ale iba pre tento konkrétny typ EEPROM. Ostatné musia obvykle pripojiť tieto piny na GND alebo na VCC, čím si nastavia I2C adresu. Treba si vždy skontrolovať datasheet ku konkrétnemu typu a nastaviť to podľa neho.

Fyzikálne hranice EEPROM

EEPROM pamäte sú navrhnuté tak, aby sa do nich dalo bezpečne zapísať niekoľkokrát a výrobca pritom garantuje počet zápisov a čas, počas ktorého si pamäť v sebe uchová uložené informácie. Obvykle sa jedná o 1 milión Erase/Write cyklov a 40-100 rokov uchovania údajov (data retention). Za normálnych podmienok je to viac než dostačujúce. Na to, aby ste pamäť poškodili, by ste museli prepisovať rovnaké miesto aspoň milionkrát. Ale nie je to také jednoduché, že milonkrát prepíšete bunku a je po nej. Vo vnútri pamäte sa skrýva množstvo konkrétne prispôsobených tranzistorov, ktoré dokážu vo svojej štruktúre uchovávať elektrický náboj a fyzikálne podmienky počas prepisovania spôsobujú, že materiál tranzistorov postupne degraduje, až sa náboj nedokáže v tranzistoroch uchovať.

Na uchovanie údajov pôsobí viac faktorov, ale podľa výrobcov je tým najdôležitejším parametrom teplota. So zvyšujúcou sa teplotou množstvo prepisov klesá. V tomto teste sa pozrieme na možnosti simulovania takéhoto postupného ničenia a zistíme, kde je realita.

Program

Keďže som netušil, koľko času bude trvať zničenie pamäte a aký presne bude priebeh, navrhol som zapojenie s OLED displejom. Na displeji sa zobrazuje:

  • čas
  • počet cyklov
  • počet zistených chýb

Takto je možné jednoduchým pozretím na displej zistiť, čo sa s pamäťou deje. OLED displej je zapojený v konfugurácii, ktorá sa mi javila najrozumnejšia pre Arduino Pro Mini a dva minibreadboardy. Zapojenie to nebudem popisovať, je to úplne rovnaké ako v článku o zapojení OLED displeja.

Popíšme si pár premenných v programe. Na vypisovanie na displej používam premenné tbuffer, sbuffer a ebuffer. V zdrojáku je formálne vyznačené aj ako vyzerajú konkrétne údaje v nich. Premenné step, errors a steperrors zase zberajú údaje o konkrétnom cykle a množstve zistených chýb. Polia data0 a data1 zase obsahujú vzorové údaje, ktoré sa 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;

Vo funkcii setup sa inicializuje displej a pripojí sa EEPROM. Ak sa nedá pripojiť, program zastane v nekonečnej slučke.

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

Vo funkcii loop na striedačku prepisujem údaje v pamäti. Prepisujem prvých 10 bajtov, aby test skončil v rozumnom čase. Každé zvýšenie počtu prepisovaných buniek by totiž výrazne natiahlo 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á funkcia vypíše na displej tri riadky. Prvý riadok obsahuje údaj v hodinách, minútach, sekundách a milisekundách. Hodiny môžu mať aj viac ako 24 hodín. Vo funkcii stojí za zmienku to, ako je z interných milisekúnd počítaný čas pre konkrétnu položku. Používam výpis pomocou funkcie sprintf, čo je vo svete Arduina prakticky neznáma funkcia, ale v vo svete c++ je to úplne bežná funkcia s premenlivým počtom parametrov. Výstup sa zapisuje do poľa znakov a dá sa pekne formátovať pomocou formátovacích znakov.

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

Ako prebiehalo testovanie

Nebudem vás napínať, testovanie bolo jedna obrovská nuda. Program musel prebehnúť asi 20 miliónov cyklov, kým sa začali chyby objavovať. Trvalo to dva dni, počas ktorých ma už prepadali pochybnosti, či niekde v programe nemám chybu. A po dvoch dňoch sa odrazu začalo objavovať more chýb. Na displeji to nebolo vidno, ale keď som si nechal vypísať obsah EEPROM pomocou programu z predchádzajúceho článku, bolo pekne vidno, že začali zlyhávať tri bunky z desiatich.

Zlyhávanie sa prejavovalo tak, že pár bitov prestalo byť schopných držať informáciu. V EEPROM sa informácia ukladá tak, že hodnota 1 je tranzistor bez náboja a hodnota 0 je tranzistor s nábojom. Čiže ak chcete videť chybu, musíte zapísať do bunky hodnotu 0. Hodnota 0xff sa zapíše vždy správne, lebo to len vypustí všetok elektrický náboj z tranzistora. Niektoré bunky nedokázali držať náboj hneď, iné si ho podržali pár sekúnd alebo aj hodín. V praxi to vyzeralo tak, že hneď po zápise bol obsah buniek takýto

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

a po pár minútach napríklad takýto.

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

Koľko vydrží EEPROM

Moje zistenia o výdrži EEPROM sa v podstate zhodujú s tým, čo robili iní ľudia. Napríklad testy EEPROM priamo v mikrokontroléri ATmega328P vykazujú veľmi podobné správanie. Počty cyklov sa líšili od 10 miliónov až po mojich 20 miliónov. Zaujímavé je, že pamäť sa po pár dňoch mierne zregenerovala a bola schopná o čosi lepšie držať údaje. Už to pochopiteľne nebolo spoľahlivé, ale niečo v štruktúre kremíka spôsobuje, že prerušenie zapisovania má blahodarný vplyv na výdrž.

Zvyšok buniek v EEPROM je stále v poriadku, čiže teoreticky by som túto pamäť mohol ešte stále používať.

Zdrojový kód

Zdrojový kód sa nachádza na serveri GitHub.


30.04.2017


Menu