====== EEPROM ======
//Vajalikud teadmised: [HW] [[et:hardware:homelab:controller]] //
===== Teooria =====
[{{ :et:examples:storage:eeprom2.png?250|Atmeli EEPROM mälukiip}}]
EEPROM (inglise keeles //Electrically Eraseable Programmable Read Only Memory//) on elektriliselt kustutatav mäluseade, mida kasutatakse tavaliselt mingi väiksema hulga andmete salvestamiseks. EEPROM-i eeliseks on andmete säilimine ka pärast kontrolleri toite kadumist. Seetõttu kasutatakse seda tavaliselt erinevate, programmis muudetavate seadete säilitamiseks. Muus osas käitub EEPROM mälu sarnaselt muude mäludega, kus mälubittidest on moodustatud 8-bitised baidid.
EEPROMi mälupesa kasutades on oluline meelde jätta ka see, et mälubaitide eluiga on ca 10 0000 kirjutustsüklit. Seega tuleks jälgida, et EEPROM mällu kirjutatakse vaid minimaalselt oluline andmehulk.
===== Praktika =====
AVR mikrokontrollerisse on sisse ehitatud teatud osa EEPROM mälu. Kodulabori III põlvkonna kontrolleris ATxmega128A1U on EEPROM mälumaht 2 KB. EEPROM-iga suhtlemiseks on soovitatav kasutada teeki, mis on AVR GCC-sse juba sisse ehitatud. Teegis on ära defineeritud põhilised funktsioonid EEPROM mälupesaga suhtlemiseks:
* uint8_t eeprom_read_byte (const uint8_t *addr)
* uint16_t eeprom_read_word (const uint16_t *addr)
* void eeprom_read_block (void *pointer_ram, const void *pointer_eeprom, size_t n)
* void eeprom_write_byte (uint8_t *addr, uint8_t value)
* void eeprom_write_word (uint16_t *addr, uint16_t value)
* void eeprom_write_block (const void *pointer_eeprom, void *pointer_ram, size_t n)
* void eeprom_update_byte (uint8_t *addr, uint8_t value)
* void eeprom_update_word (uint16_t *addr, uint16_t value)
* void eeprom_update_block (const void *pointer_ram, void *pointer_eeprom, size_t n)
Lihtne näitekood EEPROM-i andmete salvestamiseks. Loetakse bait aadressilt 46 ning sõna aadressilt 50. Kirjutamiseks kasutatakse //update// funktsiooni, mis enne kirjutamist loeb EEPROM mälupesa sisu ja korrektse väärtuse olemasolul seda üle ei kirjuta. Nii säästetakse mäluelemente hävimise eest, kuid kirjutamine võtab natuke rohkem aega.
// AVR-i EEPROM mällu baidi ja sõna salvestamise ja sealt lugemise näidisprogramm
#include
// Põhiprogramm
int main(void) {
uint8_t andmeBait;
uint8_t andmeSona;
// EEPROM-i aadressile 46 numbri 86 kirjutamine
eeprom_update_byte((uint8_t*)46, 86);
// EEPROM-i aadressile 50 numbri 860 kirjutamine
eeprom_update_word((uint16_t*)50, 860);
// EEPROM-i aadressilt 46 baidi lugemine (peaks olema 86)
andmeBait = eeprom_read_byte((uint8_t*)46);
// EEPROM-i aadressilt 50 sõna lugemine (peaks olema 860)
andmeSona = eeprom_read_word((uint16_t*)50);
}
Selleks, et liigutada korraga rohkem andmeid, tuleks kasutada bloki lugemist/kirjutamist. Selleks tuleb eelnevalt defineerida andmeblokk muutujamälus:
// AVR-i EEPROM mällu andmebloki salvestamise ja sealt lugemise näidisprogramm
#include
// Põhiprogramm
int main(void) {
uint8_t andmeJada1[10] = "TestLause.";
uint8_t andmeJada2[10];
// Esimene parameeter on pointer EEPROM mälu andmeblokile,
// teine parameeter on pointer muutujamälu andmeblokile
// kolmas parameeter on andmeJada pikkus
eeprom_update_block((const void*)&andmeJada1, (void*)12, 10);
// Esimene parameeter on pointer muutujamälu andmeblokile,
// teine parameeter on pointer EEPROM-i mälu andmeblokile
// kolmas parameeter on andmeJada pikkus
eeprom_read_block((void*)&andmeJada2, (const void*)12, 10);
}
Alati ei ole aga otstarbekas pidada meeles täpseid EEPROM-i mäluaadresse. Selleks on defineeritud selline muutuja atribuut nagu EEMEM. Selle kasutamine vabastab kasutajat aadresside haldamisest ning laseb seda teha kompilaatoril. Meeles tuleb aga pidada, et andmeid tuleb EEPROM-is liigutada siiski teegikäskudega.
// AVR-i EEPROM EEMEM kasutamise näidisprogramm
#include
uint8_t EEMEM NonVolatileChar;
uint16_t EEMEM NonVolatileInt;
uint8_t EEMEM NonVolatileString[10];
// Põhiprogramm
int main(void) {
uint8_t SRAMchar;
uint16_t SRAMint;
uint8_t SRAMstring[10];
SRAMchar = eeprom_read_byte(&NonVolatileChar);
SRAMint = eeprom_read_word(&NonVolatileInt);
eeprom_read_block((void*)&SRAMstring, (const void*)&NonVolatileString, 10);
}