mercoledì 2 febbraio 2022

arduino wokwi contenuto della ram (advanced)

 Arduino Uno e la RAM

La scheda Arduino Uno monta la MCU ATmega328p equipaggiata con solo 2048 celle di memoria da un byte, detto in altri termini, 2 KiB di RAM.

Potrebbe essere interessante e istruttivo visualizzare il contenuto della RAM cella per cella, potrebbe anche tornare utile per costatare che la string literal specificata con la macro F("la mia string literal") funzioni correttamente. Principalmente a me interessa l'aspetto istruttivo ma devo dire che non ho scritto la funzione seguente con questa finalità, mi sono reso conto che il codice è didatticamente valido e quindi ho deciso di scrivere questo articolo.

Cosa stampa la funzione?

La funzione inizia a stampare il contenuto di ogni cella di memoria a partire dall'indirizzo 0x100 (256) così come specificato nel datasheet della MCU. L'ultima cella di memoria allora si trova all'indirizzo 0x8FF (2303) valore calcolato così:

    256 + 2047 = 2303 in decimale. 

    La stessa cosa ma espressa in esadecimale:  0x100 +0x7FF = 0x8FF.

Qui a seguire il contenuto stampato sul terminale seriale del simulatore WokWi:

addr	0123456789ABCDEF
100	..e.......~.....
110	..<.............
120	].\........[Maur
130	oTec Software], 
140	millis() vale.%s
150	 %09ul .gCounter
160	 = .d?...L......
170	..              
180	                
190	                
1A0	................
1B0	................
1C0	................
1D0	................
1E0	................
1F0	..............0.
200	................
210	.1F0............
220	...0..200.......
230	...........210r.
240	...g............
250	..............@.
260	Px.....         
270	       .........
280	................
290	................

La funzione che permette questo output si chiama showRam() e la mostro qui di seguito:

void showRam() {
// spazzoliamo tutta la ram cella per cella.
// come da datasheet inizio da 0x100
const char *ptrToRam = (char*)0x100;
// mi servono 16 caselle da 0÷15
uint8_t counter15 = 15;
Serial.print(F("addr\t0123456789ABCDEF"));
// Nota per il 328 RAMEND vale 2303
for (uint16_t t=0; t<=(RAMEND-0x100); t++) {
if (counter15 == 15) {
Serial.print("\n");
Serial.print((uint16_t)ptrToRam, HEX);
Serial.print("\t");
}
if ((counter15 > -1) && (counter15 < 16)) {
// vogliamo vedere i caratteri quindi
// dal puntatore con * otteniamo il puntato
// e poi il cast a char
char b = (char)*ptrToRam++;
// se b non è rappresentabile
// stampo il punto ".".
if ((b < 32) || (b > 126)) {
Serial.print(".");
} else {
Serial.print(b);
}
}
counter15--;
counter15 = counter15 % 30;
}
Serial.println();
}
 
Userò ptrToRam++ per passare su ogni cella di memoria attraverso il suo indirizzo. Al termine del for ptrToRam punterà all'ultimo indirizzo valido di valore 0x8FF. Come si può vedere nell'output occorre stampare gli indirizzi uno per riga, ogni indirizzo vale indirizzo precedente più F più 1, così avremo: 
 
    0x100, 0x110, 0x120 ecc. 0x120 + F = 12F + 1 = 130.
 
Uso un contatore counter15 inizializzato a 15. Se conter15 == 15 stampo un NL seguito dal valore del puntatore ptrToRam espresso in esadecimale. Per terminare stampo un "\t" TAB per allineare il tutto.
 
    if (counter15 == 15) {
Serial.print("\n");
Serial.print((uint16_t)ptrToRam, HEX);
Serial.print("\t");
}

Ora non resta che stampare il contenuto delle 16 celle di memoria, ma se il valore di una cella è un byte non rappresentabile (cioè ad esso non è associato un simbolo come A, B, C) allora stampo solo un punto. Di ciò si occupa la seguente if:

    if ((counter15 > -1) && (counter15 < 16)) {
char b = (char)*ptrToRam++;
if ((b < 32) || (b > 126)) {
Serial.print(".");
} else {
Serial.print(b);
}
}

Per terminare decremento conter15 ad ogni ciclo fino che arriva a zero e riparte da 15.

Provando la funzione in un vostro programma non troverete in RAM la string literal "addr\t0123456789ABCDEF" grazie alla macro F(""). 

Chi volesse provare la funzione rapidamente può cliccare qui per eseguire un programma demo sul simulatore online WokWi. La demo in questione fa scorrere del testo in una riga del display impiegando una classe di nome MTScrollText ma di questa se ne parlerà in altra occasione.

Per questo articolo è tutto, buon divertimento con WokWi ed in generale con la vostra board preferita.


Licenza Creative Commons
Quest'opera è distribuita con Licenza Creative Commons Attribuzione 4.0 Internazionale