Questa demo mostra ciò che sono riuscito a fare con la libreria SerialCmd e che non pensavo si riuscisse a fare. Comincio a pensare che siano tante le possibili applicazioni di questa libreria ma a me è venuta la malsana idea di permettere all'utente di potere scrivere in ram un valore ad un indirizzo di memoria scelto in modo arbitrario. Malsana perché potenzialmente posso scrivere nel registro SREG azzerandolo e come risultato arduino si pianta.
Tuttavia ci sono risvolti positivi, come ad esempio il comando DMEM che mostra su seriale il memory dump e osservandolo si riesce a scoprire a che indirizzo di memoria c'è il ring buffer della seriale. Altra informazione che si può ricavare riguarda le string literal che sono presenti in ram se non si usa PROGMEM o la macro F("") di arduino. In sostanza tanta è la valenza didattica di questa demo che ciò sembra malsano invece offre potenza di controllo in mani esperte.
C'è anche il rischio di bruciare un pin di arduino, modificando il registro DDR. Se a questo pin fosse connessa una resistenza di pull-up e impostiamo il registro DDR per configurarlo come OUTPUT e poi impostiamo il pin LOW avremo un assorbimento di corrente in relazione alla resistenza di pull-up, se questa fosse di valore tanto bassa da superare i 40mA massimi erogabili, il pin di arduino si guasterebbe.
PS:Ora si torna a leggere la sdk della pi-pico.
Sempre didatticamente sarebbe interessante potere osservare cosa accade alla ram quando si frammenta. Specie alle prese con String(), ma
anche malloc. Se ci arrivate voi prima di me fatemelo sapere.
Ammesso che il microcontrollore abiliti la resistenza di pull-up con il pin impostato come uscita e che non porti, invece, semplicemente l'uscita a livello alto, le resistenze di pull-up sono circa 20kohm, quindi la massima corrente che può scorrere con 5V è circa 250uA!
Non ho fatto riferimento a internal pull-up e non posso sapere se un utente ha una scheda con connesso un circuito e quale circuito. Resta il fatto che modificare la RAM attraverso indirizzi di memoria non è cosa chiara ed esplicita come per pinMode, pinMode che è stato scritto dall'utente, ma io con questo demo permetto di modificare DDR, PIN, PORT ecc in modo poco consapevole nel mentre che l'applicazione gira. Considera wreg,0x5e ma io scrivo wreg,0xe5 già questo potrebbe fare la differenza e trasformare un board funzionante in una danneggiata. Se avessi lavorato su linux avresti provato il brivido lungo la schiena dopo avere dato il comando su. Da adesso puoi fare danni volontariamente che involontariamente ed e bene informare di ciò l'utente.
Lo storico dei comandi costa, anche salvare l'ultimo costa un buffer di n lunghezza. Quindi lo storico dei comandi rimane nel serial monitor, per fare ciò ho modificato il metodo read() per fargli stampare mp_buffer, il risultato è questo:
Beh, una volta che con un comando da seriale puoi attivare una funzione, per di più passandogli dei parametri ... le possibilità sono praticamente infinite e ci si può sbizzarrire anche se ... la cosa è per lo più a fini didattici e di studio, che pratici
Nel caso di esempio si, ma aspettiamo qualche applicazione pratica, che so un automatismo che usa SerialCmd come shell e all'avvio ti chiede la password e poi fai logout ecc.
Il mio maggiordomo telegram si basava su pricipi simili
Ma non lo ho sviluppato molto, ho csmbiato passatempo...
La particolarità del maggiordomo era che anche alcuni dei "comandi" risiedevano in memoria di massa...
Sotto forma di coppia
nome:lista comandi elementari
Se vi ricordate "la mia seconda volta in c++" il formato è quello
E una versione di "grep non vuol dire greppia" che legga anche le strighe da cercare da memoria di massa non è difficile da creare...
Ottimo, lo avevo letto ma pensavo ci volesse ancora tempo (e infatti @standardoil aspetta ancora che arrivi il modulo. Ma pensi sempre a comandi di alto livello? no perché i 32 registri r0÷r31 sono in ram, non è che vorresti il comando r0,0x31?
Allora la chiamata a funzione tramite indirizzo è comodissima (e rapida) basta scrivere nel file (accorciando il comando CALL in cl) cl,0xdd5 cl,0xadd ecc. Ovviamente per quelle funzioni che non prendono argomenti, come set_LEDON.
Osservando il datasheet del 328 a pag.621 c'è il sommario dei registri. Ok alcune porzioni di ram sono riservate, ma cosa si intende? Riservate per versioni della MCU, oppure sono non documentate e attualmente servono a fare funzionare la MCU?
Io comunque ci scrivo e leggo ciò che ho scritto, quindi funziona la RAM. da c7 a ff ci sono 56 byte e altri 35 più avanti.
Se osservi il datasheet del ATmega328PB ti accorgi che, parecchi di quei registri che non sono usati, ma comunque marcati riservati, su ATmega328P, sono invece utilizzati nel ATmega328PB.
Normalmente quando c'è scritto riservato è un qualche cosa che loro pensano di usare per qulche altra cosa futura (es. una revisione del chip) e che quindi NON vanno usati perché, in futuro, li potrebbero usare loro (così come è avvenuto con il ATmega328PB).
Dove si vede che nel comando manca la F. Il risultato nel serial monitor è il seguente:
INFO: Program running ...
Alcuni comandi non sono stati registrati. err:1
>LEDBL,200
OK
Comando sconosciuto. err:2
Comando sconosciuto. err:2
Comando sconosciuto. err:2
Non me lo aspettavo, blinka sempre e ovviamente dovrebbe chiamare set_LEDOF() che contiene questa assegnazione:
Si che le ricordo e ti ho riletto da recente. A me piacerebbe provassi la demo e scrivessi tu un paio di comandi:ls, cat, rm, mkdir ecc. Prima o poi lo faccio io perché lo trovo divertente.
PS: apropos manca il comando sysinfo mo lo scrivo.
Ciao.
Attenzione alla ricorsione. Il comando lop chiama la funzione
uf_loop() mostrata di seguito:
void uf_loop() {
Serial.println(SPL, HEX); // stampa il puntatore allo stack
bool state = !digitalRead(LED_BUILTIN);
digitalWrite(LED_BUILTIN, state );
delay(1000);
mySerCmd.ReadString("lop"); // chiama se stessa
}
Riducendo il delay a 1ms si sfonda lo stack in breve tempo e il programma riparte e torna usabile.