Ah sì.
Beh, sarebbe più corretto dire che il linguaggio di programmazione di Arduino è il C/C++ con un set di librerie personalizzate basate su quelle di Wiring che viene definito core.
Janos:
Purtroppo mi sa che la delete non libera la memoria allocata. Ho provato questo codice:
a vedere quell'output sembra che la new funziona solo la prima volta... secondo me ti stai scontrando con la frammentazione della ram o qualcosa di simile tipo lazy garbage collection, poi so che la new e la delete in realtà al loro intern chiamano malloc() e free(), che non so come sono implementate
Ma infatti mi sembrava strano che funzionasse correttamente, in fondo Arduino non riesce a gestire lo heap...
Risultato: tolte tutte le new/delete... =)
ma guarda che credo che funzioni correttamente, è solo che non funziona così linearmente come crediamo... credo.
Beh, sarebbe più corretto dire che il linguaggio di programmazione di Arduino è il C/C++ con un set di librerie personalizzate basate su quelle di Wiring che viene definito core.
Scusate, forse son confuso.
Ma per me è difficile capire cosa l'IDE ingloba (a livello di librerie) nel programma eseguibile scaricato poi su Arduino.
Ho provato (con scarso successo, non fa il build) ad usare codeblock (bello come editor) e lì ho notato che un "progetto" includerebbe una serie di librerie dette "core".
Mi sembra che l'operazione di includere alcune librerie core, l'IDE Arduino ufficiale lo "nasconde". Ovvero non vedo da qualche parte quali librerie include in "automatico".
Questo "core"+"wiring" è quello che è stato citato più sopra come framework?
Il codice per la implementazione di new e delete si trova nel core lib e i file da visionare sono "new.cpp" e "new.h".
Segue il pezzo iniziale di new.cpp
#include <new.h>
void * operator new(size_t size)
{
return malloc(size);
}
void operator delete(void * ptr)
{
free(ptr);
}
Come si vede si fa ricorso alla libreria standard C e se non funziona l'operatore delete neanche la funzione "free" dovrebbe funzionare.
Prova con qualcosa di più complesso di un intero, come una struttura complessa, sopratutto referziarla cioè usarla in qualche modo è fondamentale perchè altrimenti credo che ci siano ancora possibilità di ottimizzazione da parte del compilatore, basterebbe salvare un dato di valore sconosciuto al tempo di compilazione come ad esempio la lettura ADC0.
@nid69ita
Anche per me è stato difficile capire e c'è voluto tempo, specie perchè cercavo di trovare l'implementazione di wiring che non ho trovato, o meglio ho trovato un modo di agire inconsueto che ha il suo perchè di esistere, cioè ha dei vantaggi e come ogni cosa dei svantaggi.
Sul codice sorgente agisce un preprocessore interno all'ide Arduino, quindi scritto in java, che fa alcune cose, sulle quali non ho informazioni recenti e quindi predetele con le pinze. Il preprocessore java incorpora tutti i file sorgenti in un unico grande file, in più dovrebbe sistemare anche la dichiarazione di alcune funzioni. Quanto detto vale solo per i sorgenti con l'estensione .cpp, mentre per quelli con estensione .c .s vengono compilati in file oggetto ".o".
Il file che accorpa più sorgenti viene compilato e si produce un file oggetto ".o". Il core lib viene compilato e tutti i moduli oggetto vengono archiviati in una libreria statica ".a", in questa fase viene chiamato il linker g++ per collegare tutti i file oggetto in un unico file eseguibile in formato ".elf" tipico di sistemi unix like, che poi viene trasformato in formato intel hex ad opera di objcopy che appartiene al pacchetto binutils.
Per vedere i programmi invocati dall'IDE devi abilitare la modalità verbose.
Quello che segue è ciò che accade quando si compila l'esempio ArduinoISP.
/home/mauro/bin/arduino-1.0.1/hardware/tools/avr/bin/avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/variants/standard /tmp/build4046947270294740742.tmp/ArduinoISP.cpp -o /tmp/build4046947270294740742.tmp/ArduinoISP.cpp.o
ArduinoISP.cpp: In function ‘void universal()’:
ArduinoISP.cpp:312: warning: unused variable ‘w’
ArduinoISP.cpp: In function ‘int avrisp()’:
ArduinoISP.cpp:584: warning: no return statement in function returning non-void
ArduinoISP.cpp:584: warning: control reaches end of non-void function
/home/mauro/bin/arduino-1.0.1/hardware/tools/avr/bin/avr-gcc -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/variants/standard /home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino/wiring_shift.c -o /tmp/build4046947270294740742.tmp/wiring_shift.c.o
/home/mauro/bin/arduino-1.0.1/hardware/tools/avr/bin/avr-gcc -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/variants/standard /home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino/wiring_digital.c -o /tmp/build4046947270294740742.tmp/wiring_digital.c.o
/home/mauro/bin/arduino-1.0.1/hardware/tools/avr/bin/avr-gcc -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/variants/standard /home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino/wiring_pulse.c -o /tmp/build4046947270294740742.tmp/wiring_pulse.c.o
/home/mauro/bin/arduino-1.0.1/hardware/tools/avr/bin/avr-gcc -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/variants/standard /home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino/WInterrupts.c -o /tmp/build4046947270294740742.tmp/WInterrupts.c.o
/home/mauro/bin/arduino-1.0.1/hardware/tools/avr/bin/avr-gcc -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/variants/standard /home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino/wiring_analog.c -o /tmp/build4046947270294740742.tmp/wiring_analog.c.o
/home/mauro/bin/arduino-1.0.1/hardware/tools/avr/bin/avr-gcc -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/variants/standard /home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino/wiring.c -o /tmp/build4046947270294740742.tmp/wiring.c.o
Nota che ho dovuto troncare il post perchè superava i 9500 caratteri.
/home/mauro/bin/arduino-1.0.1/hardware/tools/avr/bin/avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/variants/standard /tmp/build4046947270294740742.tmp/ArduinoISP.cpp -o /tmp/build4046947270294740742.tmp/ArduinoISP.cpp.o
Quello sopra è una riga di comando completa, dove si vede che viene invocato avr-g++ (compilatore c++) che accompagna l'ide, quindi non viene usato il compilatore (in generale non viene usata tutta la toolchain installata sul sistema) che io ho installato sul sistema.
Si vede che seleziona il microcontroller atmega328p (-mmcu=atmega328p).
Si vede la definizione volante della macro F_CPU=16000000L. Nota che ci sono altre definizioni volanti -D.
Si vede che il percorso di ricerca degli include con ciò che segue -I (occhio che si tratta di un i maiuscola)
Si vede che l'obbiettivo è compilare il file /tmp/build4046947270294740742.tmp/ArduinoISP.cpp.
Si vede che il file trattato dovrà chiamarsi /tmp/build4046947270294740742.tmp/ArduinoISP.cpp.o, specificato con l'opzione "-o"
ArduinoISP.cpp: In function ‘void universal()’:
ArduinoISP.cpp:312: warning: unused variable ‘w’
ArduinoISP.cpp: In function ‘int avrisp()’:
ArduinoISP.cpp:584: warning: no return statement in function returning non-void
ArduinoISP.cpp:584: warning: control reaches end of non-void function
/home/mauro/bin/arduino-1.0.1/hardware/tools/avr/bin/avr-gcc -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino -I/home/mauro/bin/arduino-1.0.1/hardware/arduino/variants/standard /home/mauro/bin/arduino-1.0.1/hardware/arduino/cores/arduino/wiring_shift.c -o
Più avanti si vede la compilazione del core lib e tutte le fase successive.
Ora si può capire che il core lib e tutto il sorgente viene compilato per ogni microcontroller e quindi è specifico per quel microcontroller, quindi dipendente
oltre che dall'architettura (AVR) anche dalla sigla del microcontroller. Se il core non fosse compilato ad ogni sketch si dovrebbe avere sul sistema un libcore.a per ogni microcontroller con il quale ho intenzione di sviluppare il mio sketch, questo è un vantaggio? Anche si e forse no dipende tutto da dove guardi il mondo.
Spero che le informazioni che ho fornito ti siano utili e tu possa trovare il tempo per approfondire.
Ciao.
@Edit:
Ho solo corretto qualche errore di distrazione.
Certamente, ora è più chiaro. Forse ho anche capito come far compilare code-block, per il quale su altri siti ho letto bisogna fargli già trovare gli .o compilati.
Mi vien da pensare che il framework ha una sua main() che inzializza il sistema e che in realtà setup() e loop() son funzioni chiamate da questo main.
La setup() una volta sola, la loop() di continuo. (semplificando molto).
Grazie per le info.
nid69ita:
Certamente, ora è più chiaro. Forse ho anche capito come far compilare code-block, per il quale su altri siti ho letto bisogna fargli già trovare gli .o compilati.Mi vien da pensare che il framework ha una sua main() che inzializza il sistema e che in realtà setup() e loop() son funzioni chiamate da questo main.
La setup() una volta sola, la loop() di continuo. (semplificando molto).Grazie per le info.
Nella cartella "..\hardware\arduino\cores\arduino" c'è un file che si chiama main.cpp, lo riporto qui:
#include <Arduino.h>
int main(void)
{
init();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}