Die folgenden Ausschnitte stammen aus dem Quellcode der TimerOne-Bibliothek :
// 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();
}
Die Frage: Wenn der Timer bereits läuft und das Hauptprogramm aufruft attachInterrupt()
, kann der Timer-Interrupt dort während der Funktionszeigerzuweisung auftreten isrCallback = isr;
? Dann Timer1.isrCallback();
würde der Funktionszeiger mit etwas Glück teilweise aus der alten und teilweise aus der neuen Adresse bestehen, was dazu führen würde, dass der ISR zu einem falschen Ort springt?
Ich nehme an, dass dies der Fall sein könnte, da Funktionszeiger sicherlich breiter als 1 Byte sind und der Zugriff auf Daten mit> 1 Byte nicht atomar ist. Mögliche Problemumgehungen könnten sein:
- Immer anrufen
detachInterrupt()
an, um sicherzustellen, dass der Timer nicht läuft, bevor Sie anrufenattachInterrupt()
, dh klären Sie die Timer1-Dokumente. - Oder ändern Sie Timer1, indem Sie die Timer-Überlauf-Interrupts kurz zuvor vorübergehend deaktivieren
isrCallback = isr;
Ist dies sinnvoll oder gibt es etwas in Timer1
Quellen oder Funktionszeigerzuweisungen, das ich verpasst habe?