LIBRERIA FLASHSTORAGE - MEMORIZZARE ARRAY DI STRUCT IN UN UNICA ALLOCAZIONE

Salve a tutti,
avrei da memorizzare in flash un array di struct utilizzando la libreria "flashstorage". Ho dichiarato in questo modo l'array:

typedef struct {
 nt tipo = 1;
 char descrizione[];
 char modello[];
 boolean disponibilita;
 int specifichei[];
} 
strumenti;
strumenti st[60];

Il problema è che non riesco a dichiarare un unica allocazione di flash per l'intero array e sono costretto a dichiararne 60 (per quanti sono gli indici:

FlashStorage(my_flash_store0, strumenti);
FlashStorage(my_flash_store1, strumenti);
FlashStorage(my_flash_store2, strumenti);
FlashStorage(my_flash_store3, strumenti);
FlashStorage(my_flash_store4, strumenti);
FlashStorage(my_flash_store5, strumenti);
FlashStorage(my_flash_store.................);
...........................................................
...................................
........

e a differenziare la lettura e la scrittura distinando il singolo indice ad una differente allocazione:

//SCRITTURA DIFFERENZIATA PER ALLOCAZIONE
void ScriviFlash(int indice)

{
 if (indice== 0)
 {
   my_flash_store0.write(st[indice]);
 }
 else if (indice == 1)
 {
   my_flash_store1.write(st[indice]);
 }
 else if (indice == 2)
 {
   my_flash_store2.write(st[indice);
 }
 else if (indice == 3)
 {
   my_flash_store3.write(st[indice]);
 }
 else if (indice== 4)
 {
   my_flash_store4.write(st[indice]);
 }
........................
.......................
.......................
}
void LeggiFlash(int indice)
{
 //LETTURA DIFFERENZIATA PER ALLOCAZIONE
 if (indice == 0)
 {
   st[indice] = my_flash_store0.read();
 }
 else if (indice== 1)
 {
   st[indice] = my_flash_store1.read();
 }
 else if (indice == 2)
 {
   st[indice] = my_flash_store2.read();
 }
 else if (indice == 3)
 {
   st[indice] = my_flash_store3.read();
 }
 else if (indice == 4)
 {
   st[indice] = my_flash_store4.read();
 }
.......................
.......................
.......................
}

Sono costretto praticamente a replicare tutto per i 60 inidici. Sarebbe molto piu comodo e "stilisticamente" corretto poter memorizzare l'intero array in un unica allocazione.

Chi riesce a darmi una mano? Ve ne sarei veramente grato.

Un abbraccio e tanti auguri di buon Natale a tutti.

Antonio

Ciao, Antonio
Benvenuto!

Come da regolamento, devi racchiudere le parti di codice usando il tasto < / > che trovi sopra al messaggio quando fai "More/Modify".
Inoltre, il titolo tutto maiuscolo è un po' fastidioso...

Grazie
Gianluca

quando avrai modificato il primo post,
qualche idea c'è

Standardoil ho modificato il post,
ti ringrazio in anticipo per l disponibilità.

Antonio

ho dato uno sguardo alla libreria
e mi sembra proprio che usi pesantemente puntatori e sizeof()
prova a fare una cosa del genere

typedef struct {
 nt tipo = 1;
 char descrizione[];
 char modello[];
 boolean disponibilita;
 int specifichei[];
}
strumenti;
strumenti st[60];
FlashStorage(my_flash_store, sizeof(strumenti)*60);
// per scrivere tutti assieme
my_flash_store.write(st);
// per leggere tutti assieme
   st = my_flash_store.read();

ma non puo' funzionare, l'ultima riga è sbagliata

boh, ci penso...

PS
hai provato con un array di oggetti flash?

Sembra che lo spazio allocato in flash sia determinato a compile-time, cioè il compilatore deve potere ricavare informazioni sulla dimensione partendo dal tipo di dato specificato.

Con la struttura che hai definito non è possibile sapere quanto spazio occupa, dovresti specificare quanti elementi hanno gli array.

L'esempio "StoreNameAndSurname.ino" mostra questa struttura:

typedef struct {
  boolean valid;
  char name[100];
  char surname[100];
} Person;

// Reserve a portion of flash memory to store a "Person" and
// call it "my_flash_store".
FlashStorage(my_flash_store, Person);

FlashStorage è una macro:

#define FlashStorage(name, T)

Su 'T' esegue in sizeof(T) e grazie a ciò ricava la dimensione.

C'è un altra macro:

#define Flash(name, size) \

Dove come si vede si può specificare per size sizeof(strumenti) * 60
Provala con la struttura seguente:

typedef struct {
 int tipo = 1;
 char descrizione[20];
 char modello[10];
 boolean disponibilita;
 int specifichei[20];
} strumenti;

Ciao.

per maurotec: giusto, non avevo fatto caso all'interno della struttura
però ancora rimane come passare l'intero array e/o un singolo
chissa se funziona:

for (i=0; i<60;i++)
{
FlashStorage(my_flash_store[i], sizeof(strumenti));
}

hai visto mai che essendo una macro.......

[edit in realtime]
no, non puo' funzionare, le macro sono espanse a realtime
[/edit in realtime]

unica cosa che mi viene in mente è leggerle / scriverle tutte assieme, usando una union di array di byte sopra all'array di strutture, ma è una porcata

ci penso ancora un po'

Ragazzi grazie mille per il supporto.

Per maurotec: visto che non sono cosi' "avanzato" come te nella programmazione potresti sottopormi un esempio completo? L'osservazione di Standardoil è corretta, va bene la dichiarazione dell'array e della macro "*60" ma non saprei poi come accedere ai dati. Con una struttura del tipo array di struct posso scorrere gli indici semplicemente con un ciclo for, nel caso del tuo esempio non saprei come fare.

Attendo tue

Grazie ancora

Antonio

Non la ho quella lib in locale, quindi l'ho solo letta on line dal repositor git.

Ad occhio direi di scrivere:
Al posto di questo:

FlashStorage(my_flash_store, Person);

questo:

strumenti st[60];
Flash(my_flash_store, sizeof(strumenti) * 60);
// Read the content of "my_flash_store" into the "owner" variable
st = my_flash_store.read();

st[0].tipo = 2;
st[0].disponibilita = true;

// salva tutto in flash
my_flash_store.write(st);

Ciao.

Maurotec ti ringrazio ancora per la premura e il supporto,
ne approfitto per farti i piu sinceri auguri di buon anno.

La compilazione sembra che vada a buon fine se mi limito alle dichiarazioni e alla scerittura. Se implemento la lettura con la riga

st = my_flash_store.read();

ottengo errore,

Ho guardato il codice nella libreria, per la classe Flash la funzione read sembra si aspetti qualcosa in piu tra cui la dimensione:

void FlashClass::read(const volatile void *flash_ptr, void *data, uint32_t size)
{
  memcpy(data, (const void *)flash_ptr, size);
}

Per quanto mi sforzi a interpretarla capisco che non è alla mia portata..

Mi dai una mano :frowning:

Grazie e scusa ancora

Antonio

Standardoil scusami,
non avevo notato che anche tu fossi arrivato alla medesima conclusione, non so perchè avevo saltato il tuo post. Ad ogni modo come leggi sopra sono arenato con la lettura che è l'unica istruzione che mi provoca errore di compilazione. Se leggi su ho spiegato tutto. Hai qualche idea? Sono nei guai se non risolvo :frowning:

Grazie mille e auguri di buon anno.

Antonio

ottengo errore,

Si ma quale errore, vorrei evitare di spendere una ora per scrivere codice di test che poi non possono testare nella piattaforma poiché non la ho.

Posta tutto il codice che usi e l'errore (per errore noi intendiamo che il compilatore esce con errore non concludendo la compilazione.).

Ciao.

Il costruttore di FlashCalss

FlashClass::FlashClass(const void *flash_addr, uint32_t size) :
  PAGE_SIZE(pageSizes[NVMCTRL->PARAM.bit.PSZ]),
  PAGES(NVMCTRL->PARAM.bit.NVMP),
  MAX_FLASH(PAGE_SIZE * PAGES),
  ROW_SIZE(PAGE_SIZE * 4),
  flash_address((volatile void *)flash_addr),
  flash_size(size)
{
}

Prende due argomenti, un puntatore null di tipo const void *flash, size di tipo uint32_t.

La macro Flash

// Concatenate after macro expansion
#define PPCAT_NX(A, B) A ## B
#define PPCAT(A, B) PPCAT_NX(A, B)

#define Flash(name, size) \
  __attribute__((__aligned__(256))) \
  static const uint8_t PPCAT(_data,name)[(size+255)/256*256] = { }; \
  FlashClass name(PPCAT(_data,name), size);

La chiamata a costruttore tramite la macro Flash

Flash(my_flash_store, sizeof(strumenti) * 60);

Si espande in:

__attribute__((__aligned__(256)))  static const uint8_t _datamy_flash_storage)[(size+255)/256*256] = { };
  FlashClass name(_datamy_flash_storage, size);

Il nome della istanza di classe

my_flash_storage

Ora per leggere si deve usare il metodo read (c'è ne sono due) proviamo con questo:

void read(void *data)        { read(flash_address, data, flash_size);  }

Quindi leggiamo con:

my_flash_storage.read(st);

// oppure se da errore: my_flash_storage.read( (void*) st);

Per la write usiamo:

void write(const void *data)

da usare allo stesso modo di read.

PS: Ci sono due classi, una standard FlashClass e l'altra è un template C++ FlashStorageClass che vuole T come tipo da cui riva la dimensione. Per la tua necessità non puoi usare il template ma la classe standard.

Prova e fa sapere (inclusi errori).

Ciao.