Variabili modificate da interrupt

Una domanda sulle variabili modificate dai gestori di interrupt.

Nel mio programma ho una variabile del tipo unsigned long (quindi 32 bit) che tiene il conteggio di un encoder, quindi questa viene modificata dai gestori di interrupt dei pin ai quali sono collegate le fasi dell’encoder stesso. Ovviamente è dichiarata come variabile volatile.

La domanda è questa: quando accedo in lettura a tale variabile devo prevedere che sia strutturata come una funzione atomica, ovvero devo disabilitare gli interrupt prima di leggerla per poi riattivarli dopo, o non serve? Mi viene il dubbio in quanto il dato è su 32 bit, quindi sono necessari 4 cicli macchina per accedere a tale dato.

Se accedi in lettura esternamente agli interrupt sarebbe sempre meglio incapsulare la lettura in una porzione di codice che:

  1. disattivi gli interrupt → funzione cli()
  2. legga la variabile
  3. riattivi gli interrupt → funzione sei()

Questo per evitare che la variabile venga letta contemporaneamente ad un aggiornamento eseguito dall’interrupt.

Perfetto, esattamente quello che volevo sapere. Grazie mille.

Mi viene il dubbio in quanto il dato è su 32 bit, quindi sono necessari 4 cicli macchina per accedere a tale dato.

Temo che sono significativamente molto di piú cicli macchina.

parlando teoreticamnete. una volta letto i 4 Bit cons ne fai? non devi memorizzarle in qualche altro posto?. Ti serve anche quel tempo. Ciao Uwe

Questo per evitare che la variabile venga letta contemporaneamente ad un aggiornamento eseguito dall'interrupt.

Questo per evitare che durante la lettura il puntatore PC debba saltare alla routine di interrupts lasciando il valore della variabile che hai letto troncato, sempre che questa operazione non sia di base atomica, e credo proprio non lo sia.

Nella doc di avr-libc ci sono alcune macro ma non so in che contesto si debbano usare, magari e cli e sei prendono tempo per essere eseguite allore quelle macro potrebbero essere la soluzione, ma non ho indagato sul loro funzionamento.

Ciao.

uwefed:

Mi viene il dubbio in quanto il dato è su 32 bit, quindi sono necessari 4 cicli macchina per accedere a tale dato.

Temo che sono significativamente molto di piú cicli macchina.

parlando teoreticamnete. una volta letto i 4 Bit cons ne fai? non devi memorizzarle in qualche altro posto?. Ti serve anche quel tempo.
Ciao Uwe

I cicli critici sono soltanto 4, cioè quelli necessari a copiare sui registri il valore dalla ram. Se mi ricordo bene non è possibile effettuare confronti fra registri e locazioni di memoria ram, quindi quando deve essere eseguito un confronto vengono copiate entrambe le variabili su registri (ed è solo questa la fase critica) e poi effettuate il resto delle operazioni.

MauroTec: Nella doc di avr-libc ci sono alcune macro ma non so in che contesto si debbano usare, magari e cli e sei prendono tempo per essere eseguite allore quelle macro potrebbero essere la soluzione, ma non ho indagato sul loro funzionamento.

Le macro a cui ti riferisci servono per rendere atomiche le routine di interrupt in modo che non siano interrompibili da altri interrupt. E' la condizione di default, quando cioè si crea una routine di intercettazione di un interrupt il compilatore la "isola" in questo blocco atomico. Se poi vai ad indagare a fondo, vedi che l'isolamento viene fatto proprio con cli e sei :D

Le macro a cui ti riferisci servono per rendere atomiche le routine di interrupt in modo che non siano interrompibili da altri interrupt. E' la condizione di default, quando cioè si crea una routine di intercettazione di un interrupt il compilatore la "isola" in questo blocco atomico.

Ho avuto una reminescenza, allora di default le ISR non sono interrompibili da altri eventi (interrupt) quindi una volta "entrati" nella ISR, l'unico modo per uscire è aspettare che arrivi alla fine della routine stessa, durante l'esecuzione la mcu è sorda. Mentre è possibile impostare le ISR in modo che possano essere interrotte da altri eventi. Mi pare che c'è anche il modo di specificare che quella ISR non ritorna e credo si possa fare anche per le funzioni semplici, come utilizzarle però riguarda la progettazione software.

Ciao.

Sì, è così. Le ISR sono di default atomiche, per renderle interrompibili da altri INT devi specificarlo esplicitamente. http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html http://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html

Sul fatto che non ritornino, non so dirti. Non sapevo di questa possibilità