EEPROM - wbudowana pamięć
Procesory AVR mają oddzielne przestrzenie adresowe dla różnych typów pamięci. Dostęp do każdej z nich odbywa się za pomocą specyficznych dla niej instrukcji. Podobnie rzecz się ma w przypadku pamięci EEPROM. Co prawda w niektórych mikrokontrolerach z rodziny AVR (np. ATXMega) pamięć ta jest zmapowana do odczytu w obszar pamięci SRAM, jednak w większości przypadków dostęp do niej odbywa się za pomocą specjalnych rejestrów:
EEAR (ang. EEPROM Address Register) — zawiera adres adresowanej komórki pamięci EEPROM.
EEDR (ang. EEPROM Data Register) — zawiera 8-bitową daną do zapisu lub odczytaną z pamięci EEPROM.
EECR (ang. EEPROM Control Register) — rejestr kontrolny, za pomocą którego odbywają się operacje kasowania, zapisu i odczytu pamięci EEPROM.
Pamięć EEPROM nie traci swej zawartości po wyłączeniu mikrokontrolera i w przeciwieństwie do pamięci FLASH, w której zawarty jest program, umożliwia łatwe przeprogramowanie
swej zawartości. Jednak w przeciwieństwie do pamięci SRAM czas potrzebny na zapis nowej wartości do pamięci jest bardzo długi i wynosi ok. 3,3 ms/komórkę. Co gorsze, liczba możliwych cykli zapisu jest ograniczona do ok. 100 tys./komórkę. Po przekroczeniu tej wartości producent nie gwarantuje parametrów dotyczących czasów przechowywania zawartości. Każda operacja kasowania komórki pamięci powoduje stopniowe pogarszanie właściwości izolatora, w efekcie dochodzi do ucieczki ładunku elektrycznego i powolnego kasowania zawartości komórki. Im więcej cykli kasowania wykonano, tym proces ten przebiega szybciej.
Uszkadzanie komórki pamięci EEPROM powodują wyłącznie operacje kasowania. Zapis oraz odczyt nie wywołuje takich efektów i może być wykonany nieskończoną ilość razy.
W niektórych mikrokontrolerach AVR zapis do komórki pamięci EEPROM zawsze wymusza wykonanie operacji kasowania. W nowszych te dwie operacje można przeprowadzić
niezależnie od siebie. Kasowanie zawartości komórki pamięci EEPROM powoduje ustawienie wszystkich bitów, w efekcie taka komórka zawiera wartość 0xFF. Zapis polega więc wyłącznie na zerowaniu niektórych bitów. Tak więc komórki niezaprogramowanej pamięci EEPROM mają wartość 0xFF.
Należy pamiętać, że programowanie pamięci EEPROM odbywa się niezależnie od programowania pamięci FLASH mikrokontrolera.
Jeśli końcowym etapem kompilacji programu są pliki w formacie Intel HEX, programując, musimy wybrać opcję programowania zarówno pamięci FLASH, jak i pamięci EEPROM. Zwykle w takim przypadku otrzymujemy dwa oddzielne pliki — jeden z rozszerzeniem hex, zawierający dane do zaprogramowania pamięci FLASH, drugi z rozszerzeniem
eep, zawierający dane niezbędne do zaprogramowania pamięci EEPROM.
Jeśli do programowania używamy pliku elf (ang. Executable and Linkable Format), to programator powinien sam stwierdzić, czy istnieje w nim sekcja definiująca zawartość
pamięci EEPROM, i ją ewentualnie zaprogramować. Warto jednak przy korzystaniu z nowego oprogramowania upewnić się, w jaki sposób radzi ono sobie z programowaniem
pamięci EEPROM. Mikrokontrolery AVR posiadają także specjalny fusebit EESAVE, określający, czy podczas kasowania pamięci programu ma być także kasowana zawartość pamięci EEPROM. Jeśli bit ten jest niezaprogramowany (ma wartość 1), to podczas kasowania pamięci FLASH w trakcie programowania kasowana jest także zawartość pamięci EEPROM. Jeśli bit ten jest zaprogramowany (ma wartość 0), to zawartość pamięci EEPROM jest zachowywana. Dzięki temu jeśli zawiera ona prawidłowe dane, przy kolejnych programowaniach wystarczy tylko wczytać zawartość pamięci FLASH.
Zapobieganie uszkodzeniu zawartości pamięci EEPROM
Do przypadkowego zapisu komórki pamięci EEPROM może dojść w sytuacji, kiedy procesor lub poszczególne jego bloki nie funkcjonują prawidłowo. Najczęściej z takim stanem mamy do czynienia w momencie, kiedy napięcie zasilające procesor znajduje się poza zakresem dopuszczonym przez producenta układu. Stan taki występuje zawsze w chwili włączenia urządzenia do prądu oraz w chwili jego wyłączenia. Dodatkowo problem z zapisem może pojawić się w sytuacji obniżenia napięcia zasilającego poniżej dolnej granicy w trakcie wykonywania zapisu do pamięci EEPROM. Potencjalnie istnieje jeszcze jedna możliwość uszkodzenia zawartości pamięci — kiedy procesor taktowany jest zegarem o częstotliwości przekraczającej maksymalną częstotliwość pracy układu. Oczywiście, ten ostatni powód jest całkowicie pod kontrolą projektanta urządzenia.
Układ zawsze powinien być tak zaprojektowany, aby w sytuacji kiedy napięcie z różnych przyczyn jest zbyt niskie, procesor był w stanie resetu. Efekt ten możemy uzyskać, stosując zewnętrzne układy nadzorujące napięcie zasilania lub wykorzystując układ nadzorujący zasilanie wbudowany w procesor (BOD — ang. Brown-out Detektor). Ten ostatni możemy uaktywnić, stosując odpowiednie ustawienia tzw. fusebitów. Oprócz aktywowania układu BOD musimy pamiętać także o ustawieniu właściwego napięcia, poniżej którego BOD wywoła reset procesora.
Pamiętaj! Jeśli ustawisz próg zadziałania BOD na napięcie wyższe niż napięcie zasilające procesor, to mikrokontroler będzie utrzymywany w stanie permanentnego resetu.
W tabeli 7.1 pokazano ustawienia fusebitów i progi zadziałania BOD dla mikrokontrolera ATMega88. Jeżeli mikrokontroler pracuje z napięciem zasilającym, dla którego nie da
się wybrać odpowiedniego ustawienia progu zadziałania wewnętrznego układu BOD, jedyną możliwością jest zastosowanie zewnętrznego układu.
Tabela 7.1. Konfiguracja fusebitów i progi zadziałania układu BOD. W tabeli podano minimalne, typowe i maksymalne napięcie zadziałania układu BOD dla mikrokontrolera ATMega88
Fusebity BODLEVEL2:0 Vmin Vtyp Vmax
111 Układ BOD jest nieaktywny
110 1,7 V 1,8 V 2,0 V
101 2,5 V 2,7 V 2,9 V
100 4,1 V 4,3 V 4,5 V
Fusebity BODLEVEL2:0 | Vmin | Vtyp | Vmax |
111 | Układ BOD jest nieaktywny | ||
110 | 1,7 V | 1,8 V | 2,0 V |
101 | 2,5 V | 2,7 V | 2,9 V |
100 | 4,1 V | 4,3 V | 4,5 V |
Włączenie układu BOD właściwie powinno być obowiązkowym etapem tworzenia każdego urządzenia opartego o mikrokontrolery AVR. Co prawda BOD dramatycznie zmniejsza ryzyko uszkodzenia zawartości komórki pamięci EEPROM, jednak go całkowicie nie eliminuje. Stąd też powinniśmy stosować także inne metody. Jedną z zalecanych jest zapisanie do rejestru adresowego EEPROM (EEAR) adresu nieużywanej komórki pamięci EEPROM. Dzięki temu nawet jeśli dojdzie do przypadkowego zapisu do komórki pamięci, to nie spowoduje on uszkodzenia istotnych danych. Stosunkowo bezpieczne jest ustawienie go tak, aby wskazywał na ostatnią komórkę pamięci EEPROM.
Kontrola odczytu i zapisu do pamięci EEPROM
Zarówno odczyt, jak i zapis do pamięci EEPROM są operacjami wieloetapowymi. Ze względu na uniemożliwienie przypadkowych modyfikacji tej pamięci na skutek np. błędnego działania programu operacje te wymagają wykonania kilku etapów w ściśle określonym czasie. Każdy dostęp do pamięci niespełniający wszystkich wymagań jest przez procesor ignorowany.
Odczyt zawartości komórki pamięci
Jest stosunkowo prostą operacją. W pierwszym etapie do rejestru EEAR musimy wpisać adres komórki pamięci, której zawartość chcemy odczytać. W przypadku kontrolerów dysponujących >256 bajtów pamięci EEPROM rejestr ten jest 16-bitowy, lecz kolejność dostępu do jego młodszej i starszej połowy jest bez znaczenia. Po wpisaniu adresu musimy ustawić bit zezwolenia na odczyt (EERE, ang. EEPROM Read Enable) znajdujący się w rejestrze EECR. Powoduje to wstrzymanie wykonywania dalszych instrukcji procesora na 4 cykle zegara, po czym odczytana wartość dostępna jest w rejestrze EEDR. W trakcie zapisu dowolnej komórki pamięci EEPROM niemożliwy jest odczyt danych z tej pamięci. Jeśli taka sytuacja może wystąpić, to przed odczytem musimy upewnić się, że bit EEPE (ang. EEPROM Write Enable) jest wyzerowany.
Zapis do komórki pamięci
Operacja zapisu do pamięci EEPROM jest nieco bardziej skomplikowana. W zależności od procesora przebiega ona zawsze w połączeniu z operacją kasowania zawartości komórki, a w nowszych mikrokontrolerach AVR może przebiegać rozdzielnie. Rozdzielenie operacji kasowania od zapisu ma kilka zalet: czas zapisu ulega dwukrotnemu skróceniu, jeśli nie towarzyszy mu operacja kasowania, jest to także wykorzystywane do zwiększenia liczby możliwych zapisów do pamięci EEPROM. Jak pamiętamy, sam zapis nie powoduje skrócenia żywotności komórki. Oczywiście, operacja kasowania jest niezbędna w sytuacji, w której bit pamięci EEPROM o wartości 0 chcemy przeprogramować na 1. Jak pamiętamy, w trakcie zapisu możliwa jest wyłącznie operacja odwrotna, tj. zmiana bitu o wartości 1 na 0. Zapis, podobnie jak odczyt, przebiega w kilku etapach:
- Pierwszym krokiem jest upewnienie się, że bit EEPE rejestru EECR jest wyzerowany. Wartość 1 świadczy o aktualnie toczącej się operacji zapisu do pamięci, w efekcie niemożliwe jest przeprowadzenie kolejnego zapisu do czasu, aż poprzedni nie ulegnie zakończeniu.
- Na kolejnym etapie do rejestru EEAR wpisujemy adres komórki pamięci, do której chcemy przeprowadzić operację zapisu.
- Następnie do rejestru EEDR wpisujemy 8-bitową liczbę, która ma znaleźć się w pamięci.
- W kolejnym etapie do bitu EEMPE (ang. EEPROM Master Write Enable) rejestru EECR wpisujemy wartość 1.
- W ciągu maksymalnie 4 cykli zegara od zapisania 1 do EEMPE do bitu EEPE (ang. EEPROM Write Enable) rejestru EECR wpisujemy 1. Koniec operacji zapisu sygnalizowany jest wyzerowaniem tego bitu lub wygenerowaniem przerwania EE READY (o ile na nie zezwoliliśmy, ustawiając bit EERIE [ang. EEPROM Ready Interrupt Enable]).
Przerwanie wywołane pomiędzy zapisami do EEMPE i EEPE wydłużyłoby czas operacji ponad wymagane 4 cykle, w efekcie zapis do pamięci EEPROM nie powiódłby się.
Ponieważ od chwili ustawienia bitu EEMPE do chwili ustawienia bitu EEPE nie może minąć więcej niż 4 cykle zegara, to w systemie, w którym mamy odblokowane przerwania, musimy na czas zmiany tych bitów je zablokować.
W niektórych procesorach opisane powyżej bity EEMPE i EEPE nazywają się odpowiednio EEMWE i EEWE.
W niektórych (nowszych) procesorach AVR w rejestrze EECR istnieją dwa opcjonalne bity, których stan precyzuje charakter dokonywanej operacji zapisu. Są to bity EEPM0 i EEPM1 (ang. EEPROM Programming Mode Bits). Typ wykonywanej operacji zapisu w zależności od stanu tych bitów pokazano w tabeli 7.2.
Tabela 7.2. Tryby zapisu do pamięci EEPROM
EEPM1 | EEPM0 | Czas programowania | Operacja |
0 | 0 | 3,4 ms | Kasowanie i zapis w jednej operacji. Domyślna wartość po resecie |
0 | 1 | 1,8 ms | Tylko kasowanie |
1 | 0 | 1,8 ms | Tylko zapis |
1 | 1 | Kombinacja zarezerwowana |
Jeśli nie zmienimy zawartości tych bitów, to zapis do pamięci będzie się odbywał tak jak w starszych modelach mikrokontrolerów AVR, tj. nastąpi jednoczesne kasowanie i zapis. W przypadku kiedy przeprowadzamy tylko operację kasowania, zawartość rejestru EEDR jest bez znaczenia, stąd też w tym trybie możemy pominąć zapis do tego rejestru.