Home

EPROM

 

Accesso alla EEPROM interna

 
Uno degli argomenti che fino ad ora non ho ancora affrontato è quello della memorizzazione dei dati in maniera permanente. Molte applicazioni necessitano infatti di mantenere telune informazioni anche nel caso in cui l'alimentazione viene a mancare. Si pensi ad esempio ad un contacicli nelle macchine di produzione oppure alle password di accesso ai sistemi o anche il numero IP di un host. Anche con i PICMicro è possibile


C'è memoria e memoria...

Facciamo un breve excursus. I sistemi informatici si basano principalmente su questo tipo di memorie:

  • memorie volatili;
  • memorie non volatili;
  • memoria di massa

Memorie volatili

Rientrano in questa categoria principalmente le memorie RAM, acronimo di Random Access Memory. La RAM è costituita da una serie di celle in grado di memorizzare le informazioni solamente se tali celle vengono mantenute alimentate. Mediante una linea bus indirizzi e una linea bus dati è possibile accedere alla singola cella e leggerne e/o scriverne il valore. Le celle sono assimilabili a condensatori il cui valore di carica determina lo stato di un bit. Le memorie RAM di tipo dinamico (note anche come DRAM) dispongono anche di un pin di controllo detto di refresh che serve a rinfescare il valore di carica delle celle/condensatori. Altre memorie, come le FerroRAM mantengono il dato in memoria senza dover avere il meccanismo di refresh. Altri bit di controllo, come i comandi di lettura (Read) e scrittura (Write) permettono alla CPU di accedere alla memoria.

 

Schematizzazione memoria RAM

Ecco come si presentano alcune memorie RAM in uso sui personal computer (fonte Wikipedia):

Memorie RAM

Memorie non volatili

Questo tipo di memorie in passato sono state impiegate per la memorizzazione di programmi (o parti di essi) che non avevano motivo di venire modificate. I primi home-computer disponevano infatti di una ROM, acronimo di Read-Only Memory, nel quale veniva posto ad esempio un interprete BASIC oppure un "rozzo" sistema operativo. Oggi le ROM, nella loro eccezione esatta, non esistono (quasi) più. Anche i microcontrollori, da oltre dieci anni, hanno abbandonato questa tecnologia e utilizzano, per la memorizzazione del firmware, memorie non volatili di tipo FLASH.
Esistono poi memorie non volatili programmabili come le EPROM (Electrically Programmable ROM) e le EEPROM (Electrically Eraseble Programmable ROM). Le prime ormai sono quasi del tutto sparite, mentre le seconde, pur in tecnologia FLASH e non più CMOS, trovano ampio spazio, anche nel mondo dei microcontrollori!

 

Schematizzazione memoria ROM

In questa immagine alcune EPROM, memorie che venogono programmate per via elettrica e cancellate con raggi U.V.

EPROM

 

Ed ecco un programmatore multiplo, che viene utilizzato per caricare il firmware in modo contemporaneo su 10 EPROM, leggendone una campione. Programmatori analoghi vengono invece connessi ad un computer per poter caricare il firmware presente su HD.

Programmatore EPROM

Memorie di massa

Tra questo tipo di memoria si annoverano i sistemi di memorizzazione di grosse quantità di dati. Il primo pensiero è rivolto alle unità a disco, come gli hard-disk. In passato i dischi flessibili denominati floppy disk rappresentavano l'evoluzione miniaturizzata dei sistemi di memorizzazione di massa che, fino a quell'epoca, erano rappresentati da grosse bobine di nastro magnetico. Il disco "floppy" o "hard" ha segnato il passo: ha permesso infatti l'accesso rapido e indirizzato ai dati memorizzati, cosa che non era possibile con i nastri magnetici, essendo essi dispositivi con memorizzazione dati di tipo sequenziale.

Floppy disk da 5" e 1/4
Oggi i sistemi di memorizzazione di massa si sono notevolmente ampliati e in pochi centimetri cubi di volume possiamo immagazzinare quantità di dati impressionanti, eliminando anche le parti in movimento. L'evoluzione dell'hard disk è infatti il dispositivo a stato solido che tutti conosciamo sotto le sembianze di "chiavette USB" e schede di memoria nei formati e nelle sigle che si leggono ovunque: MMC, SD, CompactFLASH, ecc.
Un ulteriore passo in avanti è rappresentato dal cloud-computing che, nella sua eccezione relativa alla memorizzazione dei dati, svincola gli utenti dal possedere un proprio dispositivo di memorizzazione, demandando questa incombenza a grossi server ai quali il nostro terminale si va a collegare, mediante una connessione in rete.

Tanto per rendere l'idea di come si sono evoluti i sistemi di memorizzazione nel giro di una ventina di anni, ecco una rassegna di dispositivi: si va dal disco di alluminio magnetizzato di un HD da 14 pollici fino alla piccolissima microSD. Le dimensioni dei dispositivi sono inversamente proporzionali alla capacità di memorizzazione.

Sistemi di memorizzazione

 

I PICMicro e le memorie

È giunto il momento di analizzare cosa contiene, in termini di memoria, un microcontrollore. La prima cosa da fare è scegliere un PICMicro ed aprire il suo datasheet. Ed ecco come si presenta l'architettura interna di un PIC16F819. In rosso ho evidenziato le tre memorie RAM, Flash ed EEPROM.


Architettura PIC16F819

 

Per avere un'idea delle dimensioni di ciascuna delle memorie, ecco qui un paio di tabelle che dovrebbero aiutare a decifrare.

 

Tabella memoria PIC16F819

 

Tabella memoria PIC16F819

 

Dato che il datasheet si riferisce tanto al PIC16F818 quanto al PIC16F819, in rosso ho evidenziato le caratterische del PIC16F819. Riassumendo, ecco le caratteristiche del PIC16F819:

  • Flash: 3584 byte;
  • RAM: 256 byte;
  • EEPROM: 256 byte

Il fatto che sia indicato un "X14" piuttosto che un "X8", significa che lo spazio di indirizzamento è a 14 o a 8 bit, in funzione del tipo di accesso. Ma questa è un'altra storia, di cui, in parte, racconterò in queste pagine.

 

La EEPROM e i suoi registri

Come detto la EEPROM è una ROM cancellabile e programmabile elettricamente, il che significa che con opportuni valori di tensione, è possibile scrivere e/o cancellare dati. La EEPROM è sì una memoria non volatile ed è utile per conservare variabili ritentive, il cui valore deve essere conservato anche in mancanza di energia elettrica, fornita da reti elettriche e/o da batterie tampone, ma dato che non è una memoria ad accesso veloce come la RAM, non viene utilizzata per salvare le variabili di programma!

Dato che la EEPROM interna al PIC è sostanzialmente una memoria FLASH, per la gestione di tale memoria il PIC mette a disposizione un certo numero di registri, i quali permettono tanto l'accesso alla EEPROM quanto alla Program Memory! Sì, alcuni PIC sono programmabili dallo stesso firmware, operazione che ad esempio svolgono i bootloader. C'è però una sostanziale differenza tra la prorgammazione "ordinaria", quella che avviene con modalità ICSP (In Circuit Serial Programming) e l'accesso alla Program Memory da parte del firmware. Ora, non è questo l'argomento dell'articolo ma è necessario averne accennato in quanto, come si vedrà poco più avanti, le impostazioni dei registri possono infatti permettere l'accesso alla Program Memory o alla EEPROM.

Lo schema generale dell'accesso alla EEPROM da parte del PIC è il seguente:

 Schema connessione EEPROM interna a PICMicro

I registri coinvolti nella gestione di Program Memory ed EEPROM sono i seguenti:

  • EECON1
  • EECON2
  • EEDATA
  • EEDATH
  • EEADR
  • EEADRH

Fatta eccezione per EEDATH ed EEADRH, i rimanenti registri sono tutti coinvolti nelle operazioni di lettura e scrittura della EEPROM. Questi sono i ruoli giocati dai singoli registri:

  • EECON1: è il registro di configurazione principale. Contiene al suo interno bit per impostare l'accesso in scrittura o lettura, lo stato di eventuali errori, l'accesso alla Program Memory o alla EEPROM
  • EECON2: non è un vero e proprio registro, infatti una lettura di EECON2 comporta solamente come risultato '0'. Questo registro è utilizzato dal PIC nella sequenza di scrittura dei dati
  • EEDATA: registro a 8 bit che contiene il dato da scrivere in EEPROM oppure il dato che la EEPROM restituisce a seguito di una lettura
  • EEADR: è il registro che contiene l'indirizzo della cella di memoria della EEPROM nella quale si vuole scrivere o leggere un dato

Il registro EECON1 è così composto

 

Registro EECON1

Il significato dei bit è il seguente:

bit nome significato
0 RD Se posto a 1, avvia una lettura
1 WR Se posto a 1, avvia una scrittura
2 WREN

Se posto a 1, abilita i cicli di scrittura,

altrimenti li inibisce

3 WRERR

Bit di sola lettura: se è posto a 1,

significa che è avvenuto un errore

durante le operazioni di scrittura

4 FREE

Bit per la cancellazione di una cella

all'indirizzo composto EEADRH + EEADR

(accesso alla Program Memory)

5 --- Non usato
6 --- Non usato
7 EEPGD

 Se posto a 1 permette l'accesso alla

program memory, viceversa si accede

alla EEPROM

 

Accesso in lettura

La lettura dei dati dalla EEPROM è senz'altro un'operazione molto semplice. Con quattro passi si arriva dalla richiesta al dato:

  1. Scrivere nel registro EEADR l'indirizzo della cella alla quale si vuole accedere
  2. Porre a 0 il bit EEPGD del registro EECON1, in modo da dichiarare l'accesso alla EEPROM
  3. Porre a 1 il bit RD di EECON1, in modo da dare il via alle operazioni di lettura
  4. Leggere il dato dal registro EEDAT

In linguaggio C, tutto questo si traduce in poche righe:

unsigned char read_eeprom(unsigned char eeprom_address)
{
    unsigned char ee_data;

    EEADR  = eeprom_address;        // EEPROM address stored in the byte register

    EEPGD = 0;                                // Access to EEPROM memory
    RD = 1;                                     // Start EEPROM reading

    ee_data = EEDATA;                   // Read the EEDATA
    return ee_data;
}

Per chi preferisce l'assembly, è sufficiente copiare le righe che il datasheet mette a disposizione ed il gioco è fatto:


BANKSEL EEADR        ; Select Bank of EEADR
MOVF ADDR, W         ;
MOVWF EEADR         ; Data Memory Address to read
BANKSEL EECON1        ; Select Bank of EECON1
BCF EECON1, EEPGD     ; Point to Data memory
BSF EECON1, RD         ; EE Read
BANKSEL EEDATA         ; Select Bank of EEDATA
MOVF EEDATA, W         ; W = EEDATA


Accesso in scrittura

La scrittura dei dati in EEPROM è invece una faccenda più complessa. Microchip infatti impone una sequenza di istruzioni da rispettare tassativamente, pena il malfunzionamento della procedura.

  1. Qualora gli interrupt siano abilitati, verificare che il bit EEIF sia posto a 1, il che significa che non è in corso alcuna operazione di scrittura. Viceversa, verificare che il bit WR di EECON1 non sia posto a 1, proprio ad indicare che non sia in atto alcuna operazione di scrittura
  2. Scrivere nel registro EEADR l'indirizzo della cella alla quale si vuole accedere
  3. Scrivere nel registro EEDAT il dato da scrivere
  4. Porre a 0 il bit EEPGD del registro EECON1, in modo da dichiarare l'accesso alla EEPROM
  5. Porre a 1 il bit WREN del registro EECON1, in modo da abilitare le operazioni di scrittrura
  6. Disabilitare gli interrupt, qualora siano stati abilitati in precedenza
  7. Eseguire una specifica sequenza composta da 5 istruzioni: scrittura di 0x55 prima nel registro W e poi nel registro EECON2, scrittura di 0xAA prima nel registro W e poi nel registro EECON2, avviare il ciclo di scrittura ponendo a 1 il bit WR
  8. Riabilitare gli interrupt, se erano stati utilizzati
  9. Porre il bit WREN a 0 per disabilitare le operazioni di scrittura
  10. Al termine della scrittura, il bit WR viene automaticamente posto a 0 e il bit EEIF viene posto a 1, ad indicare che le operazioni sono state concluse.

 

In C, nuovamente con qualche riga di codice si riesce ad accedere alla EEPROM in scrittura:

void write_eeprom(unsigned char eeprom_address,unsigned char eeprom_data)
{
    char flInterruptEnabled;

// Read the Interrupt status
    flInterruptEnabled = GIE;

    EEADR  =  eeprom_address;      // EEPROM address stored in the byte register

    EEDATA = eeprom_data;           // Load the value that must be saved in EEPROM

    EEPGD = 0;                               // Access to EEPROM memory
    WREN  = 1;                               // Start a data EEPROM writing cycle

    GIE = 0;                                    // Disable Interrupt

/* REQUIRED SEQUENCE */
    EECON2 = 0X55;
    EECON2 = 0XAA;
    WR = 1;
/* REQUIRED SEQUENCE */

    // Enabling interrupt, only if required
    GIE = flInterruptEnabled;      // Enable Interrupt


    while (EEIF == 0);               // Wait for the end of the writing operation
    EEIF = 0;                             // Clear the EEPROM interrupt flag
    WREN = 1;
}


Invece, in assembly il codice è sempre preso dal datasheet:

BANKSEL EECON1         ; Select Bank of EECON1
BTFSC EECON1, WR     ; Wait for write
GOTO $-1                    ; to complete
BANKSEL EEADR         ; Select Bank of EEADR
MOVF ADDR, W          ;
MOVWF EEADR           ; Data Memory Address to write
MOVF VALUE, W         ;
MOVWF EEDATA         ; Data Memory Value to write
BANKSEL EECON1       ; Select Bank of EECON1
BCF EECON1, EEPGD   ; Point to DATA memory
BSF EECON1, WREN    ; Enable writes
BCF INTCON, GIE        ; Disable INTs.
MOVLW 55h              ;
MOVWF EECON2         ; Write 55h
MOVLW AAh              ;
MOVWF EECON2         ; Write AAh
BSF EECON1, WR        ; Set WR bit to begin write
BSF INTCON, GIE        ; Enable INTs.
BCF EECON1, WREN   ; Disable writes

 

Per il download dell'esempio, si faccia riferimento alla sezione DOWNLOAD di questo articolo.

 

EEPROM interne ai PIC18F

Cambia qualcosa con i PIC18F. Infatti per questi PIC è facile trovare dispositivi con tagli di EEPROM maggiori di 256 byte, per i quali i soli 8 bit di indirizzamento sono insufficienti. Il PIC18F4620, ad esempio, ha una EEPROM di 1024 byte, ossia pari a 1kbyte; per accedere a tale EEPROM è indispensabile impiegare un indirizzo ad almeno 10 bit.

 Capacità EEPROM interna a PIC18F4620

Le modalità di accesso alla EEPROM è la medesima a quella dei PIC16F, tanto per i tagli fino a 256 byte quanto per quelli fino a 1kbyte. I file sorgente sono disponibili nella sezione DOWNLOAD di questo articolo.

 

Un esempio per PIC16F

La verifica di quanto accade, con i PIC16F, è espressa da un semplicissimo programma scritto in C per SDCC:


void main(void)
{
    InitPic();
    write_eeprom(0,0x55);
    PORTB=read_eeprom(0);
    while (1);
}

Il programma non fa altro che scrivere all'indirizzo 0 della EEPROM il valore esadecimale 0x55. Siccessivamente il programma accede nuovamente alla EEPROM interna per la lettura del dato all'indirizzo 0. Il valore letto viene poi utilizzato per pilotare PORTB. Per verificare che il valore scritto sia effettivamente presente in memoria, è sufficiente utilizzare MPLAB e richiedere lo stato della EEPROM interna. Prima della scrittura si presenta in questo modo:

La EEPROM prima della scrittura

Dopo aver eseguito il programma, se si legge mediante MPLAB la EEPROM, ecco che si ottiene questo:

La EEPROM dopo la scrittura

Si noti che all'indirizzo 0x00 è presente il valore 0x55, il che è indice di avvenuta scrittura. La lettura del dato è verificabile chiaramente con lo stato di PORTB.

 

Download

Ho cercato di raccogliere quanto detto in due pacchetti zip, uno per PIC16F e l'altro per PIC18F:

 

Licenza

Questo articolo ed il software rilasciato rientrano nell'ambito della licenza CREATIVE COMMONS BY-NC-ND Italia 3.0, secondo quanto indicato nelle note legali qui riportate.

 

  Sintesi delle note legali (italiano)
Creative Common License Note legali (italiano)
  Legal Code (international)
  Commons deed (international)

 

Bibliografia

Dalla rassegna LO HAI MAI REALIZZATO CON UN PIC?

  • I PIC e i segnali analogici: la conversione A/D
  • Una tecnica di misura della tensione di batteri
  • Il PIC tiene la data e l'ora
  • Una prima occhiata a SDCC
  • PIC Watch un semplice OROLOGIO SVEGLIA

 

Ambiente di sviluppo MPLAB

Compilatore SDCC

Compilatore C18

Datasheet PIC16F819

Datasheet PIC18F4620

 
Pillole di microcontrollori PIC:

Pillole di Microcontrollori PIC

Licenza Creative Commons
Questa opera viene distribuita con licenza Creative Commons Attribuzione - Non commerciale - Non opere derivate 3.0 Unported.
ShoppingASEhandelASErhvervIndexDKServiceIndexDK