I've been playing with my little side project, and that involves Atmel AVR microcontrollers. I love the Atmel AVR family because they're simple and compiler friendly. Friendly enough that even GCC supports them... under Windows too (WinAVR). I'm writing some code to generate PWM signals to drive brushed DC electric motors. Now, these great little chips often support built-in PWM generation. In fact, the particular model I'm using supports six hardware PWM channels. Call me a crazy, but I decided to ignore this perfectly good hardware feature and flip the output pins on and off in code.
In doing so, I've got a set of raw output variables which I convert to a PWM structure. When I call the conversion function in my main loop, it works fine. When I call the conversion function from a interrupt handler (connected to a timer), it doesn't update. WTF?
It's the little things in life... hours spent scratching your head about a simple code change. "Hmmm... works here... not here. Okay... Interrupt handler is definitely called." A trip to AVR Studio's emulator and setting break points on the lines where raw outputs were changed was the key. Quite simply... I couldn't.
When the call that uses these output variables was only within an interrupt handler (and not called from the main body), GCC would optimise away setting (and even calculating) the output variables. My structure was never updated because GCC couldn't see where it was ever used. A similar (non-microcontroller) example is given at over at LinuxDevices.
Adding the volatile keyword to my variable declaration fixed the issue (yay!). Is there a performance impact? Certainly. Enough to worry about? Not yet.