L'AVR è un'architettura RISC, quindi ha una gestione hardware piuttosto basilare degli interrupt. La maggior parte dei processori fa casino con lo stack durante gli interrupt, sebbene ci siano un paio, in particolare ARM e PowerPC, che usano metodi diversi.
In ogni caso, questo è ciò che AVR fa per gli interrupt:
Quando si verifica un interrupt, l'hardware del processore esegue questi passaggi, che non sono solo un semplice GOTO:
- Termina l'istruzione corrente.
- Disabilita il flag di interruzione globale.
- Inserisci l'indirizzo della prossima istruzione in pila.
- Copiare l'indirizzo nel vettore di interrupt corretto (in base all'interrupt che si è verificato) nel contatore del programma.
Ora a questo punto, l'hardware ha fatto tutto ciò che stava per fare. Il software deve essere scritto correttamente per non rompere le cose. In genere, i passaggi successivi sono in questo senso.
Inserire il registro di stato nello stack. (Questo deve essere fatto prima di essere modificato).
Inserire tutti i registri della CPU che saranno (o potrebbero essere) modificati nello stack. I registri che devono essere salvati in questo modo sono definiti dal modello di programmazione. Il modello di programmazione è definito dal compilatore.
Ora è possibile eseguire il codice di interruzione funzionante. Per rispondere al caso relativo alla chiamata di una funzione, fa semplicemente quello che fa sempre, spinge il valore di ritorno nello stack, quindi lo riavvia al termine. Ciò non influisce su nessuno di questi valori precedenti che abbiamo salvato nello stack fino ad ora.
- Esegui il codice di lavoro ISR.
Ora abbiamo finito e vogliamo tornare dall'interruzione. Innanzitutto dobbiamo eseguire la pulizia del software.
- Pop i registri della CPU che abbiamo inserito nel passaggio 6.
- Riporta il valore di stato salvato nel registro di stato. Dopodiché dobbiamo stare attenti a non eseguire alcuna istruzione che potrebbe cambiare il registro di stato.
Eseguire l'istruzione RTI. L'hardware esegue questi passaggi per questa istruzione:
un. Abilita il flag di interruzione globale. (Si noti che è necessario eseguire almeno un'istruzione prima che venga rispettato l'interruzione successiva. In questo modo si evita che interruzioni pesanti blocchino completamente il lavoro in background.)
b. Inserisci l'indirizzo di ritorno salvato nel PC.
Ora torniamo al codice normale.
Si noti che ci sono alcuni punti in cui dobbiamo stare molto attenti, in particolare attorno al registro di stato e ai registri di salvataggio che potrebbero essere modificati. Fortunatamente se si utilizza un compilatore C, tutto questo viene gestito sotto le copertine.
Inoltre, devi guardare la profondità del tuo stack. In qualsiasi momento in cui gli interrupt sono abilitati, un ISR potrebbe usare più dello stack di quanto sia ovvio guardando il codice locale. Ovviamente, questo non viene fuori molto se non spingi la tua memoria al limite.
Ecco un link che descrive questo processo se si desidera un riferimento.