-2

here,

My origin code

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;

compile it, and look into asm, I found my code's business was changed. it became some other like bellow

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;

Attention on line "mark here". In my origin code. pwm should be used by timer overflow interrupt. the second code is not really generated by compiler. I wrote it just for convenience describe

Any suggestion? Thanks

howard
  • 83
  • 1
  • 5
  • IMHO, that's extremely weird that GCC would opt to push your read outside the for-loop. Might want to post a bit more of your code for us to make a good judgement of this. I know AVR-GCC can do some funky stuff, but not completely without reason, but this small example might become more understandable if we get a bit more of context. – Ludricio Jan 11 '17 at 03:34
  • *The code I posted that shows the problem isn't real. I just made it up. Why is the compiler producing something different?* isn't going to work. – Ken White Jan 11 '17 at 03:35
  • 2
    Maybe you misread the assembly? No one can verify unless you show the asm together with whatever else is needed to verify your conclusions. – kaylum Jan 11 '17 at 03:35
  • If you could post more of the assembly, we could debunk this easier. (you could use, say pastebin or something (I'm not that sure about code posting alternatives) if you don't want to completly clog up the question with assembler code. – Ludricio Jan 11 '17 at 03:38
  • Compiler considers `for` statement is useless for variable `pwm`. just assigned the final value `forward[5]` – howard Jan 11 '17 at 08:43

1 Answers1

3

The problem is that the compiler has no way of knowing that you intend to use pwm in a different location from a different thread. As you don't use the value in the loop the compiler just sets the value to the last value it would have written to the variable (the other values will be over written anyway).

You need to use a memory fence to get around this (so the compiler and the CPU) don't reorder the writes to memory.

edit: Looking at this answer suggests that adding volatile to pwm should be enough to make sure that all the writes occur.

Community
  • 1
  • 1
dave
  • 4,812
  • 4
  • 25
  • 38