微控制器中的 volatile 关键字
Volatile keyword in microcontrollers
volatile
关键字告诉编译器不要优化带前缀的变量。该变量可能在 运行 时间内由未知来源(编译器不知道)可能由外部中断等改变。
volatile
还有其他优势吗?
volatile
是否适用于读取文件?
volatile 的 C/C++ 标准意味着对 volatile 变量的读取和写入将是对内存中该位置的读取或写入,并且将维护对 volatile 变量的操作顺序。由于从 volatile 变量读取实际上是读取内存中的变量,因此如果变量由外部源(例如另一个线程、进程或硬件)更新,则读取的值将反映读取之前发生的任何写入。它旨在用于内存映射硬件接口,例如 I/O 内存映射端口。它不会阻止对其他变量的乱序操作。我假设维护多个易失性变量的操作顺序,因为硬件/软件握手需要这样做。
Microsoft 编译器可选择扩展 volatile 的含义,以便对 volatile 变量的读/写操作有效地作为 memory barrier and can be use for communication between threads. MSDN volatile 完成。
正如您提到的,volatile
保证编译器不会对变量执行任何优化。如果变量的值在编译器确定的范围内未更改,它 可能 将值缓存到寄存器并引用该缓存值以提高效率,这样就不会浪费周期从主内存中获取实际值。
我想在寄存器数量如此有限的微控制器中,您不会希望不断缓存变量。
volatile
实际上告诉编译器变量的值可能会在其控制流 之外被更改。最流行的是中断或中断处理程序或硬件寄存器。对于后者,编译器实际上 not 知道它的值何时改变。它也不是中断,因为它只发生在 运行 时间。
请注意,C 假定单线程程序流;编译器对并发进程一无所知。更不用说对底层硬件做假设了。
对于所有其他变量,编译器可能(例如 gcc 实际上 将 )假设它完全了解系统状态。
此外,对 volatile
变量的访问可能不会相对于彼此重新排序。例如,这很重要。 UART 要求先读取状态寄存器,然后将新的字符存储到发送数据寄存器。对于大多数 MCU,只有此序列才能正确清除标志。非常重要:非可变变量 可以 根据编译器的需要重新排序(当然,只要它不改变程序逻辑)。
请注意,volatile
不能保证多核系统上的原子性和正确行为,也不能防止硬件(内存控制器等)对访问进行重新排序(好吧,AVR 有点所有这些都处于弱势地位;-)。这是锁的原因之一,也是内存映射中的硬件区域被硬件特殊对待的原因之一(有序的,非共享的)。
编辑:
Here详细介绍了gcc如何处理volatile对象。众所周知,gcc 严格遵守优化标准。任何未被禁止的内容都可能被用于优化。像 IAR 这样的经典嵌入式编译器通常要保守得多。
volatile
keyword says to compiler do not optimize the variable which is prefixed with, the variable may change during run time by unknown source(not known to compiler) may be by an external interrupt etc.
没有。 volatile
关键字不会告诉编译器禁用或不优化变量; volatile
关键字告诉编译器可以在程序外部修改变量(或者更确切地说,变量代表的内存)。
这会导致编译器不再能够进行必要的分析以确定各种优化是否安全(即功能等效),因此编译器不会执行这些优化。这是一个必要的副作用,但不是关键字存在的主要目的。
使用 volatile
作为一种有点或稍微可移植的 hack 来像 pragma
一样来禁用编译器的优化是一种相当常见的模式。在嵌入式编程之外,这可能是应用程序员最常遇到的用法。
The compiler knows all the interrupts of that controller. So in that case how the volatile
keyword helps?
volatile
关键字表示可以在程序控制之外修改内存内容,可以是在另一个进程、线程中,也可以是通过硬件中断等外部信号。
编译器不 "know" 关于中断,可能有编译器分发的系统头文件定义了中断的 符号名称 ,但这并不意味着编译器理解它们。
Is there any other advantage of volatile
?
除了这里描述的内容,我想不出。
[Does] volatile
appl[y] to reading from files?
除非用作进程间通信 (IPC) 的一种形式或用作信号量,否则文件的内容通常由单个进程控制,因此没有必要使用 volatile
。
volatile
关键字告诉编译器不要优化带前缀的变量。该变量可能在 运行 时间内由未知来源(编译器不知道)可能由外部中断等改变。
volatile
还有其他优势吗?
volatile
是否适用于读取文件?
volatile 的 C/C++ 标准意味着对 volatile 变量的读取和写入将是对内存中该位置的读取或写入,并且将维护对 volatile 变量的操作顺序。由于从 volatile 变量读取实际上是读取内存中的变量,因此如果变量由外部源(例如另一个线程、进程或硬件)更新,则读取的值将反映读取之前发生的任何写入。它旨在用于内存映射硬件接口,例如 I/O 内存映射端口。它不会阻止对其他变量的乱序操作。我假设维护多个易失性变量的操作顺序,因为硬件/软件握手需要这样做。
Microsoft 编译器可选择扩展 volatile 的含义,以便对 volatile 变量的读/写操作有效地作为 memory barrier and can be use for communication between threads. MSDN volatile 完成。
volatile
保证编译器不会对变量执行任何优化。如果变量的值在编译器确定的范围内未更改,它 可能 将值缓存到寄存器并引用该缓存值以提高效率,这样就不会浪费周期从主内存中获取实际值。
我想在寄存器数量如此有限的微控制器中,您不会希望不断缓存变量。
volatile
实际上告诉编译器变量的值可能会在其控制流 之外被更改。最流行的是中断或中断处理程序或硬件寄存器。对于后者,编译器实际上 not 知道它的值何时改变。它也不是中断,因为它只发生在 运行 时间。
请注意,C 假定单线程程序流;编译器对并发进程一无所知。更不用说对底层硬件做假设了。
对于所有其他变量,编译器可能(例如 gcc 实际上 将 )假设它完全了解系统状态。
此外,对 volatile
变量的访问可能不会相对于彼此重新排序。例如,这很重要。 UART 要求先读取状态寄存器,然后将新的字符存储到发送数据寄存器。对于大多数 MCU,只有此序列才能正确清除标志。非常重要:非可变变量 可以 根据编译器的需要重新排序(当然,只要它不改变程序逻辑)。
请注意,volatile
不能保证多核系统上的原子性和正确行为,也不能防止硬件(内存控制器等)对访问进行重新排序(好吧,AVR 有点所有这些都处于弱势地位;-)。这是锁的原因之一,也是内存映射中的硬件区域被硬件特殊对待的原因之一(有序的,非共享的)。
编辑:
Here详细介绍了gcc如何处理volatile对象。众所周知,gcc 严格遵守优化标准。任何未被禁止的内容都可能被用于优化。像 IAR 这样的经典嵌入式编译器通常要保守得多。
volatile
keyword says to compiler do not optimize the variable which is prefixed with, the variable may change during run time by unknown source(not known to compiler) may be by an external interrupt etc.
没有。 volatile
关键字不会告诉编译器禁用或不优化变量; volatile
关键字告诉编译器可以在程序外部修改变量(或者更确切地说,变量代表的内存)。
这会导致编译器不再能够进行必要的分析以确定各种优化是否安全(即功能等效),因此编译器不会执行这些优化。这是一个必要的副作用,但不是关键字存在的主要目的。
使用 volatile
作为一种有点或稍微可移植的 hack 来像 pragma
一样来禁用编译器的优化是一种相当常见的模式。在嵌入式编程之外,这可能是应用程序员最常遇到的用法。
The compiler knows all the interrupts of that controller. So in that case how the
volatile
keyword helps?
volatile
关键字表示可以在程序控制之外修改内存内容,可以是在另一个进程、线程中,也可以是通过硬件中断等外部信号。
编译器不 "know" 关于中断,可能有编译器分发的系统头文件定义了中断的 符号名称 ,但这并不意味着编译器理解它们。
Is there any other advantage of
volatile
?
除了这里描述的内容,我想不出。
[Does]
volatile
appl[y] to reading from files?
除非用作进程间通信 (IPC) 的一种形式或用作信号量,否则文件的内容通常由单个进程控制,因此没有必要使用 volatile
。