avr-gcc编译器优化了全局变量

时间:2017-01-11 03:17:10

标签: c volatile avr-gcc

这里,

我的原始代码

OCR0A=30;
uint16_t start=TCNT1;
uint16_t w;
for(uint8_t i=0;i<6;i++){
  pwm=pgm_read_byte(&forward[i]);     // mark here
  // delay
  do{
    w=TCNT1;
  } while(w-start>300);
}
OCR0A=127;

编译它,并查看asm,我发现我的代码的业务发生了变化。它变得像波纹管一样

OCR0A=30;
uint16_t start=TCNT1;
uint16_t w;
for(uint8_t i=0;i<6;i++){
  // delay
  do{
    w=TCNT1;
  } while(w-start>300);
}
pwm=pgm_read_byte(&forward[5]);      // mark here
OCR0A=127;

注意在线“标记在这里”。 在我的原始代码中。定时器溢出中断应该使用pwm。第二个代码并非真正由编译器生成。我写这篇文章只是为了方便描述

有什么建议吗? 感谢

1 个答案:

答案 0 :(得分:2)

问题是编译器无法知道您打算在与不同线程不同的位置使用pwm。由于您没有在循环中使用该值,因此编译器只将值设置为它将写入变量的最后一个值(其他值将被覆盖)。

您需要使用内存栅栏来解决此问题(因此编译器和CPU)不会将写入内容重新排序。

编辑:查看this回答表明,将volatile添加到pwm应该足以确保所有写入都会发生。