Thursday, February 7, 2008

XC3S1000 failed to boot...

Before several days a friend of mine lend me again his FPGA dev-kit (Xilinx Spartan 3 Starter Board). I worked with this board almost an year before, so as one can imagine I had forgotten how to set the board jumpers for JTAG / Platform Flash configuration. I started playing with different options and programming devices - Digilent LPT JTAG, Digilent Net1 JTAG, Digilent USB2 JTAG.

After several experiments with jumpers and flash programming retries, Xilinx iMPACT failed to program the XCF04S device with verify errors... But when I fired Adept ExPort,
the flashing process was sucessful. Looks like the new iMPACT (v.9.2.04i) is not the way to go... So, we have programmed the platform flash, but still the board is unable to boot from it. After tinkering again with some ISE WebPACK options, I found the problem.

Usually, when building the project we upload the bitstream via the JTAG interface, so the bitstream is configured to be clocked with "JTAG-clock". If we convert the bitstream to a PROM file like this

promgen -w -x xcf04s -p mcs -u 0 bitstream.bit

we get bitstream.mcs ready to be put into the platform flash device. But it won't boot from it  whatever you do. The solution is to change the clock source for the bitstream using "Generate Programming File" -> "Properties" -> "Startup Options" and to set the property "FPGA Start-Up Clock" to "CCLK" value. This will ensure that when FPGA boots from its flash, data will be transferred using the on-board clock, not JTAG clock. So, we succeeded :)

Just as a reminder to everyone (including me), don't forget to set ON all jumpers on J8 (M0, M1, M2), and to set in "Default" position JP1 jumper, otherwise FPGA won't boot (again!).

If you made it through, the prize will be one green LED with label "DONE" ;)

I was afraid at the beginning that the Spartan 3 FPGA or platform flash were defective, but now I'm relaxed.

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?!?