以下代码片段来自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
我错过了源代码或函数指针分配中的某些内容?