易失性关键字 - MSP430

时间:2013-06-19 17:31:45

标签: c msp430

我正在尝试在TI MSP430 Launchpad板上闪烁LED。我有两段代码。一个工作,而另一个不工作。唯一的区别是在工作版本中包含volatile关键字。为什么程序执行需要此关键字?

此代码有效......

void main(void) {
    WDTCTL = WDTPW | WDTHOLD;           // Stop watchdog timer

    // Configure Port Directions
    P1DIR |= 0x01;                      // 0000 0001

    volatile unsigned int i;

    for(;;)
    {
        P1OUT ^= 0x01;                  // Set P1.0 LED on
        for (i = 20000; i > 0; i--);    // Delay
    }
}

虽然这段代码没有......

void main(void) {
    WDTCTL = WDTPW | WDTHOLD;           // Stop watchdog timer

    // Configure Port Directions
    P1DIR |= 0x01;                      // 0000 0001

    unsigned int i;

    for(;;)
    {
        P1OUT ^= 0x01;                  // Set P1.0 LED on
        for (i = 20000; i > 0; i--);    // Delay
    }
}

6 个答案:

答案 0 :(得分:4)

如果没有volatile,编译器可以更好地优化代码,它确定什么都不做,以及重新排序内存访问。不使用volatile时,您的延迟循环正在优化。

答案 1 :(得分:3)

这两个版本都没有任何好处,未来版本的编译器可能会生成截然不同的代码。

大多数MSP430开发工具提供了当您想要等待特定周期数时要使用的内部函数__delay_cycles()

例如:

#include <intrinsics.h>
void main(void)
{
  WDTCTL = WDTPW | WDTHOLD;           // Stop watchdog timer

  // Configure Port Directions
  P1DIR |= 0x01;                      // 0000 0001

  for(;;)
  {
    P1OUT ^= 0x01;                  // Set P1.0 LED on
    __delay_cycles(40000);
  }
}

请注意,为此生成的代码将以完整的处理器速度执行。如果在功率受限的环境中需要更长的延迟,请考虑使用定时器并将处理器置于低功耗模式。

答案 2 :(得分:1)

如果您在循环中的第二个版本中添加NOP

for (i = 20000; i > 0; i--) {
    asm volatile("nop");
}

它应该也可以。在这两种情况下,都需要volatile来阻止优化。在第一个版本中,它阻止编译器完全删除循环。在使用asm的第二个版本中,它告诉编译器将其保留在原来的位置(因此它不会移动到另一个位置)。

令人难过的是,这两个版本都不被认为是好的风格:考虑使用计时器来确保繁忙的延迟。如果更改核心频率,循环将无法执行您想要的操作。

答案 3 :(得分:1)

在检查IAR编译器的汇编输出(MSP430F5438的V4.21.9)时,总是编译无限循环,有或没有volatile关键字。 (达到中等优化设置。)因此,这可能是编译器依赖性。当然,请尝试关闭优化进行编译。

volatile关键字很重要的地方是告诉编译器不要指望一个值,因此重新读取它。例如,您可能正在读取接收外部字符的输入缓冲区。需要告诉编译器继续读取,因为缓冲区是由其知识范围之外的东西更新的。

答案 4 :(得分:0)

我更喜欢适用于每个编译器的解决方案,从另一个未优化或未通过循环优化的模块调用函数。 Asm就是一个很好的例子。一个只返回

的虚函数
dummy:
   ret

...

void dummy ( unsigned int );

unsigned int ra;
for(ra=0;ra<10000;ra++) dummy(ra);

编译器可以根据需要展开一些循环,但是必须以正确的顺序使用正确的参数调用dummy,您可以毫无顾虑地对C代码使用最大优化。

答案 5 :(得分:0)

如果你没有声明它是volatile,那么很多编译器都会执行运行时优化,因此你可能无法获取更改