Os seguintes trechos são do código-fonte da 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();
}
A pergunta: se o cronômetro já estiver em execução, e o programa principal chamar attachInterrupt()
, o temporizador poderá ocorrer durante a atribuição do ponteiro de função isrCallback = isr;
? Então, com um tempo de sorte, o Timer1.isrCallback();
ponteiro de função consistiria em parte no antigo e em parte no novo endereço, fazendo com que o ISR pulasse para um local falso?
Suponho que possa ser esse o caso, pois os ponteiros de função certamente são maiores que 1 byte e o acesso a dados de> 1 byte não é atômico. As soluções possíveis podem ser:
- Sempre ligue
detachInterrupt()
para garantir que o cronômetro não esteja funcionando antes de chamarattachInterrupt()
, ou seja, esclareça os documentos do Timer1. - Ou modifique o Timer1, desativando temporariamente o estouro de temporizador interrompe temporariamente antes de
isrCallback = isr;
Isso faz sentido ou há algo nas Timer1
fontes ou atribuições de ponteiros de função que eu perdi?