Random JMPing Jacks
Oh right, this blog thing. All’s been fairly silent publicly in Camp Camera over the last few months — but fear not, for I know you’re all excited to hear that I am, in fact, still alive and kicking. The truth of the matter is that I’ve just been completely drained of both spare time and energy ever since I started work making light bulbs for a living. No jokes about Watts, Lumens, etc. please, as I assure you I’ve now heard every single possible pun in the English language on the subject.
Working at a start-up company, even a fast growing and fast growing-up one, is a very difference experience to my time at Atmel. It’s had its ups and downs, tantrums and triumphs, but overall I really think it’s been of a great personal benefit; I’ve rapidly expanded my comfort zone outside the realms of my beloved AVRs and into the wide range of horribly broken, awfully designed processors thrown up by various silicon manufacturers. All those who’ve complained about (non-UC3) AVR datasheets in the past can put a sock in it, for there are worse beasts out there.
That said, recently I’ve started taking a guilty look at my overflowing inbox — last year I averaged about three to four days before giving a response, sadly of late it’s more like two two three weeks and I’m trying to regain a little of the work/life balance I’ve been missing. Me culpa.
The downside to spending all day arms deep in third party stacks and undocumented processor bugs is that when I get home I don’t really feel like working on my personal AVR projects very often, but a week ago I decided to poke around a bit again and re-familiarize myself with my old code. And of course, as luck would have it, I managed to hit a fun “feature” of the newer versions of AVR-GCC whist trying to test a third party contributed patch to LUFA’s bootloaders.
A summary: the newer versions of AVR-GCC optimize some C
switch statements into a jump table (effectively a bunch of GOTOs), using a fixed set of assembly instructions that read out the jump target locations from the table stored in flash memory, via the
LPM instruction. However, while this works on most classic 8-bit AVR processors, if the jump table is located above the first 64KB of flash memory, the
ELPM instruction needs to be used, or the read data will be sourced from an incorrect position in the lower 64KB of flash and the processor will jump to an unintended location. The GCC internals have safety checks to avoid this case, however it fails when the compiled code is relocated such as in my case where the application text segment is moved into the upper bootloader area.
The fix is simple, compile with the
-fno-jump-tables flag to disable that optimization. I still think this should be off by default, or at least the pessimistic ELPM instruction used on the larger parts (so that the optimization works regardless of the jump table’s location) but alas, we’re stuck with what we have. In any case, as of the next LUFA release that optimization will be disabled by default in the LUFA build system and Atmel Studio templates.
On that note, I’ll be spinning a new LUFA release soon, since it’s been quite a while since the last one earlier this year. Most of the changes this time are community driven, but I think it’s a shame that they aren’t in general use so the time is about right for another full release package.
Oh, and AVRFreaks.net has finally got a new facelift after many years (and, much more importantly, a new backend that appears to actually work). Go check it out; there’s a lot of known issues like broken redirects from the old style URLs that are being worked on, but it’s great to see some movement on it after having it stagnate for so long.
UPDATE: Looks like the GCC developers have now fixed it for AVR-GCC 4.9.2. Awesome!