Macro F() e occupazione di memoria

Ciao a tutti

Poco fa sono stato a combattere con un programma che, dopo aver aggiunto un pezzetto insignificante di codice, si bloccava poco dopo l'accensione.
Al secondo caricamento fallito (voglio dire con il programma che si bloccava), ho pensato subito a una mancanza di memoria, ma il compilatore mi dava un uso dell'85% di flash e del 44% di ram! Tolto altrove un pezzo di codice, tutto funzionava!
Allora ho tolto la F() in alcuni lcd.print(F("Durata")); e simili e adesso funziona.

Perché il compilatore non tiene conto dell'occupazione di memoria spostata dalla macro? Non dovrebbe essere difficile...

Difficile dire che il problema sia F(), poi 44% di ram è ok se poi a run-time fai allocazione dinamica allora può essere quella la causa.

F (o progmem) non fa altro che dire di non caricare in RAM ciò che è dichiarato con F. Per cui la dimensione della flash non cambia. La ram non cambia nemmeno, mentre cambia l’uso dello stack sempre che il buffer sia dichiarato locale e non globale. Nella chiamata a lcd.print(F(“Durata”)) il buffer è locale al metodo print.

size_t Print::print(const __FlashStringHelper *ifsh)
{
  PGM_P p = reinterpret_cast<PGM_P>(ifsh);
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);

La variabile c è il buffer locale.

Ciao.

Mah... Per lasciare un po' di margine per eventuali modifiche, ho messo alcune parti usate un paio di volte in funzioni, risparmiando diverse centinaia di byte in flash. Funziona... :slight_smile:

Forse ci fai vedere lo sketch non funzionante e vediamo piú chiaro

Allego il file .zip di una versione precedente, quando si è manifestato il problema dopo aver aggiunto lo sweep logaritmico (che funziona: togliendo un’altra parte di programma, va…)
La versione che allego funziona solo perché ho tolto un paio di (F( , altrimenti il programma si bloccava due secondi dopo l’accensione
[/quote]

Generatore_con_GPS_e_DDS_v2.2_p11_OK.zip (22.9 KB)

Datman:
La versione che allego funziona solo perché ho tolto un paio di (F) , altrimenti il programma si bloccava due secondi dopo l'accensione

Premesso che la Flash può essere piena al 100% senza alcun problema (viene solo letta, quindi cosa pensi che possa cambiare?), quello provoca questo tipo di blocchi è sempre un problema si SRAM.

Il fatto che il compilatore ti dia il 44% di SRAM occupata NON siglifica nulla ... quella è l'occupazione statica e NON include tutta l'occupazione dinamica (variabili locali, stack, memoria allocata dinamicamente, ecc.).

Ricorda inoltre che con la macro F(), vero che sposti le cose in Flash, ma vero pure che quando le devi usare, almeno una piccola parte deve essere riportata in SRAM e ... se sei già a tappo con la SRAM, un'ulteriore allocazione dinamica manda il tutto in crash.

Guglielmo

Grazie anche a te, Guglielmo
Ma perché togliendo le F in un paio di lcd.print funziona?... Così facendo, occupo più RAM...

Datman:
Ma perché togliendo le F in un paio di lcd.print funziona?... Così facendo, occupo più RAM...

Perché probabilmente sei prorpio al limite e, in tal caso, l'allocazione dinamica occorrente (spazio nell "heap") alla macro F() fa collassare il tutto.

Quello che NON è sotto macro F() è allocato staticamente in ".data", mentre tutto ciò che è allocato dinamicamente finisce nell "heap" che si contende la memoria con lo "stack" ...


Guglielmo

SWEEPOUT:
passo; // Serve solo per scrivere qualcosa per permettere il salto dal goto.
}

Questa non la comprendo mica.

Il programma è davvero lungo e ci sono tante variabili globali e non ho trovato molte String ed in genere un uso smodato dell'allocazione dinamica della memoria per cui faccio fatica a trovare un problema. Quindi sembra che l'ipotesi di Guglielmo sia l'unica, almeno fino a prova contraria.

Leggendo il sorgente vedo solo la possibilità di risparmiare un poco di flash riducendo le ripetizioni ma questo penso lo sistemerai alla fine sempre che sia necessario sistemarlo.

Mi dispiace non avere l'hardware per testare.

Ciao.

Questa non la comprendo mica.

SWEEPOUT è una targhetta per fare un salto verso l'uscita dalla funziona Sweep. Avevo provato return, ma senza successo. Poiché con solo la parentesi chiusa mi dava errore, ho dovuto scrivere qualcosa che non fosse un semplice commento.

Maurotec:

F (o progmem) non fa altro che dire di non caricare in RAM ciò che è dichiarato con F.

Quindi è un po' più lento, ma probabilmente il tempo è comunque trascurabile rispetto alla trasmissione al display.

Datman:

Questa non la comprendo mica.

SWEEPOUT è una targhetta per fare un salto verso l'uscita dalla funziona Sweep. Avevo provato return, ma senza successo.

... evidentemente avevi sbagliato, perché il "return" è fatto apposta per uscire da una funzione ... ::slight_smile:

Guglielmo

Il problema è che devo districarmi da un for che sta dentro un while e uscire dalla funzione... :slight_smile:

Datman:
Il problema è che devo districarmi da un for che sta dentro un while e uscire dalla funzione... :slight_smile:

... e allora? Esistono le break; per uscire dai cicli ... :smiley:

Guglielmo

if(pulsante premuto) {break; break; return;} ?

Datman:
if(pulsante premuto) {break; break; return;} ?

Cos'è questa robaccia ? ? ? :o :o :o

if ( condizione_per_uscire_dal_ciclo ) break;

... ripetuta all'interno di ciascun ciclo (se nidificati).

Usciti da tutti i cicli ...

if ( condizione_per_uscire_dalla_funzione ) return;

Guglielmo

Aaagh! Ti dispiace se lascio il goto?... :slight_smile:

Datman:
Aaagh! Ti dispiace se lascio il goto?... :slight_smile:

SI, mi spiace molto :frowning: , è pratica ampiamente sconsigliata e ...
... dovresti imparare a scrivere i programmi come si deve :grin: :grin: :grin:

Guglielmo

Ok ho sollevato una questione, non era mia intenzione, per risolvere capra e cavoli visto che non ti è venuto l’intuito di scrivere dopo l’etichetta return; potresti anche scrivercelo no. :smiley:

END_SWEEPOUT:
return; 
}

Così io non avrei sollevato la questione. :wink:

Ciao.

A quel punto, però, return non svolge la sua vera funzione, perché sta alla fine della funzione e l'uscita è già assicurata.