Arduino / Programmazione · 24 ottobre 2012 0

Come sapere l’occupazione di RAM del proprio sketch

Molti dei moderni microcontrollori sono basati sull’architettura Harvard, vale a dire separano la memoria che contiene il programma, solitamente di tipo non volatile (Flash), dalla memoria che contiene i dati, memoria di tipo volatile (SRAM). Siccome il quantitativo di questa memoria è ridotto, può succedere di saturarla completamente anche con sketch che occupano una piccola percentuale della memoria principale dove risiede il codice dell’utente.

Esistono però un paio di metodi che permettono di sapere quanta memoria RAM utilizza il nostro programma, sia prima che venga caricato sia durante l’esecuzione.

Partiamo dall’inizio. A chi è abituato a programmare sui computer questa cosa può suonare strana: su un comune PC, infatti, sia il programma che i dati risiedono nella stessa RAM. Se ho un sistema con 100 kB di memoria ed il mio programma ne occupa solo 10, so che a disposizione dei dati ho 90 kB. Se ho un programma di 90 kB, so che per i dati ne ho soltanto 10. Questa architettura si dice di von Neumann.

Sulle architetture Harvard invece non è così: se ho ad esempio un microcontrollore con 32 kB di Flash e 2 kB di RAM (come nel caso dell’Atmega328 dell’Arduino UNO), posso avere uno sketch che occupa solo 1 kB di Flash e saturare lo stesso tutta la RAM semplicemente dichiarando un array.

La saturazione della RAM porta a comportamenti strani del microcontrollore dato che i dati delle variabili iniziano ad essere recuperati a caso nella memoria, portando ad esempio a visualizzazioni di caratteri strani su un display LCD, alla stampa di dati senza senso sulla seriale oppure al blocco stesso dell’esecuzione del codice. La saturazione della RAM è anche un problema che spesso non viene diagnosticato correttamente: l’utente, spesso, pensa che i motivi di queste anomalie possano risiedere nel suo codice oppure nello stesso circuito.

Fortunatamente esistono alcuni sistemi per poter valutare il consumo di memoria RAM e capire se i sintomi che si manifestano possono dipendere dal suo consumo. Il primo è di tipo non invasivo e serve a misurare la memoria allocata staticamente. Si tratta di utilizzare uno strumento software messo a disposizione dalla toolchain Avr, avr-size. Questo programma restituisce l’occupazione statica di RAM analizzando lo sketch compilato, prima di farne l’upload sul microcontrollore. Non è invasivo nel senso che non si deve modificare il proprio programma, ed è uno strumento che analizza staticamente la memoria perché considera l’occupazione di RAM a “bocce ferme”: se ad esempio lo sketch crea un array dinamico e lo riempie durante l’esecuzione, avr-size fornirà un risultato non affidabile.

Il secondo metodo riguarda l’uso di una libreria denominata MemoryFree che permette di avere il consumo di memoria istantaneo, vale a dire durante l’esecuzione del programma stesso. Questo metodo è invasivo perché richiede la modifica del proprio codice, e richiede anche un sistema di comunicazione con il microcontrollore perché MemoryFree deve in qualche modo comunicare all’utente il dato e lo fa su seriale.

Il terzo metodo utilizza una piccola funzione che fa semplicemente la differenza fra l’indirizzo di inizio dell’HEAP e quello di inizio dello STACK, restituendo il numero di byte di SRAM ancora disponibili. Lo STACK e l’HEAP sono 2 strutture create e modificate continuamente durante il funzionamento del programma (le analizzeremo in un prossimo articolo).

Personalmente preferisco l’uso di avr-size per via del fatto che non devo modificare nulla né usare la seriale per ricevere i dati: un Attiny85, ad esempio, non ha la seriale e per spedire dei dati devo usare una sua emulazione software, con aggravio di consumo di memoria e alterazione del valore reale. Presento comunque tutt i metodi e lascio all’utente la scelta su quale utilizzare.

Uso di “avr-size”

Questo comando fa parte della toolchain e si trova nella cartella /arduino-1.0.1/hardware/tools/avr/bin: si chiama “avr-size.exe” sui sistemi Windows, semplicemente “avr-size” sui sistemi Linux. Lavora sui file .elf del firmware, file che vengono creati durante la compilazione dello sketch. L’IDE di Arduino usa una cartella temporanea dove parcheggia tutti i file che genera durante la sua attività. Per sapere dove è salvato il firmware compilato, basta (IDE 1.0.1) aprire il menu “File/Preferenze” e poi mettere il segno di spunto sulla voce “Mostra output verboso durante: compilazione”. A questo punto, compilate (senza fare l’upload) il vostro sketch e vedrete che nel terminale dell’IDE apparirà una sfilza di messaggi. Quando la compilazione è terminata, scorrete alcune righe in alto e troverete un messaggio simile a questo:
/tmp/build3857425205743446753.tmp/nome_del_vostro_sketch.cpp.hex
oppure
C:\DOCUME~1\User\IMPOST~1\Temp\build3857425205743446753.tmp\nome_del_vostro_sketch.cpp.hex
a seconda che usiate un sistema Linux o Windows.

Copiate tutta la riga ad esclusione di “.hex”. Aprite adesso un terminale (su Linux) oppure la riga di comando (su Windows) e spostatevi nella cartella in cui avete avr-size. Scrivere “./avr-size” (sui sistemi Linux) o “avr-size.exe” (sui sistemi Windows), date uno spazio e poi incolalte la riga che avete copiato in precedenza, aggiungendo “.elf”, date un altro spazio e terminate inserendo “-C” (C maiuscola). Alla fine la riga deve apparire così:

./avr-size /tmp/build3857425205743446753.tmp/nome_del_vostro_sketch.cpp.elf -C

oppure

avr-size.exe C:\DOCUME~1\User\IMPOST~1\Temp\build3857425205743446753.tmp\nome_del_vostro_sketch.cpp.elf -C

Il programma restituirà in formato leggibile l’occupazione della Flash (voce “program”) e della RAM (voce “data”) permettendovi di capire se il vostro sketch consuma più delle risorse a disposizione. Facciamo l’esperimento compilando lo sketch ArduinoISP dell’IDE 1.0.1. Ecco cosa appare:


AVR Memory Usage
----------------
Device: Unknown
Program: 5438 bytes (16.6% Full)
(.text + .data + .bootloader)
Data: 482 bytes (23.5% Full)
(.data + .bss + .noinit)

Se volete eliminare il messaggio “Device: Unknown”, basta passare il tipo di microcontrollore con il parametro –mcu. Ad esempio, per l’Atmega328P, basta aggiungere “–mcu=Atmega328p”.

Libreria “MemoryFree”

Per usare questo metodo vi serve un modo per visualizzare i dati elaborati dalla libreria: il modo più semplice è quello di usare la connessione seriale e spedire i dati al computer.

Per prima cosa scaricate il pacchetto contenente la libreria che è posto alla fine di questa pagina: esso contiene la libreria ed uno sketch di esempio. Scompattate il pacchetto e copiate il suo contenuto, ad IDE chiusa, all’interno della cartella /libraries. Avviate quindi l’IDE e caricate lo sketch che volete controllare. All’inizio dello sketch inserite il seguente codice per includere la libreria:
#include "MemoryFree.h"

Adesso in un punto del vostro codice basta inserire la seguente riga:
Serial.println(freeMemory());

Essa non fa altro che spedire il valore della SRAM ancora libera, così da sapere l’occupazione in tempo reale della memoria. Ricordo che questo metodo è invasivo ed altera il consumo di SRAM dato che sia la libreria che l’uso della comunicazione seriale aumentano la memoria usata dallo sketch. Esso inoltre richiede un modo per poter comunicare all’utente il valore della memoria disponibile.

Funzione freeRam

La funzione si chiama freeRam ed è stata pubblicata per la prima volta su JeeLabs.org:

int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

Basta inserire questa funzione nel vostro sketch e richiamarla: essa restituirà un valore di tipo int che rappresenta il numero di byte di SRAM in quel momento ancora liberi – tale valore potrete stamparlo su seriale oppure visualizzarlo su un LCD.

MemoryFree
MemoryFree
MemoryFree.zip
1.5 KiB
1761 Downloads
Dettagli...