Следующие фрагменты взяты из исходного кода библиотеки 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
источниках или назначениях указателей на функции, которые я пропустил?