" volatile"的重要性是什么?关于嵌入式系统的关键词?

时间:2015-08-07 20:31:40

标签: embedded c

我最近一直在努力学习嵌入式系统编程。我在声明变量时观察到关键字volatile限定符的使用率相当高?

在嵌入式系统编程中声明变量时volatile有什么意义?

基本上应该使用关键词。我确实读过有关编译器优化和关键字使用的内容。还有与内存映射寄存器有关的东西。

例如,我读了这篇StackOverflow post,但我并不了解它在嵌入式环境中的应用。更具体地说,我不明白何时应该使用关键词。我确实读过有关编译器优化和关键字使用的内容。还有一些与内存映射寄存器有关的东西,但我不知道何时使用它。

5 个答案:

答案 0 :(得分:10)

让我们来看一个例子。当您查看PIC微控制器的C头文件时,您将看到许多元素被声明为volatile

extern volatile unsigned char           PORTB               @ 0x006;

如您所读,volatile关键字禁用编译器优化。假设您编写了一个执行以下操作的程序:

PORTB = 0x00;            // set all of port B low
while (PORTB == 0x00);   // wait for any pin to get high
// do something else

当编译器优化此代码时,它会将第二行识别为无限循环:条件为true且永远不会在其正文中变为false。因此,无限循环之后的所有都不需要编译,因为它永远不会被运行。因此,编译器可能决定不在生成的汇编代码中包含该部分代码。

但是,此PORTB实际上与物理端口相关联。它是硬件端口,其值可能会被外部电路改变。这意味着虽然循环似乎是无限的,但它并不是必须的。编译器可能不知道这一点。

volatile所在的位置。当PORTB被声明volatile时,编译器不会根据PORTB的推理进行任何优化。它将假设其值可能随时由外部因素改变。

答案 1 :(得分:6)

在嵌入式系统领域,volatile关键字的一个关键方面是它表示可能随时改变的变量(例如外部/硬件数据输入 - 例如ADC)和因此编译器不得优化使用。

但具体而言,当与控制寄存器一起使用时,它表明读取访问实际上可能会改变数据!

作为一般经验法则,我建议在以下所有内容中使用volatile限定符:

  • 所有硬件寄存器访问(读写)
  • 多个线程中可访问的所有变量(尤其是中断处理程序)

注意:访问volatile不一定是原子的,因此您必须了解硬件和代码结构。

答案 2 :(得分:2)

主要使用 volatile 关键字告诉编译器变量的值可能随时更改。它还告诉编译器不要对变量应用优化。我对此并不是一位专家,但下面是我过去提到过的好参考。

  

volatile 是在声明变量时应用于变量的限定符。它告诉编译器变量的值可能随时发生变化 - 编译器在附近找不到任何代码。这种影响非常严重。但是,在我们检查它们之前,让我们看一下语法。

参考:

答案 3 :(得分:1)

让我从其他角度来看,它与 const 关键字正好相反。 当编译器遇到任何变量的 const 限定符时,它会检查是否在初始化时修改了任何函数或语句。因此标志错误。

易失性正好相反,这个变量可以通过任何函数改变。因此编译器不应用优化。

由于使用了中断,您在嵌入式系统编程中看到了这一点,并且一些编程逻辑结构似乎是多余的。

答案 4 :(得分:0)

尽管关于优化的陈述是正确的,但对我来说似乎有些不清楚。这是真正发生的事情。

如果您不使用volatile关键字,则C可能会将变量优化为当前未使用的寄存器。这样可以减少汇编指令,并且代码执行速度更快。

例如,考虑以下...

extern int my_port;    // my_port is defined in a different module somewhere
                       // presumably a memory mapped hardware port
while (my_port > 0) {so stuff}

编译器可能决定仅在实际的while语句之前将my_port读入寄存器一次,然后每次测试my_port时,它只会查看寄存器而不是内存位置。

但是,如果my_port是硬件端口,则该端口可能会更改,但注册不会更改,而条件条件不会更改。

循环变量(寄存器)将与实际变量(my_port)“异相”。

因此需要关键字volatile。

Volatile告诉C,“不要将此变量优化为reg,而是每次需要时都读取它。”

生成的指令更多,代码稍慢一些,但始终准确。