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++);
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...
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]
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.
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" ...
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.
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.
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.