Sunday, January 20, 2008

Unaligned memory access on TI OMAP ARM platform

Before several weeks I was writing some code for TI OMAP1710 and some other models. The code was loading audio data into my current sound engine... And then it came the interesting part. I wrote the loading and media-recognition code and satisfied with the results, I sent the build for testing.

After only 5 min or so, I got a crash report for OMAP1710 (of course I tested on all other boards and forgot to test on just 1710!). 10 mins later I found the reason - of course, unaligned memory access. Let's look at the code (remember this is not the actual code, only showcase for the bug):

void doSomeStuff(unsigned long* base)
{
    unsigned char* p = (unsigned char*)base;
    unsigned long data = 0;

    for (; p < p + 16; p++)

        if (data == 0xAA)
        {
            // do some stuff
        }
        else
        {
            // do other stuff
        }
    }
}

What we are doing here? Trying to read u32 data while stepping by 1 byte in memory...

So, as our common sense talks, this will crash on OMAP1710. But, why the hell this code does not crash but works perfectly on any other platform I've tested?!? (TODO, add a list of working OMAPs).

One simple explanation for this behaviour - OMAP1710 is one of the oldest platforms in it's class, and maybe the board's firmware has just a simple ABORT exception vector (throw an exception to OS and terminate app), while newer OMAP boards have more complicated ABORT exception vector, which can emulate unaligned read via several reads (I know some compilers can also emulate unaligned read/write, but in our case it is not - I ran the same binary on all platforms!)

 So, what's the moral of this story?
1. Never (again) write code when you're tired :)
2. Always test you code on all compatible platforms.
3. Never trust your ARMs (pun intended).

P.S.: Blogger sux. Why I'm supposed to fight with it just to put several lines of text and code?!?