微控制器中的Volatile关键字

Volatile keyword in microcontrollers

本文关键字:Volatile 关键字 控制器      更新时间:2023-10-16

volatile关键字告诉编译器不要优化带有前缀的变量。该变量可能在运行期间被未知源(编译器不知道)更改,可能是由外部中断等。

volatile还有其他优势吗?volatile是否适用于读取文件?

volatile关键字告诉编译器不要优化前缀的变量,变量可能在运行时被未知源(编译器不知道)改变,可能是由外部中断等

volatile关键字不告诉编译器禁用或不优化变量;volatile关键字告诉编译器该变量(或者该变量所代表的内存)可以在程序的外部被修改。

这会导致编译器不再能够进行必要的分析来确定各种优化是否安全(这在功能上是等同的),因此编译器不会执行这些优化。这是一个必要的副作用,但不是关键字存在的主要目的。

使用volatile作为一种或多或少可移植的方法,类似于pragma来禁用编译器的优化,这是一种相当常见的模式。在嵌入式编程之外,这可能是应用程序程序员最常遇到的用法。

编译器知道该控制器的所有中断。那么在这种情况下,volatile关键字有什么帮助呢?

volatile关键字意味着内存内容可以在程序控制之外修改,可以在另一个进程、线程中修改,也可以通过外部信号(如硬件中断)修改。

编译器不"知道"中断,可能有一些系统头文件和编译器一起为中断定义了符号名,但这并不意味着编译器理解它们。

volatile还有其他优势吗?

除了这里所描述的,我想不起来。

[Does] volatile appl[y] to read from files?

除非用作进程间通信(IPC)的一种形式或作为信号量,否则文件的内容通常由单个进程控制,因此没有必要使用volatile

volatile实际上告诉编译器变量的值可以在其控制流之外被更改。最流行的是中断或中断处理程序或硬件寄存器。对于后者,编译器实际上不知道它的值何时改变。对于中断也是如此,因为它只在运行时发生。

注意C语言假设一个单线程程序流;编译器对并发进程没有任何概念。它对底层硬件的假设更少。

对于所有其他变量,编译器可能(例如gcc实际上)假设它完全了解系统状态。

volatile变量的访问也不能相对于其他变量重新排序。当UART要求首先读取状态寄存器,然后将新字符存储到传输数据寄存器时,这一点很重要。对于大多数mcu,只有这个序列才能正确清除标志。非常重要:非易变变量可以按照编译器的意愿对重新排序(当然,只要不改变程序逻辑)。

请注意,volatile不能保证多核系统上的原子性和正确行为,也不能防止硬件(内存控制器等)对访问的重新排序(好吧,AVR在所有这些方面都有点特权不足;-)。这就是使用锁的原因之一,也是为什么硬件对内存映射中的硬件区域进行特殊处理(有序的、非共享的)。 编辑:

下面详细说明了gcc如何处理volatile对象。众所周知,GCC严格遵守优化标准。任何未被禁止的内容都可能被用于优化。像IAR这样的经典嵌入式编译器通常要保守得多。

volatile的C/c++标准意味着对volatile变量的读和写将是对内存中该位置的读或写,并且对volatile变量的操作顺序将保持不变。由于对易失性变量的读取实际上是对内存中变量的读取,因此如果变量被外部源(如另一个线程、进程或硬件)更新,则read值将反映读取之前发生的任何写操作。它意味着用于内存映射的硬件接口,如I/O内存映射端口。它不能防止对其他变量的无序操作。我假设对多个易失性变量的操作顺序是保持的,因为这是硬件/软件握手所需要的。

Microsoft编译器选择性地扩展了volatile的含义,因此对volatile变量的读/写操作可以作为内存屏障有效地完成,并且可以用于线程之间的通信。正如您所提到的,MSDN volatile .

volatile保证编译器不会对该变量执行任何优化。如果一个变量的值在编译器确定的范围内没有改变,它可以将该值缓存到寄存器中,并引用缓存的值以提高效率,这样就不会浪费从主存中获取实际值的周期。

我可以想象,在一个寄存器数量如此有限的微控制器中,您不会想要不断缓存变量。