I seguenti frammenti provengono dal codice sorgente della libreria TimerOne :
// TimerOne.h:
void (*isrCallback)();
// TimerOne.cpp:
ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt
{
Timer1.isrCallback();
}
// TimerOne.cpp:
void TimerOne::attachInterrupt(void (*isr)(), long microseconds)
{
if(microseconds > 0) setPeriod(microseconds);
isrCallback = isr; // register the user's callback with the real ISR
TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit
resume();
}
La domanda: se il timer è già in esecuzione e il programma principale chiama attachInterrupt()
, potrebbe verificarsi l'interruzione del timer durante l'assegnazione del puntatore a funzione isrCallback = isr;
? Quindi, con un tempismo fortunato, il Timer1.isrCallback();
puntatore a funzione consisterebbe in parte nel vecchio e in parte nel nuovo indirizzo, causando il salto ISR in una posizione fasulla?
Suppongo che potrebbe essere così, dal momento che i puntatori a funzione sono certamente più ampi di 1 byte e l'accesso a dati> 1 byte non è atomico. Le possibili soluzioni alternative potrebbero essere:
- Chiamare sempre
detachInterrupt()
per assicurarsi che il timer non sia in esecuzione, prima di chiamareattachInterrupt()
, ad esempio chiarire i documenti Timer1. - In alternativa, modificare Timer1, disabilitando temporaneamente le interruzioni di overflow del timer poco prima
isrCallback = isr;
Ha senso o c'è qualcosa nelle Timer1
fonti o nelle assegnazioni di puntatori a funzioni che mi sono perso?