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