函数调用之间是否刷新了全局变量?

我正在编写嵌入式固件,并发现有时很难确定何时需要使用volatile。

当我有一个等待某个布尔标志被中断改变的函数时,很明显该标志需要是易失性的,因为该函数会永远等待,因为编译器没有意识到该值可以由打断。

但是当我有一个只检查第一行中的标志的短函数时,我希望标志不需要是易失性的,因为每次进入函数时它的值都会被读取? 所以当一个中断在我第一次调用函数和第二次调用函数之间修改它的值时,我将获得最新的值。 或者是否无法保证每次进入该function时都会清除所有缓存寄存器?

你仍然需要标记你的变量volatile :因为优化器可以自由地内联你的函数,特别是短函数,在没有用于访问硬件修改内存的volatile标记的循环中调用你的函数会使你有可能无法读取初始迭代后的内存。

…因为每次进入函数时都会读取它的值?

不,不能保证这一点。 “缺乏易失性错误”的问题在于,编译器的优化器,不知道某个变量可以从外部源更改,会改变代码的整个含义。

所以,如果你有这个:

 static int x=0; int func (void) { if(x == 0) { return 1; } else { return 0; } } interrupt void isr (void) { x = SOMETHING; } 

然后编译器会思考:“嗯,x永远不会被修改,因为”isr“永远不会从程序中调用。所以x总是0,我会优化代码:

 int func (void) { return 1; } 

然后,也许,它将内联整个function。 这种情况是否发生无关紧要,因为代码的含义在之前的优化步骤中已被破坏。

与中断(或线程,或DMA,硬件寄存器或回调函数)共享的任何变量必须始终声明为volatile。

任何对硬件寄存器的访问最好标记为volatile。 编译器不知道它将通过硬件中的中断或DMA进行更改,并且编译器可以并且将认为它不会因此而且可以缓存某些值。

基本上,如果它是硬件映射的,或者可以通过中断(来自硬件)进行更改,则标记为易失性。

除了标记变量volatile以强制加载(如@dasblinkenlight建议的那样),您还应该采取措施确保以primefaces方式读取(和写入)变量。 在某些平台上,对于某些大小的对象(如最近的x86处理器上的32位值),这会自动发生。 通常,您可能需要在变量周围放置同步锁,例如互斥锁或信号量。 当异步代码是一个线程时,这相对容易。 当涉及到真正的中断时,我不确定该怎么做,因为某些同步技术可能是不可能的。 您的平台文档应该提供一些见解。

应将所有共享内存声明为volatile

您可能也可能不对,您的特定编译器不会优化特定示例中的读取,但在这种情况下, volatile关键字会增加开销(即,在指定显式读取的位置没有开销任何情况),为什么风险未定义或不可移植的行为?