在主循环中读写的变量是否需要volatile
?在ISR中为只读变量?
编辑:在写main时,ISR被禁用。因此,该变量可有效地原子使用。
答案 0 :(得分:1)
在主循环中可读写但在ISR中为只读的变量是否需要volatile?
volatile
并不是这里的问题,就像确保main
循环的写操作没有被分开一样。
main()
中的任何更改如果没有受到ISR调用的保护,都可能导致问题,volatile
或没有。声明为volatile
不会保存该问题的代码。
volatile some_type obj;
void ISR() {
foo(obj);
}
int main() {
for (;;) {
// volatile useful here to prevent the assignment from being optimized away.
some_type tmp = bar();
// protect from potential interruption need here.
// Without protection, ISR(),
// doesn't know it is working with a completely written `obj`
obj = tmp;
// release from potential interruption
}
volatile
双向都有用,main()
知道ISR()
可能已经更改了obj
,main()
则没有优化分配。
由于 ISR()
不会更改obj
,因此不需要volatile
。
声明obj
atomic
可能会有所帮助-但这是另一个问题。
答案 1 :(得分:1)
volatile
是同步访问的一种不好方法。这是一个优化障碍,但不是更多。
它不是原子的;例如当您的some_type
是uint64_t
在没有本机64位数据类型的平台上时,可能只有一部分。例如
main() irq()
/* initialization */
var[0..31] = 4
var[32..63] = 8
/* modificatoin */
var[32..63] = 23
/* read */
a_hi = var[32..64] = 32
a_lo = var[0..31] = 4
var[0..31] = 42
取决于体系结构,可能需要内存屏障操作。例如。当main
和irq
在具有专用缓存的不同内核上运行时,irq
将永远看不到更新后的值
第一个问题需要锁定,但是锁定操作通常意味着优化障碍,因此volatile
是多余的。
同上解决第二个问题,即内存屏障也充当优化屏障。
volatile
对于实现对处理器内存的访问很有用(在两次读取之间可能会改变,或者在写入时会产生副作用)。但是通常,它是不需要的并且太昂贵了。