Les extraits suivants proviennent du code source de la bibliothèque 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 question: si la minuterie est déjà en cours d'exécution et que le programme principal appelle attachInterrupt()
, l'interruption de la minuterie pourrait-elle s'y produire pendant l'affectation du pointeur de fonction isrCallback = isr;
? Ensuite, avec un timing chanceux, le Timer1.isrCallback();
pointeur de fonction serait composé en partie de l'ancienne et en partie de la nouvelle adresse, provoquant le saut ISR vers un faux emplacement?
Je suppose que cela pourrait être le cas, car les pointeurs de fonction sont certainement plus larges que 1 octet, et l'accès aux données> 1 octet n'est pas atomique. Les solutions de contournement possibles pourraient être:
- Appelez toujours
detachInterrupt()
pour vous assurer que le minuteur ne fonctionne pas, avant d'appelerattachInterrupt()
, c'est-à-dire clarifiez les documents Timer1. - Ou, modifiez Timer1, désactivant temporairement les interruptions de dépassement de minuterie juste avant
isrCallback = isr;
Est-ce que cela a du sens, ou y a-t-il quelque chose dans les Timer1
sources ou les affectations de pointeurs de fonction que j'ai manqué?