微控制器中的易失性关键字

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

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

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

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

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

使用volatile作为一个稍微或稍微可移植的黑客行为就像一个pragma来禁用编译器的优化是一种相当常见的模式。 在嵌入式编程之外,这可能是应用程序员最常遇到的用法。

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

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

编译器不“了解”中断,可能存在与编译器一起分发的系统头文件,这些文件定义了中断的符号名称 ,但这并不意味着编译器理解它们。

volatile还有其他优势吗?

除了这里描述的内容之外,这不是我能想到的。

[ volatile ] appl [y]从文件中读取?

除了用作进程间通信(IPC)或信号量的forms之外,文件的内容通常由单个进程控制,因此不需要使用volatile

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

请注意,C假定单线程程序流程; 编译器不知道并发进程。 它对底层硬件的假设更少。

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

volatile变量的访问也可能不会相互重新排序。 当例如UART要求首先读取状态寄存器然后可以将新的字符存储到发送数据寄存器时,这是重要的。 对于大多数MCU,只有这个序列才能正确清除标志。 非常重要:非vloatile变量可以像编译器一样重新排序(当然,只要它不改变程序逻辑)。

请注意, volatile不能保证多核系统的primefaces性和正确行为,或者确保防止硬件(内存控制器等)对访问的重新排序(好吧,AVR对所有这些都有点不利;-)。 这是锁定的一个原因,以及为什么硬件处理内存映射中的硬件区域(有序,非共享)。

编辑:

这里详细介绍了gcc如何处理volatile对象。 众所周知,gcc严格遵守优化标准。 任何不被禁止的东西都可能被利用来进行优化。 像IAR这样的经典嵌入式编译器通常要保守得多。

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

Microsoft编译器可选地扩展volatile的含义,以便对volatile变量的读/写操作有效地作为内存屏障完成 ,并可用于线程之间的通信。 MSDN易变 。

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

我想在具有如此有限数量的寄存器的微控制器中,您不希望不断地缓存变量。