Zwiększanie żywotności i eliminowanie błędów danych w pamięciach Flash

| Technika

Nieulotne pamięci Flash to popularne nośniki danych używane w dyskach SSD, kartach pamięci, pamięciach USB oraz urządzeniach wbudowanych. Zbudowane są z komórek, z których każda składa się z dwóch bramek: pływającej oraz sterującej. W tej pierwszej gromadzony jest ładunek. Bramka sterująca odczytuje go jako wartość logiczną 0 lub 1, może również kasować oraz zapisywać zawartość bramki pływającej.

Zwiększanie żywotności i eliminowanie błędów danych w pamięciach Flash

Ze względu na typ bramki logicznej wyróżnia się dwa rodzaje pamięci Flash: NOR oraz NAND. Zapis oraz odczyt danych w tych drugich jest szybszy. Dlatego pamięci typu NOR są używane głównie do przechowywania informacji rzadko aktualizowanych, często jako odpowiednik pamięci ROM. Dostęp do pamięci NAND jest sekwencyjny, natomiast do pamięci NOR - swobodny. Z kolei pamięci NAND mają o około 60% mniejsze komórki niż pamięci NOR. Dzięki temu charakteryzuje je większa gęstość upakowania danych, są zatem tańsze.

Pamięci NAND również dzieli się na dwie grupy: SLC (single-level cell) oraz MLC (multi-level cell). W pojedynczej komórce pamięci SLC można zapisać jednocześnie tylko jeden bit informacji. W komórce pamięci MLC mieszczą się natomiast dwa bity danych, a nawet większa ich liczba. Dzięki temu te ostatnie są tańsze niż pamięci SLC, ale niestety również wolniejsze i mniej niezawodne. Dlatego używa się ich głównie w elektronice użytkowej. Z pamięci SLC częściej korzysta się natomiast w zastosowaniach specjalistycznych.

Podstawowe jednostki organizacyjne w strukturze pamięci Flash to bloki oraz strony (rys. 1). Te pierwsze są podstawową jednostką w operacji kasowania danych, a strony - w procesie ich zapisu. Wszystkie bloki składają się z takiej samej oraz stałej liczby stron. W tych ostatnich można z kolei wyróżnić dwa obszary. W pierwszym przechowywane są dane bieżące. W drugiej części (spare area), która jest niewidoczna dla użytkowników, system zarządzający zasobami pamięci zapisuje informacje pomocnicze. Pojemność tego obszaru jest odpowiednio mniejsza w stosunku do pojemności całej strony. Przykładowo w wypadku stron o pojemności 512 bajtów oraz 2048 bajów spare area zajmuje zwykle zaledwie odpowiednio 16 bajtów oraz 64 bajty.

Wear leveling

Rys. 1. Bloki i strony to podstawowe jednostki organizacyjne pamięci Flash

Zapis nowych danych polega na zmianie układu bitów w pamięci. W tym celu zawartość jej komórek najpierw jest kasowana, a następnie zapisuje się w nich nowe wartości logiczne. Każda taka operacja wpływa na fizyczne właściwości komórek pamięci, powodując ich stopniowe zużywanie się. Dlatego liczba cykli zapisu oraz kasowania pamięci jest ograniczona. Typowo żywotność pamięci typu NAND SLC wynosi 100 tys. cykli zapisu/kasowania, a pamięci typu NAND MLC - 10 tys. takich cykli. Po przekroczeniu tych wartości pewny oraz bezbłędny zapis oraz odczyt danych nie jest już gwarantowany.

Aby wydłużyć żywotność pamięci, wdraża się mechanizm optymalizacji jej zużycia (wear leveling). Polega on na śledzeniu częstości korzystania z poszczególnych bloków pamięci oraz równomiernym rozmieszczaniu w nich danych w taki sposób, aby żaden z bloków nie był czyszczony oraz zapisywany częściej niż pozostałe. W rezultacie wszystkie bloki pamięci są już chociaż raz zapisane, zanim operacja ta zostanie powtórzona. Maksymalna możliwa liczba komórek pamięci jest dzięki temu zużyta minimalnie.

Zapewnia to żywotność najdłuższą z możliwych. Wyjaśniamy to na przykładzie pamięci Flash o żywotności 10 tys. cykli, która składa się z 4096 bloków. Zapisane są w niej trzy pliki, z których każdy zajmuje 50 bloków pamięci. Co 10 minut dane zapisane w jednym pliku są aktualizowane. W ciągu godziny zawartość pamięci jest zatem zmieniana sześciokrotnie. Zakładając, że dane będą stale wprowadzane do tych samych 200 bloków pamięci, nośnik będzie się nadawał do użytku krócej niż rok ((10000 · 200) / (50 · 6 · 24) = 278). Gdyby do zapisu tej samej ilości informacji z taką samą częstością wykorzystać wszystkie bloki, z pamięci można by natomiast korzystać ponad 15 lat ((10000 · 4096) / (50 · 6 · 24) = 5689).

Dynamicznie czy statycznie?

Wear leveling można zrealizować dynamicznie lub statycznie. Pierwsza metoda polega na optymalizacji zapisu wyłącznie danych dynamicznych, czyli takich, które są często aktualizowane. Zapisuje się je do tych bloków, które do tej pory były używane najrzadziej. Przyjmijmy, że w przykładzie przedstawionym wcześniej 25% pamięci zajmują dane dynamiczne, a 75% dane statyczne, czyli zmieniane bardzo rzadko. Wdrażając wear leveling dynamiczny, żywotność tego nośnika można wydłużyć z mniej niż roku do prawie 4 lat ((10000 · 1024) / (50 · 6 · 24) = 1422). Ponieważ wear leveling dynamiczny jest dość prosty w realizacji, korzysta się z niego w urządzeniach tańszych, o z założenia stosunkowo krótkim czasie użytkowania. Przykładem są pamięci USB.

Druga metoda polega na zarządzaniu zapisywaniem zarówno danych dynamicznych, jak i statycznych. Monitorowany jest wówczas stopień zużycia wszystkich bloków pamięci. Jeżeli te, z których dotychczas korzystano najrzadziej, są aktualnie puste, zapisuje się do nich nowe dane. Jeżeli jednak znajdują się już w nich dane statyczne, te ostatnie przenosi się do bloków bardziej zużytych. Wadą tej techniki jest większy stopień złożoności, a przez to większe obciążenie kontrolera oraz wolniejszy zapis. W zamian uzyskuje się maksymalną możliwą żywotność nośnika, która w podawanym wcześniej przykładzie wyniesie 15 lat. Wear leveling dynamiczny jest stosowany w droższych nośnikach danych, m.in. w dyskach SSD.

Żywotność nośnika danych można również wydłużyć, stosując shadowing. Metoda ta polega na skopiowaniu zawartości części lub całości pamięci Flash do pamięci SDRAM lub SRAM. System operacyjny korzysta wówczas bezpośrednio z informacji z tego ostatniego nośnika. Po zakończeniu operacji lub okresowo zawartość pamięci Flash jest aktualizowana.

Bad blocks

Tabela 1. Wear leveling dynamiczny vs. statyczny

Niektóre bloki pamięci już w czasie produkcji mogą ulec uszkodzeniu. Wykrywa się je w czasie testów, które polegają na przykład na wykonaniu kilku cykli kasowania/zapisu danych w różnych warunkach środowiskowych. Następnie takie obszary pamięci (bad blocks) specjalnie się znakuje. W tym celu w spare area pierwszych stron zepsutego bloku umieszcza się odpowiednią informację.

Kolejne bloki mogą ulec uszkodzeniu również w trakcie użytkowania pamięci z różnych przyczyn. Przykładowo mimo stosowania mechanizmu wear leveling pewna nierównomierność rozmieszczenia danych jest bowiem nieunikniona. Niektóre bloki zużyją się zatem wcześniej niż pozostałe. Jeżeli liczba bad blocks przekroczy określoną przez producenta wartość, zwykle kilka %, całą pamięć uznaje się za zepsutą.

Uszkodzone bloki nie wpływają na funkcjonowanie pozostałych, ponieważ jednostki te w pamięci Flash są od siebie izolowane. Ważne jest jednak, aby system zarządzania zasobami pamięci zidentyfikował te jej obszary, z których nie może korzystać jeszcze przed podjęciem jakiejkolwiek próby zapisu danych. W przeciwnym wypadku informacje w spare area zostałyby skasowane. Wdrożyć trzeba zatem system zarządzania uszkodzonymi blokami (bad block management, BBM).

BBM

Realizuje on algorytm przedstawiony na rysunki 2. Efektem jego działania jest tablica (bad block table, BBT), w której zebrane są adresy uszkodzonych bloków. Zapisuje się ją w sprawnych obszarach pamięci, dzięki czemu nie trzeba za każdym razem na nowo skanować wszystkich bloków w poszukiwaniu tych zepsutych. BBT jest też stale aktualizowana.

Jeżeli w trakcie operacji zapisu danej strony wystąpi błąd, nie ma to wpływu na zawartość pozostałych stron w bloku. Informacje te można zatem przekopiować do sprawnego obszaru pamięci. Dane, które miały zostać zapisane w uszkodzonym bloku, należy natomiast przekierować. BBM może to zrealizować na różne sposoby. Przykładowa metoda (skipping bad blocks) polega na przekopiowaniu lub przekierowaniu informacji do pierwszego sprawnego bloku o adresie następującym po adresie tego uszkodzonego.

Stosowany jest również podział całej pamięci Flash na dwa obszary. Do pierwszego z nich mogą się bezpośrednio odwoływać użytkownicy (user addressable block area), natomiast drugi jest zarezerwowany (reserved block area). Można do niego zapisywać wyłącznie dane z uszkodzonych bloków oraz samą tablicę BBT. To, ile bloków pamięci zostanie zarezerwowanych, zależy od tego, uszkodzenie ilu bloków dopuszcza producent. Jeżeli na przykład jest to 2% wszystkich, tyle samo bloków trzeba wyłączyć z normalnego użytkowania.

ECC

Rys. 2. Algorytm tworzenia tablicy z adresami uszkodzonych bloków pamięci

Przyczyny błędów danych w pamięci Flash mogą być różne. Ich przykłady to: zbyt duże napięcie przyłożone do bramki komórki pamięci (over programming), zakłócenie lub przerwanie procesu programowania, wyciek ładunku, jego przepływ między sąsiadującymi komórkami lub zjawisko charge trap, które zachodzi w czasie operacji kasowania oraz programowania pamięci. Błędów spowodowanych tym ostatnim nie można już naprawić. Pozostałe można natomiast skorygować w kolejnym cyklu kasowania/zapisu.

Aby zwiększyć integralność danych w pamięci, stosuje się kodowanie korekcyjne ECC (error correction code). Jest ono koniecznością zwłaszcza w przypadku pamięci NAND, a szczególnie MLC, w których częściej występują wycieki ładunków. Pamięci NOR natomiast zwykle nie wymagają takiej ingerencji. Dzięki ECC błędy danych są wykrywane i naprawiane. W celu sprawdzenia, czy dane zostały zapisane poprawnie, uzupełnia się je o nadmiarowe informacje. Po ich rozkodowaniu wiadomo, które bity danych są przekłamane.

ECC można zaimplementować programowo lub sprzętowo. W pierwszym przypadku specjalne oprogramowanie przetwarza dane, uzupełniając je o informacje nadmiarowe przed ich zapisaniem do pamięci. Wymaga to większej mocy obliczeniowej, ale z kolei nie są potrzebne dodatkowe układy elektroniczne.

Kody korekcyjne

Algorytmy korekcyjne dzieli się na dwie grupy: blokowe oraz splotowe. W obu k-bitowy ciąg wejściowy zostaje zakodowany w n-bitowy ciąg wyjściowy. Ten ostatni w wypadku kodowania splotowego jest zależny od wcześniej zakodowanych słów kodowych. W kodowaniu blokowym słowa kodowe nie są ze sobą powiązane. W pamięciach Flash najczęściej wykorzystywane są kody blokowe, zwłaszcza kody: Hamminga, Reeda-Solomona oraz BCH.

Algorytm Hamminga jest najprostszy, a dzięki temu najłatwiejszy do zaimplementowania, zarówno sprzętowo, jak i programowo. Niestety jego możliwości w zakresie detekcji oraz korekcji błędów danych są ograniczone - jest on w stanie wykryć jedynie dwa błędne bity, a naprawić tylko jeden. Dlatego jest stosowany głównie w pamięciach NAND SLC. Rodzaj kodu Hamminga opisuje zależność: (2n-1, 2n-n-1), gdzie n - liczba bitów nadmiarowych, 2n-1 - rozmiar słowa kodowego, 2n-n-1 - liczba bitów informacyjnych. Najpopularniejsze z nich to (7, 4), w którym na 7-bitowe słowo kodowe składają się: 4 bity danych oraz 3 bity korekcyjne, (15, 11) oraz (31, 26).

Większa gęstość upakowania danych w pamięciach Flash MLC wymusza stosowanie w nich bardziej złożonych algorytmów ECC. Jest to zwykle jeden z dwóch algorytmów: Reeda-Solomona lub BCH. Oba są skuteczniejsze niż kodowanie Hamminga, ponieważ wykrywają oraz naprawiają wiele błędów jednocześnie. Liczba tych ostatnich zależy od długości słowa kodowego i liczby bitów parzystości. Kodowanie Reeda-Solomona (używane też m.in. w CDROM- ach) wymaga jednak większej mocy obliczeniowej oraz pamięci, niż BCH, które jest prostsze. Kodowanie BCH umożliwia ponadto wykrycie oraz naprawę zarówno błędów rozproszonych w obrębie pamięci Flash, które nie są ze sobą skorelowane, jak i tych skupionych w jednym obszarze. Algorytm Reeda-Solomona sprawdza się z kolei najlepiej w detekcji oraz korekcji tych ostatnich.

Monika Jaworowska

Zobacz również