Наступні фрагменти з вихідного коду бібліотеки 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();
}
Питання: якщо таймер вже запущений, і основна програма викликає attachInterrupt()
, чи може там відбутися перерва таймера під час призначення функціонального вказівника isrCallback = isr;
? Тоді, із вдалим терміном, Timer1.isrCallback();
покажчик функції складеться частково від старої, а частково від нової адреси, спричиняючи перехід ISR до фіктивного місця?
Я припускаю, що це може бути так, оскільки покажчики функцій, безумовно, ширші за 1 байт, а доступ до даних> 1 байт не є атомним. Можливими шляхами вирішення можуть бути:
- Завжди дзвоніть,
detachInterrupt()
щоб переконатися, що таймер не працює, перед викликомattachInterrupt()
, тобто уточнюйте документи Timer1. - Або змінити Timer1, відключення переповнення таймера тимчасово переривається безпосередньо раніше
isrCallback = isr;
Чи має це сенс, чи є щось у Timer1
джерелах чи присвоєннях функцій, які я пропустив?