Pages: [1]   Go Down
Author Topic: pgmspace e puntatori  (Read 724 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2908
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Durante il tempo libero ho cercato varie soluzioni per realizzare una collezione di dati non omogenea, ho provato quasi di tutto e solo una soluzione mi ha colpito, si per vari motivi ma uno in particolare mi porta ancora a pensare alle possibili applicazioni.

Io ho usato un array di struct:
Code:
int16_t setpoint_pb0 = 3000;
int16_t setpoint_pb0_max_value = 32767;
int8_t  setpoint_pb0_min_value = -50;
uint8_t diff_pb0 = 2;

struct data_type_t  {
    uint8_t type;
    void *ptr_data;
};

struct data_type_t data_types[] PROGMEM = {
    {INT16 | VIEW_AS_DOUBLE ,   &setpoint_pb0},
    {INT16 | VIEW_AS_DOUBLE ,   &setpoint_pb0_max_value},
    {INT8                   ,   &setpoint_pb0_min_value},
    {UINT8                  ,   &diff_pb0}
    .....

INT16, INT8 VIEW_AS_DOUBLE sono macro utili per assegnare un valore a data_type.type, VIEW_AS_DOUBLE indica che il dato
anche se è un int16 deve essere visualizzato sul display 7x3 segment con il punto decimale.

La cosa interessante è che data_type.ptr_data contiene un puntatore o meglio un indirizzo di memoria RAM, grazie a &setpoint_pb0. Questo è possibile perché le variabili sono globali e il loro indirizzo viene risolto prima di creare il contenuto in flash. Altra cosa interessante è la possibilita per ptr_data di prendere un puntatore a funzione.

Se al posto di usare la flash usiamo la EEprom possiamo anche cambiare ptr_data per farlo puntare altrove, cioè se in eeprom ci salviamo l'indirizzo di setup() e in type ci salviamo un bit code identificativo possiamo castare a qualunque cosa prevista.

Code:
if (data_type.type = FNC_SETUP)
     (setup)(*data_type.ptr_data)(); // sempre che il cast sia giusto

La cosa bella sarebbe non avere la necessità di castare, ma purtroppo non vedo soluzione.

Per gestire i double ho evitato del tutto di usare questo tipo, anche per temperatura che viene ricavate in centesimi di grado e salvata in un int16_t e quando deve essere visualizzata accendo solo il punto decimale del display nel posto giusto.

Che ne pensate di sta cosa, quale possibile applicazione pratica ci può essere nel salvare puntatori in flash o EEprom?

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 23145
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Aspetta, tu salvi dati in EEPROM con PROGMEM? Non mi torna.
Logged


0
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2908
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non mi aspettavo alcuna risposta prima di 20 minuti e stavo per chiudere, meno male perchè allora mi sono spiegato male.

No in eeprom puoi metterci indirizzi di memoria FLASH e memoria RAM, così come in RAM salvi il puntatore ad indirizzo FLASH io ho fatto il contrario mi sono salvato in FLASH degli indirizzi di memoria RAM e mi sono appuntato come interpretarli grazie a data_type.type.

La cosa bella e che se leggo da eeprom la stessa collezione di dati non omogenea per scriverla in RAM non mi serve neanche fare il cast.

IN FLASH                                            IN RAM                    IN EEPROM
640 (is addr of g)                              &g=640                   25 (is value)
642 (is addr of h)                              &h=642                   2  (is value)

Quindi leggo da flash l'indirizzo di g e accedo a g presente in ram, stessa cosa dovrebbe essere possibile con i puntatori a funzione.

Ah si in effetti se in EEprom scrivo un indirizzo presente in flash come un puntatore a funzione poi posso richiamare questa funzione risalendoci dall'indirizzo.

Ciao.
« Last Edit: August 30, 2013, 11:19:36 am by MauroTec » Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 23145
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok. Comincio a capire "come", ma non capisco "perché" fai questo...  smiley-sweat
Logged


0
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2908
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, il perché è richiesto dalla applicazione e dalla efficienza.

Ho una collezione di dati non omogenea come possono essere tutte le variabili globali normarlmente usate dentro un programma. Come fai ad accedere sequenzialmente a tutte queste variabili sparse per il programma pigiando dei tasti?

Risposta:
Salvi l'indirizzo in un array di struct presente in flash, e quindi leggi da flash una struct per volta e grazie a questa sai che all'indirizzo xxx c'è un intero con segno.

Metti che a tutte queste variabili ci vuoi dare un altro valore preimpostato preso da EEprom o da flash, bene fai il compia incolla
leggi da EEprom e grazie a ptr_data accedi alla variabile in memoria e non serve neanche sapere il tipo.

Cosi è più chiaro?
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 23145
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok. Grazie della spiegazione.
Logged


0
Offline Offline
Faraday Member
**
Karma: 49
Posts: 6020
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mi iscrivo per solidarieta'  smiley
purtroppo solo morale
« Last Edit: August 31, 2013, 03:49:29 am by Testato » Logged

- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

non ho mai torturato troppo arduino..non mi quadra tanto
Code:
(setup)(*data_type.ptr_data)();
..magari si può fare,ma non so..invece dovrebbe andare
Code:
typedef void (*tipoFun)(void);
  ((tipoFun)a)();
forse può dare problemi se gli passi il metodo di una classe(ma forse no,probab arduino,dato che non sfrutta tanto il polimorfismo,non usa i fat pointer)..invece coi funtori dovrebbe andare anche un goccetto più veloce..
Logged

0
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2908
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Si in C++ ci sono anche i funtori e la cosa può funzionare anche con questi ma rimane il problema del casting. Il fatto è che ptr_data è un puntatore a void e prima di usarlo per chiamare funzione bisogna castarlo e finisce la speranza di dinamicità, d'altronde si tratta di C che è tutto altro che dinamico.

Però è possibile usare un puntatore a void per leggere e scrivere nella memoria, per questo mi è possibile cambiare i valori di tutte le variabili globali i cui indirizzi sono stati salvati in flash.

Però questa è una imposizione richiesta dal C/C++ ma non da asm con il quale dovrebbe bastare l'indirizzo e la chiamata __call o sbaglio.

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ho sbagliato a scrivere  smiley-roll-sweat ..per castare da void puoi scrivere
Code:
typedef void (*tipoFun)(void);
  ((tipoFun)data_type.ptr_data)();
, supponendo che te fai un assegnamento del tipo data_type.ptr_data=miaFunzione ..si,l'assembler di solito non è schizzinoso..ti parlavo dei funtori perchè di solito danno la possibilità al compilatore di fare espansioni inline, ma il passaggio tramite un puntatore generico in effetti può precludere questa ottimizzazione..

tipoFun puoi lasciarlo scritto così o dare un altro nome, è uguale..
Logged

0
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2908
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non poi male fare cast a puntatore a funzione che non prende e non restituisce nulla, una certa flessibilità c'è poi per curiosità scrivo un programmino che salva in eeprom i puntatori di 5 funzioni ognuna delle quali stampa in seriale qualcosa di senso compiuto se eseguite in ordine opportuno, poi inverto l'ordine dei dati in eeprom e vediamo cosa accade.

Io ho fatto l'esempio della funzione "setup" perchè attinente ad Arduino, ma io non la uso perchè scrivo solo C con un IDE generico e non uso le funzioni tipiche di Arduino, per cui con i funtori non posso provare. In ogni caso la coperta è sempre corta e se espandi inline occupi più FLASH ma guadagni in velocità specie se chiami il funtore ripetutamente, guadagni in leggibiità e usabilità, ma quano le risorse flash sono limitate pensi a farci stare dentro più codice possibile sacrificando la leggibilità e usabilità.

Se ti va puoi provare a fare tu l'esperimento con i funtori, anche perchè non ho idea di come accroccarlo un esempio valido.

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Offline Offline
God Member
*****
Karma: 9
Posts: 550
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

col mio cast, il compilatore non riesce a fare espansioni inline, tranne se alla variabile assegni una sola funzione,e non hai  if(..)puntat=funzione1;else puntat=funzione2..
Logged

Pages: [1]   Go Up
Jump to: