C标准规定,当变量的值有可能在程序的正常执行流程之外发生变化时,应该在变量的定义中使用volatile关键字。
如果在正常执行流程期间更改(写入)全局变量,并且仅在此正常流程之外读取(在中断中)。这个变量是否需要变化?为什么?
如果在正常执行流程期间更改(写入)全局变量,并且仅在此正常流程之外读取(在中断中)。这个变量是否需要变化?
是的,一点没错。
为什么?
确保正确执行中断处理程序(而不是正常流程)。
让我详细说明一下。
想象一下,你有一个像这样的变量:
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,以防止编译器干扰程序。