Quando si utilizza l'interrupt di un processore come quello della scheda Arduino/Genuino, si usa dire che il programma salta immediatamente alla procedura di gestione del'interrupt.
Ovviamente "immediato" può significare zero secondi ma non zero microsecondi.
Qui si prova a vedere quanto dura il passaggio dall'esecuzione del programma ordinario, quello del loop, a quello della procedura di interruzione.
Per fare questo si monta un circuito di prova con (vedi schema):
- un generatore di segnali che invia onde quadre al pin D2 della scheda Arduino/Genuino
- una scheda Arduino/Genuino Uno a 16MHz che "sorveglia" il pin D2 per avviare la procedura di interrupt che, all'occorrenza, produce una variazione di stato sul pin D9
- un oscilloscopio che rileva la tensione sul pin D2 e la tensione sul pin D9 permettendo il confronto temporale.
Viene caricato uno sketch che con il loop mantiene basso il valore del pin D9 fino a quando viene elaborata la procedura di interrupt nel qual caso il valore del pin D9 diventa alto.
Appena la procedura di interrupt è stata completata, il programma ritorna al loop che abbassa subito il valore del pin D9.
Si possono misurare
a- il ritardo tra impulso sul pin D2 che genera l'interrupt sul fronte di discesa e l'esecuzione della procedura che porta alto il valore del pin D9
b- il tempo che il processore impiega per tornare all'esecuzione del loop dopo aver terminato la procedura (la quale si esaurisce appena inviata l'istruzione di porre "alto" il pin D9).
Caso con un impulso, rapidissimo
Lo sketch viene ridotto all'essenziale per generare l'interrupt senza variabili o altro che possa allungare i tempi di esecuzione. Credo che essere più rapidi di così non sia possibile.
La prova è stata effettuata con il generatore di impulsi a 1kHz.
I risultati sono illustrati con l'oscillogramma qui sotto dove risulta, con una base tempi di 2µs/div, un ritardo pari a 7,5µs ed una durata dell'impulso è di 3,5µs.
L'impulso termina nel momento in cui il loop principale esegue l'istruzione di scrittura "LOW" del pin D9 dopo che è terminata l'esecuzione della procedura di interrupt.
Prove a frequenza maggiore fino a 40kHz non hanno mostrato variazioni sui tempi di ritardo misurati.
Nota: una frequenza di 40kHz di invio di impulsi di interruppt è possibile solo perchè la procedura di gestione dello stesso è brevissima visto che ha una durata che non supera i 16µs.
Il ritardo dell'impulso è dovuto al fatto che nell'intervallo di tempo che intercorre tra la richiesta di interruzione e l'esecuzone della procedura occorre che il processore salvi alcuni dati per consentire la ripresa del programma principale appena la procedura è terminata. Sicuramente deve salvare il Program Counter per tornare allo stesso punto di esecuzione del programma principale appena terminata la procedura richiamata con l'interrupt.
Un aspetto emerso dall'esperimento riguarda la durata dell'impulso il cui valore deve tornare "basso" quando Arduino ritorna ad eseguire il programma principale. La durata è variabile.
Dalla fotografia, qui a destra, risulta che l'impulso arriva a ritardare un po' di più (8,2µs) e può durare anche 7,8µs (ho fotografato l'impulso più lungo).
Caso con tre impulsi
Con uno sketch leggermente diverso si aggiungono due impulsi dalla procedura di interruzione e si vede che cosa accade:
Il grafico qui sotto mostra:
1- il ritardo del primo impulso rimane costante intorno a 7,5µs mentre
2- l'intervallo di tempo che intercorre tra due operazioni di scrittura è di circa 5µs
3- l'impulso che è affetto da una durata variabile è solo l'ultimo (nota 1) e dura 59µs di cui 5µs solo per la scrittura, gli altri 54µs sono dovuti ad operazioni interne al processore necessarie per il ripristino dei registri interni.
Caso con tre impulsi e stampa
Con il test01c si introduce una stampa nella procedura di interrupt dopo il primo impulso.
L'esito è un ritardo tra il primo e secondo impulso che dipende dal numero di caratteri da stampare.
La durata, in questo caso, è di 110µs!
Aumentando la durata della procedura deve diminuire la frequenza massima di invio di richieste di interruzione.
Nel caso dell'esperimento, occorre abbasare di molto la frequenza del generatore di segnali per non arrivare a chiedere un'interruzione mentra si sta ancora elaborando l'interruzone precedente.
Sviluppi
Ovviamente è possibile moltiplicare le prove introducendo assegnazione di valori, calcoli o chissà cosa che costringano sia il processo principale sia la procedura di interrupt a trattare variabili e quindi ad elaborare diversamente lo stack ... non si finisce mai.
Qui, un proseguimento dell'esperimento.
note
nota 1: una ragione c'è, il ritorno al ciclo principale prevede operazioni di ripristino delle condizioni presenti nel momento della richiesta di interruzione.