Salve ragazzi, oggi girovagando sul sito di arduino ho trovato una pagina interessante: PROGMEM - Arduino Reference .
Tratta di come salvare dei dati sulla memoria Flash (memoria di programma).
Ho un paio di domande al riguardo.
Nell'esempio:
/*
PROGMEM string demo
How to store a table of strings in program memory (flash),
and retrieve them.
Information summarized from:
http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
Setting up a table (array) of strings in program memory is slightly complicated, but
here is a good template to follow.
Setting up the strings is a two-step process. First define the strings.
*/
#include <avr/pgmspace.h>
prog_char string_0[] PROGMEM = "String 0"; // "String 0" etc are strings to store - change to suit.
prog_char string_1[] PROGMEM = "String 1";
prog_char string_2[] PROGMEM = "String 2";
prog_char string_3[] PROGMEM = "String 3";
prog_char string_4[] PROGMEM = "String 4";
prog_char string_5[] PROGMEM = "String 5";
// Then set up a table to refer to your strings.
PROGMEM const char *string_table[] = // change "string_table" name to suit
{
string_0,
string_1,
string_2,
string_3,
string_4,
string_5 };
char buffer[30]; // make sure this is large enough for the largest string it must hold
void setup()
{
Serial.begin(9600);
}
void loop()
{
/* Using the string table in program memory requires the use of special functions to retrieve the data.
The strcpy_P function copies a string from program space to a string in RAM ("buffer").
Make sure your receiving string in RAM is large enough to hold whatever
you are retrieving from program space. */
for (int i = 0; i < 6; i++)
{
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
Serial.println( buffer );
delay( 500 );
}
}
Crea 6 stringhe che poi racchiude in un arry? E' giusto?
Quindi con l'aiuto della libreria "avr/pgmspace.h" scrive sulla memoria Flash, ma per cancellare?
La flash la scrivi durante la programmazione del micro, probabilmente potresti andare poi a modificarla ma rischieresti di rovinare il software visto che dovresti sapere bene l'indirizzo dove questa è memorizzata.
ypkdani:
La flash la scrivi durante la programmazione del micro, probabilmente potresti andare poi a modificarla ma rischieresti di rovinare il software visto che dovresti sapere bene l'indirizzo dove questa è memorizzata.
Credo che a "stare attento" agli indirizzi di memoria ci pensi la libreria stessa.
L'unica cosa che puoi fare con Progmem è salvare delle stringhe nella flash durante la programmazione(quando cioè carichi il tuo sketch su arduino). Dall'esempio:
tu vai a salvare nella flash le stringhe "String 0",......
Queste stringhe poi puoi solo leggerle durante l'esecuzione del tuo programma ma non modificarle.
@Xfox:
ti spiego brevemente. Lo sketch che scrivi te NON viene scritto poi così com'è nella memoria del micro. Viene compilato e trasformato in codice macchina, che poi viene salvato nella memoria del micro.
Se il tuo programma non modifica più quella variabile creata nella Flash con PROGMEM non succede nulla. Ma se la va a toccare possono succedere 2 cose:
se è una variabile semplice, mettiamo ad esempio un tipo int, ed il tuo programma ne cambia spesso il valore, il micro andrà a riscrivere tante volte la Flash, e la Flash ha un difetto: permette max. 10.000 riscritture, dopodiché è... fritta. Quindi per assurdo uno sketch può rovinare alcune locazioni della Flash in brevissimo tempo.
se è una variabile dinamica, ossia che la sua dimensione può aumentare o diminuire durante l'esecuzione del programma (ad esempio un tipo String) non solo puoi incappare nel problema del punto 1) ma anche in quello che ti diceva ypkdani.
Quindi, per regola dichiara ciò che vuoi mettere in Flash di tipo "const", ossia costanti. Cioè variabili il cui contenuto non può più essere toccato. A questo punto potresti chiederti allora che senso ha usare PROGMEM: serve quando hai molti dati (tipo array) immutabili che non vuoi che il tuo programma crei nella SRAM, la memoria dove "vivono" le variabili che ha una dimensione limitata (2 kB negli Atmega328).
Non ho indagato a fondo ma credo che un programma che gira sulla Flash non possa modificare il contenuto della Flash. Se cercherai di modificare una variabile che é memorizzta nella Flash non cambierá.
Con Progmem risparmi RAM perché puoi mettere di valori costanti (come valori costanti o stringhe che servono per mettere su un display o da spedire via seriale o webserver) nella Flash.
Ciao Uwe
Ho capito perfettamente!
Però la parte citata di codice la posso inserire in un punto qualsiasi dello sketch?
Ci pensa progmem a far attenzione a salvare i miei dati (int, string che siano) in una parte di memoria che non viene sovrascritta poi dallo sketch stesso?
uwefed:
Non ho indagato a fondo ma credo che un programma che gira sulla Flash non possa modificare il contenuto della Flash. Se cercherai di modificare una variabile che é memorizzta nella Flash non cambierá.
Con Progmem risparmi RAM perché puoi mettere di valori costanti (come valori costanti o stringhe che servono per mettere su un display o da spedire via seriale o webserver) nella Flash.
Ciao Uwe
Ad essere corretti un programma che gira in Flash può modificare la Flash, così fa il bootloader (che è su Flash) quando poi riprogramma la Flash con lo sketch in arrivo sulla seriale, così fa il bootloader di Uzebox che scrive nella Flash il gioco scelto dall'utente tra la lista di quelli presenti in una SD. Però la tua obiezione mi ha fatto ricontrollare meglio pgmem.h ed effettivamente questa libreria NON supporta la scrittura in Flash per cui è corretto dire quanto segue:
nonostante il micro supporti la lettura/scrittura della Flash a runtime, la libreria prgmem non permette di fare tale operazione.
Progmem praticamente è utile se hai per esempio 10-20 stringhe da memorizzare ed in base ad un errore ne invii una di queste. Se invece hai una stringa che varia continuamente non puoi farlo, puoi pero definirla localmente in modo che venga eliminata dalla memoria una volta finito il suo utilizzo
Una cosa per cui è utile PROGMEM e che non sapevo.
In realtà non serve per salvare le variabili in Flash al posto della SRAM, serve per evitare che in runtime le variabili vengano copiate nella RAM!
A questa cosa non ci pensavo ma è chiara, se si ragiona pensando che il micro ha un'architettura Harvard per cui i dati vivono in una memoria separata da quella del codice. Il micro infatti si aspetta di trovare i dati nella RAM e quando deve ad esempio usare la variabile "X" la crea nella RAM e ci copia il suo contenuto e poi la legge da lì, mentre con PROGMEM la legge direttamente dalla Flash.
leo72:
Ad essere corretti un programma che gira in Flash può modificare la Flash, così fa il bootloader (che è su Flash) quando poi riprogramma la Flash con lo sketch in arrivo sulla seriale, così fa il bootloader di Uzebox che scrive nella Flash il gioco scelto dall'utente tra la lista di quelli presenti in una SD. Però la tua obiezione mi ha fatto ricontrollare meglio pgmem.h ed effettivamente questa libreria NON supporta la scrittura in Flash per cui è corretto dire quanto segue:
nonostante il micro supporti la lettura/scrittura della Flash a runtime, la libreria prgmem non permette di fare tale operazione.
Anche perché sia la memoria Flash che la memoria EEprom sono organizzate a blocchi e non puoi cancellare e scrivere una sola cella di memoria, ma sempre l' intero blocco.
@ ypkdani
Penso che vale la stessa cosa della validitá delle varabili anche per progmem.
Quelle dichiearte nelle funzioni sono variabili locali non esistenti fuori da tale funzione.
per questo e per leggibilitá migliore si raguppano le definizioni e eventuale contenuto delle variabili all'inizio sketch prima delle funzioni.
uwefed:
Anche perché sia la memoria Flash che la memoria EEprom sono organizzate a blocchi e non puoi cancellare e scrivere una sola cella di memoria, ma sempre l' intero blocco.
Ciao Uwe