当仅在中断期间读取变量时需要挥发

时间:2019-03-21 10:19:16

标签: c embedded interrupt volatile

C标准规定,如果变量的值可能在程序的正常执行流程之外发生变化,则应在变量的定义中使用volatile关键字。

如果在正常执行流程中更改(写入)了全局变量,并且仅在该正常流程之外(在中断中)读取。这个变量需要可变吗?为什么?

1 个答案:

答案 0 :(得分:5)

  

如果在正常执行流程中更改(写入)了全局变量,并且仅在该正常流程之外(在中断中)读取。这个变量需要可变吗?

是的。

  

为什么?

为了确保正确执行中断处理程序(而不是正常流程)。


让我详细说明。

想象一下,您有一个像这样的变量:

int x;

您正在程序的正常流程中修改此变量,如下所示:

void modify(int *x){...some code here...}

在中断服务程序中,您正在读取变量。

请记住,中断可以异步发生(任何时候)。还请记住,编译器首先会将您的代码转换为一系列机器指令,看起来像这样:

load val from mem to register
perform modification operations
store value from registers to memory
perform other operations where the variable is used

现在,编译器可以优化该程序,以减少这样的内存读写次数:

load value
perform modifications
use value
...
modify register content
...
use
...
keep using value from the registers without ever storing in the memory.

在这种情况下,如果发生中断(请注意,中断上下文通常与正常上下文不同,因此在许多体系结构中具有不同的寄存器集(例如arm ...)),它将尝试从内存中读取变量的值。但是由于编译器的优化,内存的内容从未改变过。

因此,ISR会读取一个旧值(更糟糕的是-我们不能肯定地说一个值有多旧),这会导致意外的行为。

因此,应将变量声明为volatile,以防止编译器干预程序。