MPLAB - prace s EEPROM

Vláďa Anděl vaelektronik na vaelektronik.cz
Čtvrtek Leden 6 13:47:39 CET 2022


Např. já u silabsu (8051) "EEPROM " pro data běžně používám. Zapisuje se 
do volné stránky v code. Takže snad jen inspirace, jak to může jít 
jednoduše, když to MCU a překladač umí. Pro data se vyhradí stránka v 
code a protoře do code z principu zapisovat nelze, zapisuje se tam jako 
do xdata a čte se to z code.

#define AdrEEPROM 0x1800   /* konstanty regulace od 1800 do 19FF
unsigned char data *data Adrzap;     // Zapis do EEPROM

Samotný zápis/mazání

unsigned char xdata *Pwrite;         // FLASH write pointer
EA_save=EA; EA=0;                // Disable interrupts
VDDMON=0xA0;                         // Enable VDD monitor and high 
threshold
if(Cal) Pwrite=AdrCalKonst+(unsigned int)(Adrzap);  // kalibracni 
konstanty jsou v jine strance
else Pwrite=AdrEEPROM+(unsigned int)(Adrzap); //adresa zapisu jako kopie 
RAM od AdrEEPROM
// cekani na ustaleni monitoru VDD
RSTSRC=0x02;                         // Enable VDD monitor as a reset 
source

do
   {
     FLKEY=0xA5;                         // Key Sequence 1
     FLKEY=0xF1;                         // Key Sequence 2
     if(Pocet)    PSCTL=1;         // PSWE = 1 which enables writes
   else
         {
         Pocet=1;                        // aby se cykl po prvnim 
pruchodu ukoncil
         PSCTL=3;                        // PSWE = 3 mazani stranky
     }
     *Pwrite=(*Adrzap);
     PSCTL=0;                             // PSWE = 0 which disable writes
     Pwrite++;
     Adrzap++;
   Pocet--;
     }
while(Pocet);
EA=EA_save;

U silabsu je trochu opruz s tím, že před každým zapsaným bajtem do code 
se musí dávat dva odemykací bajty, prý aby se zabránilo náhodnému 
přepsání code při zbloudění programu. A taky že se musí nastavit VDD 
monitor jako zdroj resetu.

Anděl

Dne 06.01.2022 v 11:25 Jan Waclawek napsal(a):
>> Tak jak jsem to resil driv treba v uPascalu bylo, ze jsem mel
>> nadefinovanou jednu strukturu jako promennou v RAM a z EEPROM jsem si od
>> nejake pevne dane adresy nacital nejaky blok dat a pro dalsi sadu jsem
>> si jen pocatecni adresu zvysil o offset dany velikosti te struktury v
>> eeprom.
> Presne toto iste mozes robit aj v tom C. Tu by sme mohli skoncit, ale...
>
>> Pochopil jsem, ze kdyz chci umistit promennou do EEPROM pouziji klicove
>> slovo EEMEM. Nicmene nejak nechapu jaky to ma smysl.
> To nie je klucove slovo jazyka C, ale nejake jeho rozsirenie v konkretnej
> implementacii, ktoru pouzivas. Neviem ktory prekladac pouzivas, ale v jeho
> navode by mohol/mal byt nejaky naznak toho, co to rozsirenie presne
> znamena.
>
> Jazyk C - ako napokon vsetky existujuce vyssie programovacie jazyky -
> nepredpoklada, ze by mohli existovat nejake ine formy pamati, nez jedna
> uniformna suvisla RAM. Tak to napokon skutocne je u PDP-11, na ktorom
> jazyk C vznikol, a tak je to aj na uplne vsetkych "velkych" pocitacoch
> dodnes.
>
> Jazyk ma zabudovany nejaky mechanizmus na to, aby pri definicii premennej
> nejako tie premenne do tej pamate naukladal, a ked sa ta premenna pouzije,
> tak vygeneruje instrukcie na citanie a zapis do tej pamate.
>
> Lenze mikrokontrolery nie su obycajne pocitace a maju rozne druhy pamati -
> RAM, ROM, FLASH, EEPROM, externe pripojene pamati - ktore su mapovane v
> roznych pamatovych priestoroch a pristupuje sa k nim roznymi instrukciami
> ci sustavami instrukcii. Niektore mcu (typicky 32-bitove) maju tendenciu
> napchat vsetky interne pamate na uniformnu internu zbernicu, t.j. pamate
> su v jednom adresnom priestore a obvykle sa daju aspon citat rovnakymi
> instrukciami (dokonca niekde aj zapisovat, akurat ze ten zapis dlho trva a
> pred nim treba urobit nejake odomknutie atd.). Este aj v tom pripade vsak
> obvykle zostava problem vo forme nesuvisleho adresneho priestoru.
>
> Mimochodom, situacia sa u mcu komplikuje este aj tym, ze aj do tej istej
> pamate sa da pristupovat roznymi sposobmi; co toto presne znamena, doverne
> poznaju pouzivatelia '51, ale aj trebars derivatov 6800 a vacsich
> 8-bitovych PICiek - tam vsade existuje relativne velka RAM, do ktorej sa
> pristupuje pomerne pomalou metodou (napr. nepriamo), a pritom do casti tej
> istej RAM sa da pristupovat aj rychlou metodou (priamo). Uzivatel moze
> chciet. Dalsou, trocha podobnou komplikaciou su strankovane pamate. V
> konecnom dosledku je teda lepsie nehovorit o adresnom priestore ale o
> pamatovych triedach, pretoze k nejakej konkretnej adrese sa da pristupovat
> roznymi sposobmi a uzivatel moze chciet ovplyvnit, ze ktory sposob sa
> pouzije (napr. chce mat explicitnu metodu, ktorou ovplyvni alokovanie
> nejakej premennej napriklad do "rychlejsie pristupovanej" pamati, a potom
> moze chciet mat aj metodu, ktorou prekladacu "povie", ktory druh pristupu
> sa ma pouzit).
>
> Prekladace su obvykle nastavene tak, ze "nativne" umiestnuju/pouzivaju
> premenne v RAM (ak je ich viac, obvykle sa da prepinacom pri preklade
> ovplyvnit, do ktorej), tak ako v PDP11. Co so zvysnymi pamatovymi triedami?
>
> Existuju dve moznosti - bud sa prenecha cely problem na programatora, ktory
> si musi rucne rozvrhnut, kde je ktora neRAM premenna alokovana a potom pri
> volani funkcii, ktore vedia tie pamate obsluhovat, pouzivat konstanty
> (mozno vypocitane nejakou jednoduchou aritmetikou) pre adresy a dlzky;
> alebo sa pre konkretny prekladac vytvori nejake rozsirenie jazyka, ktore
> cast alebo vsetko z tohoto problemu riesia pomocou prekladaca. Treba si
> uvedomit, ze sa jedna vlastne o tri skupiny problemov: 1. alokacia
> premennych a metodika, ktorou su dane premenne inicializovane, 2. sposob
> citania a zapisu danych premennych, 3. sposob, ktorym si prekladac interne
> vedie, do ktoreho adresneho priestoru je premenna naalokovana.
>
> Prekladace nemusia mat implementovanu kompletnu podporu v tomto duchu, a
> obvykle ani nemaju. Zlozitost problemu rastie od 1 do 3, takze typicky je
> implementovane len 1. Ciastocna ci plna implementacia 2. a 3. je
> charakteristicky pritomna len u prekladacov, ktore nativne podporuju
> (pomenovane) adresne priestory, napr. Keil C51 alebo SDCC (a asi aj ten
> "omniscient" HiTech C pre PIC (dnes XC8? nepamatam sa) ale o tom viem malo
> lebo nie som PICkar). Do urcitej miery su named address spaces
> implementovane aj v avr-gcc, hoci asi vacsina uzivatelov (tvorena
> arduinistami) o tom netusi (a v g++ to asi ani dobre alebo vobec
> nefunguje). Toto je v skutocnosti velmi rozsiahla problematika na poctive
> riesenie ktorej nie su ani ludia ani cas a ani peniaze.
>
> Takze u vacsiny prekladacov je implementovane len 1., 2. je namiesto
> nativneho pristupu (kde by uzivatel pouzival dane premenne uplne rovnako
> ako premenne v RAM) nie je a je to odbyte implementaciou funkcii na
> citanie/zapis (alebo, ako je to asi aj v tomto pripade EEPROM, je pristup
> k danej pamati asymetricky, t.j. citanie je rovnake ako u normalnych
> premennych kdezto zapis je prostrednictvom funkcii); a 3. by aj tak bolo
> treba len v pripade plnej implementacie 2. takze na to sa da v tomto
> pripade zabudnut.
>
> 1. sa da dosiahnut pomerne lahko za pouzitia linkera, t.j. casti
> prekladaca, ktory ma na starosti prave alokaciu pamate a povkladanie
> adries naalokovanych premennych vsade kam treba do vysledneho binaru
> programu. Linker je typicky ovladany konfiguracnym suborom, ktory sa
> nazyva linker script, a obvykle existuje nejaka metoda, ktorou sa v
> zdrojovom texte oznaci nestandardne alokovana premenna (napr. klucove
> slovo EEPROM, nech to znamena cokolvek), sucastou metody je potom interny
> mechanizmus, ktorym sa toto oznacenie prenesie az do linkera, ktory tym
> padom vie, ze takto oznacena premenna ma byt vlozena do nejakej konkretnej
> oblasti ("section") pamate. Ze na akej adrese je dana oblast umiestnena a
> ako je velka, pripadne aj nejake jej vlastnosti (napr. jej adresna
> granularita, ak nie je 1, lebo su aj take pamate kde sa napriklad daju
> zapisovat napriklad len cele N-bytove kusy naraz, a tak je treba potom
> premenne do nej alokovat) je prave zadane linker scriptom, co umoznuje
> urcitu pruznost pre uzivatela.
>
> Tato sada vlastnosti sa vyuziva napokon aj tam, kde je k dispozicii
> nesuvisla RAM, prip. RAM, ktora sice suvisla je, ale pozostava z viacerych
> casti a existuju dovody na alokaciu do separatnych casti (napr. len cast
> RAM je chranena hardwarovymi prostriedkami proti neziaducemu
> zapisu/citaniu alebo proti chybe sposobenej ionizujucim ziarenim, alebo
> cast RAM je intenzivne pouzivana nejakym rozhranim typu DMA ktore "brzdi"
> procesor pristupujuci do tej istej RAM, alebo cast RAM je vyhradena pre
> komunikaciu medzi procesormi vo viacjadrovom mcu, cast RAM je baterkou
> zalohovana, cast RAM je fyzicky pomalsia alebo je za sustavou zbernic,
> ktore pristup do nej spomaluju - vsetko toto je pomerne bezne u stredne
> velkych 32-bitovych mcu) - v tomto pripade nie je problem s 2. a 3 a takto
> naalokovane premenne sa pouzivaju uplne rovnako ako akekolvek ine premenne.
>
> Dost charakteristicky sa 1. pouziva aj tam, kde je ROM/FLASH sucastou
> jednotneho adresneho priestoru a cita sa rovnakou metodou ako RAM (a zapis
> sa vobec neuvazuje alebo je to len velka zriedkavost). Pomerne bezne sa na
> tento pristup ani nepouzivaju ziadne rozsirenia syntaxe jazyka, jednoducho
> len kompilator pre vsetky premenne kvalifikovane ako const generuje
> automaticky aj znacku pre linker, aby tuto premennu umiestnil v oblasti
> ROM/FLASH (niekedy je
>
> Rozdiel medzi implementaciou len 1. a "rucnou" alokaciou je (okrem toho, ze
> je tym obvykle vyriesena inicializacia premennych - pri alokacii do
> FLASH/EEPROM je inicializator jednoducho sucastou generovaneho binaru a
> premenne sa pomerne prirodzene inicializuju sucasne s "napalovanim"
> programu) v tom, ze na zadanie adresy/velkosti citanej/zapisovanej pamati
> sa daju pouzit nativne prostriedky prekladaca - adresa sa da ziskat
> pomocou operatora & (a naslednym pretypovanim vysledku zo smernika na cele
> cislo, ci uz uzivatelom pred volanim, alebo samotnou volanou funkciou -
> obe tieto operacie maju podla normy implementacne zavisly efekt, no ale
> bavime sa tu o funkciach ktore prinalezia konkretnej implementacii, takze
> to je v poriadku) a na velkost zapisovanej premennej sa da pouzit operator
> sizeof (v oboch jeho formach, t.j. priamo aplikovany na premennu alebo
> aplikovany na typ premennej). Vyhodou tiez je, ze linker automaticky
> pouklada vsetky premenne alokovane do urcitej oblasti (a tie mozu byt v C
> zdrojaku definovane na roznych miestach, v roznych zdrojovych .c suboroch)
> pekne za seba, takze je zarucene, ze sa neprekryvaju. (Linker tiez vie
> upozornit, ak by premenne "vytiekli" z danej oblasti, t.j. by ich bolo
> privela). Na druhej strane, automaticke usporiadanie premennych je aj
> nevyhodou, kedze sa tym ztazuje kompatibilita medzi roznymi verziami
> programu (ktore by mohli chciet mat urcite premenne vzdy na tom istom
> mieste). Technik, ktorymi sa docieli kompromis, je viacero, ale zavisia od
> konkretneho prekladaca/linkera.
>
> Do urcitej miery suvisiace: http://efton.sk/tmp/C_ch50.pdf
>
> wek
>
>
>
> ----- Original Message ---------------
>
> Subject: MPLAB - prace s EEPROM
>     From: Admin HWnews <hwnews na cncnet.info>
>     Date: Thu, 6 Jan 2022 08:39:02 +0100
>       To: HW-news <hw-list na list.hw.cz>
>
> Zdravim,
>
> snazim se zase nejak pokrocit s tim zatrolenym Cckem v MPLABu a narazil
> jsem na dalsi problem..respektive netusim jak se to spravne resi.
>
> Potrebuji ukladat nejake obsahle konfiguracni struktury - nekolik sad
> techto struktur...moje predstava je, ze nadefinuji pole struktur. Jedna
> cast bude ulozena normalne v kodu tedy ve flash pameti (to jsou data,
> ktera jsou znama v dobe kompilace) a pak bych rad mel jeste druhou sadu,
> ktera bude uzivatelsky definovatelna ...treba 10 polozek pole (podle
> toho co se vejde do EEPROM). Potrebuji na zaklade pripojene periferie
> najit v tech polich odpovidajici konfiguracni sadu (dle nejakeho
> identifikatoru) a tu si nacist do promenne.
>
> Pochopil jsem, ze kdyz chci umistit promennou do EEPROM pouziji klicove
> slovo EEMEM. Nicmene nejak nechapu jaky to ma smysl.
>
> Tak jak jsem to resil driv treba v uPascalu bylo, ze jsem mel
> nadefinovanou jednu strukturu jako promennou v RAM a z EEPROM jsem si od
> nejake pevne dane adresy nacital nejaky blok dat a pro dalsi sadu jsem
> si jen pocatecni adresu zvysil o offset dany velikosti te struktury v
> eeprom.
>
> Tady ale netusim jaky vyznam ma definovat neco v EEPROM...stejne se s
> tim neda primo pracovat...stejne budu muset pouzit neco takoveho:
>
> eeprom_write_block(&DA485_par, &DA485_par_EE, sizeof(DA485_struct));
>
> coz mi prijde v podstate uplne to same...jen teda netusim jak zajistim
> to abych zapsal jen cast toho pole v EEPROM.
>
> Budu moc vdecnej za nejake navedeni...ta filosofie tohodle jazyka mi
> prijde proste silena. :-(
>
> RV
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list




Další informace o konferenci Hw-list