易失的变量,只能在ISR中读取?

时间:2019-03-03 02:38:11

标签: c interrupt volatile

在主循环中读写的变量是否需要volatile?在ISR中为只读变量?

编辑:在写main时,ISR被禁用。因此,该变量可有效地原子使用。

2 个答案:

答案 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()可能已经更改了objmain()则没有优化分配。

由于ISR()不会更改obj,因此不需要volatile

声明obj atomic可能会有所帮助-但这是另一个问题。

答案 1 :(得分:1)

volatile是同步访问的一种不好方法。这是一个优化障碍,但不是更多。

  • 它不是原子的;例如当您的some_typeuint64_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
    
  • 取决于体系结构,可能需要内存屏障操作。例如。当mainirq在具有专用缓存的不同内核上运行时,irq将永远看不到更新后的值

第一个问题需要锁定,但是锁定操作通常意味着优化障碍,因此volatile是多余的。

同上解决第二个问题,即内存屏障也充当优化屏障。

volatile对于实现对处理器内存的访问很有用(在两次读取之间可能会改变,或者在写入时会产生副作用)。但是通常,它是不需要的并且太昂贵了。