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

avr gcc编译器优化了一个全局变量,c,volatile,avr-gcc,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; OCR0A=30; uint16\u t start=TCNT1; uint16

这里,

我的来源代码

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;
OCR0A=30;
uint16\u t start=TCNT1;
uint16_t w;
对于(uint8_t i=0;i300);
}
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;
OCR0A=30;
uint16\u t start=TCNT1;
uint16_t w;
对于(uint8_t i=0;i300);
}
pwm=pgm_读取_字节(&forward[5]);//在这里做标记
OCR0A=127;
注意“在这里做标记”。 在我的原始代码中<定时器溢出中断应使用代码>pwm。第二个代码实际上不是由编译器生成的。我写它只是为了方便

有什么建议吗?
谢谢

问题在于编译器无法知道您打算在不同线程的不同位置使用
pwm
。由于不在循环中使用该值,编译器只会将该值设置为它将写入变量的最后一个值(其他值无论如何都会被重写)

您需要使用内存围栏来绕过这一点(因此编译器和CPU不会对写入内存的操作重新排序)


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

IMHO,GCC选择将读取推到for循环之外,这是非常奇怪的。可能需要发布更多的代码,以便我们对此做出正确的判断。我知道AVR-GCC可以做一些古怪的事情,但并非完全没有理由,但是如果我们了解更多的上下文,这个小例子可能会变得更容易理解。我发布的代码表明问题不是真的。我只是编出来的。为什么编译器会产生不同的结果?这行不通,也许你误读了大会?没有人可以验证,除非你展示了asm以及验证你的结论所需的任何其他东西。如果你可以发布更多的汇编,我们可以更容易地揭穿这一点。(如果你不想用汇编代码完全阻塞问题,你可以使用,比如pastebin或其他东西(我不确定代码发布的替代方案)。编译器认为
for
语句对变量
pwm
无效。只需分配最终值
forward[5]