有明确记录表明,当与ISR和主程序共享全局数据时,需要声明数据volatile
以保证内存可见性(并且仅满足1字节数据;任何较大的数据都需要进行特殊安排以保证原子性) 。这里我们有很好的规则:
- 仅在ISR外部使用的变量不应是volatile。
- 仅在ISR内部使用的变量不应是可变的。
- 在ISR内部和外部使用的变量应该是可变的。
但是volatile
,当从1个以上的ISR访问变量但不与ISR共享外部变量时是否需要?例如,我有一个使用static
变量维护内部状态的函数:
void func() {
static volatile long counter; // volatile or not?
// Do stuff with counter etc.
}
可以通过两种方式调用该函数:从引脚中断和从TimerOne库:
attachInterrupt(0, func, CHANGE);
Timer1.attachInterrupt(func);
没有原子性问题,因为输入ISR时会自动禁用中断,但这volatile
更多是编译器的问题:什么是缓存,什么不是。
当然比后悔好...
volatile
,因为除了生成的代码外,它不会被其他任何东西修改。只要中断不嵌套,编译器就可以“假定” ISR是线性执行的,并且可以执行。这就说得通了。谢谢!