It’s reasonably well documented there’s a bug with the OS X gcc compiler with Arduino 0013 (and 0012?) in regard to ISR routine code generation. (What makes these different from any other function as far as the compiler is concerned I’m unclear.)
Various workarounds have been discussed, but has anyone reported or chased the actual cause of the problem? Why does the windows compiler behave differently than the OS X compiler? Should the compiler version be rolled back to the one used in 0011, since it generates correct code on all platforms?
Where does the avr-gcc come from? Is it part of some other binary distribution, or does the Arduino team build it from source?
There was another thread in which etracer discovered and explained the root cause, and mellis suggested he's going to update the copy of avr-gcc that is bundled for OSX. I don't know if he'll update the website's 0013.zip or just explain the fix required.
If your ISR calls a function, appropriate registers are not saved and therefore damaged when the ISR returns to normal code.
Right, I followed that thread, and saw the workaround, but didn’t see any indication of a true fix, like someone saying “when I upgraded gcc to version x.y.z the problem went away.” Maybe I should have read more closely.
I’m about to build some more flight hardware (rockets and balloons). The avionics depend heavily on my code, and I depend heavily on an ISR.
The whole thing is a bit strange to me: why is ISR code any different than any other function as far as the compiler is concerned?
The only "true" fix is to upgrade to a fixed version of avr-gcc (which mellis is looking into), or downgrading to an earlier version of the compiler (probably not desirable or possible without large amounts of work). You're welcome to try and include avr-gcc 4.3.2 in you Arduino-0013 (or 0012) environment yourself to address the problem.
The compiler bug is that the generated code is failing to preserve all of the affected registers before calling a function from an ISR. Why this is different from the Windows version, I don't know (that's why it's a bug).
My guess about the bug is that it has something to do with how the compiler optimizes the ISR code. The generated code (on both platforms) ends up making the called ISR function an inline declaration replicated for each interrupt vector that is attached. Before the code is placed inline, the registers are preserved on the stack. After the inline, the registers are restored from the stack.
The difference happens when the ISR code calls another function. In that case it appears the OSX version is not expanding the potential calling tree to find all of the potentially affected registers. So in essence it only preserves the registers used by the base ISR function instead of any others affected by the nested functions.
The short of it is that if your ISR doesn't call any functions (or utilize and Wiring calls), then the bug won't affect you. Otherwise the only fix is an upgraded compiler (or very targeted work-arounds like I made for the NewSoftSerial code).
The short of it is that if your ISR doesn't call any functions (or utilize and Wiring calls), then the bug won't affect you.
Ah, this explains why I haven't seen it. I generally make my ISRs set a flag and return ASAP, if I can make things work that way.
This is biting me pretty hard. Does anyone have instructions on upgrading avr-gcc?
Ok, I managed to get it working myself. In case anyone needs instructions, here is what I did:
- Download "AVR Mac Pac" from http://www.obdev.at/products/avrmacpack/index-de.html and run the installer.
- Navigate to "/Applications/arduino-0013/hardware/tools", and rename "avr" to "avr (old)".
- Copy "/usr/local/AVRMacPack-20081213" into "/Applications/arduino-0013/hardware/tools", and rename it "avr".
- Replace "/Applications/arduino-0013/hardware/tools/avr/bin/avrdude" with "/Applications/arduino-0013/hardware/tools/avr (old)/bin/avrdude".
If anyone who really knows what they're doing could confirm that I haven't missed anything, that would be great.