Salve a tutti, sto scrivendo uno sketch che occupa una buona parte di flash e ram, circa il 50%, visto che ci sono molti Serial.print usati come debug e che servirebbero solo in caso di problemi, e' possibile escludere queste righe dal compilatore?
Una soluzione potrebbe essere di commentare ogni riga ma l'operazione andrebbe fatta ogni volta per attivare o disattivare il debug e porterebbe via non poco tempo, conoscete un metodo piu' veloce per ottenere lo stesso risultato?
Grazie dell'attenzione.
Metti questo in cima allo sketch:
//#define NDEBUG
#ifndef NDEBUG
#define DSTART(speed) Serial.begin (speed)
#define DPRINT(...) Serial.print (__VA_ARGS__)
#define DPRINTLN(...) Serial.println (__VA_ARGS__)
#else
#define DSTART(...) do {} while (0)
#define DPRINT(...) do {} while (0)
#define DPRINTLN(...) do {} while (0)
#endif
Quindi rimpiazza Serial.begin() con DSTART(), Serial.print() con DPRINT() e Serial.println() con DPRINTLN().
Fatto questo, se scommenti la prima define disabiliti tutti i messaggi, se la togli/commenti li riabiliti.
Scusa SuccoPera,
ma non fa prima a mettere semplicemente le Serial.xxxxxx racchiuse nel #ifdef DEBUG ... #endif ? Se fa la #define DEBUG vengono incluse, se non la fa non vengono incluse ... più semplice di così ... ![]()
Guglielmo
Volendo sì, ma perché scrivere 3 righe ogni volta quando puoi scriverne una? ![]()
Per risparmiare memoria ... non facendo compilare neanche il "do{} while(0);", o, volendo fare come dici tu, sprecarne il meno possibile con una bella "asm("nop\n\t");"
![]()
Guglielmo
Per l'appunto: il do {} while è scritto così per un motivo ben preciso: non facendo di fatto niente, viene totalmente eliminato dal compilatore in fase di ottimizzazione, quindi è proprio come se non ci fosse niente.
Facendo come dici tu forzeresti invece l'inserimento di un'istruzione nop.
Oltre a questo, ha una serie di "pregi sintattici" che gli permettono di apparire ovunque come se fosse una funzione normale, funzionando sempre nel modo "corretto".
SukkoPera:
Per l'appunto: il do {} while è scritto così per un motivo ben preciso: non facendo di fatto niente, viene totalmente eliminato dal compilatore in fase di ottimizzazione, quindi è proprio come se non ci fosse niente.
Hai provato a verificarlo guardando il .asm prodotto (domanda seria ... io non ho verificato) ? ... perché ho sempre dei dubbi su queste "ottimizzazioni" dei compilatori ... ![]()
Guglielmo
Personalmente no, ma visto che ovunque si usa questa forma, mi fido. Se proprio anche non fosse così, mi è sufficiente la comodità che mi dà.
Ho verificato io adesso ...
![]()
Si, è vero, non lo avevo mai provato né verificato dato che uso il metodo che ti ho detto prima (spesso non hai solo le Serial.xxxx, ma manche alte cose da escludere se non sei in debug), comunque è interessante ...
... e l'ottimizzazione è ancora più spinta di quello che si potrebbe pensare ![]()
Questo pezzo di codice:
int A;
...
...
void loop() {
A = 0xAA;
do {} while(0);
A = 0x55;
}
viene ottimizzato a tal punto che ... lascia SOLO l'assegnazione ad A del valore 0x55
92: 85 e5 ldi r24, 0x55 ; 85
94: 90 e0 ldi r25, 0x00 ; 0
96: 90 93 01 01 sts 0x0101, r25
9a: 80 93 00 01 sts 0x0100, r24
9e: 08 95 ret
... non male ![]()
Guglielmo
Vedi, non si finisce mai di imparare :).
... Anche a non sottovalutare mai GCC! ![]()
SukkoPera:
... Anche a non sottovalutare mai GCC!
![]()
Guglielmo
@sukkopera questo non toglie il fatto che l'hai scritta malissimo!
#define ARDUINO_DEBUG 1
#if ARDUINO_DEBUG == 1
#define dbg_init(BR) Serial.begin( BR )
#define dbg_print(args...) Serial.print( args )
#define dbg_println(args...) Serial.println( args )
#else
#define dbg_init(BR)
#define dbg_print(args...)
#define dbg_println(args...)
#endif
per gli amanti della printf
#define dbg_printf(MSZ,FORMAT,args...) ({ char __buf__[MSZ]; snprintf(__buf__,MSZ,FORMAT, ##args); Serial.print(__buf__); })
che poi si usa:
dbg_printf(40, "ciao mondo %d\n", 12345);
Ah sì? Tralasciando le differenze sui nomi delle macro (ovviamente questione di gusti, eccetto per NDEBUG che non è un nome scelto a caso, bensì uno già utilizzato in C, dai un'occhiata a assert.h quando non sai cosa fare), supponi di avere qualcosa del genere:
if (a < 360)
fai_qualcosa (a);
else
dbg_println ("Valore inatteso di a");
fai_altro ();
In questo caso, disattivando il debug se fai come ho detto io funzionerà tutto correttamente, se fai come dici tu invece succederà qualcosa di spiacevole.
EDIT: No, la soluzione di vbextreme funziona correttamente anche in questo caso. Per i motivi per cui può essere meglio usare la mia soluzione vedasi post #28.
per fare del debug un pò piu eccitante:
#define dbg(MSZ, F, args...) ({ char __buf__[MSZ]; snprintf(__buf__, MSZ, __FILE__ ":[%u] %s() $ " F "\n", __LINE__, __FUNCTION__, ##args ); Serial.print(__buf__); })
#define asserts(X) ({ if ( X ){;} else { char __buf__[50]; snprintf(__buf__, 50, __FILE__ ":[%u] assertion fail\n", __LINE__); Serial.print(__buf__); while(1);}})
sukkopera non ci avevo pensato....
hai comunque messo i ; che non ci volevano.
Su questo hai ragione, correggo subito!
vbextreme:
hai comunque messo i ; che non ci volevano.
@vb com'e' il titolo di quel famoso libro su cui hai letto questa serie di "ottimizzazioni" ?
non trovo il thread dove lo indicavi ^-^
Parli di "Obfuscated C ad other Mysteries" di "Don Libes", ISBN 0-471-57805-3 ? ![]()
Guglielmo
non è solo quello.
libri