Los siguientes fragmentos son del código fuente de la biblioteca 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 pregunta: si el temporizador ya se está ejecutando y el programa principal llama attachInterrupt()
, ¿podría ocurrir la interrupción del temporizador allí durante la asignación del puntero de función isrCallback = isr;
? Entonces, con suerte, el Timer1.isrCallback();
puntero de la función consistiría en parte en la dirección anterior y en la nueva, lo que provocaría que el ISR salte a una ubicación falsa.
Supongo que este podría ser el caso, ya que los punteros de función son ciertamente más anchos que 1 byte, y acceder a datos de> 1 byte no es atómico. Las posibles soluciones podrían ser:
- Siempre llame
detachInterrupt()
para asegurarse de que el temporizador no se esté ejecutandoattachInterrupt()
, es decir, aclare los documentos de Timer1. - O bien, modifique Timer1, deshabilitando las interrupciones de desbordamiento del temporizador temporalmente justo antes
isrCallback = isr;
¿Tiene sentido o hay algo en las Timer1
fuentes o en las asignaciones de puntero de función que me he perdido?