mbed crash during init of SPI component with large arrays of data

21 Mar 2013

Hi everyone,

I am experiencing an strange problem: I am using a external SPI component module that I need to initialize by feeding him with a set of 4 "large" arrays of data (one of them is a little larger than 1kbyte, the 3 others are 100 bytes or less).

the way that initialization routine is written is that it writes the arrays mentionned above, and then goes on with the init process by reading data from the SPI slave chip, polling it etc.

I am able to write that data int the arrays to the SPI slave chip, but my initialization routine will crash within the operations (a while loop with SPI polling in it until it receives certain data) that come after. if I replace that SPI polling loop by, let's say, a led blinking loop, it leads to the same result. I am able to see it because if I do some debug printfs on the serial port in the polling loop, I can clearly see it stop. Same goes for the blinking led test, it will only flash once, then crash.

If I remove the function that writes the largest array on the SPI bus AND the array itself, then it works... but my chip is not initialized, of course!

My arrays are declared as const uint8* const array = {/*content of the array*/}; and should be stored in ROM, right?

Since it appears to be some memory size problem (the init routine is pretty heavy overall), I thought about stack overflow but I am not using the mBed OS feature. I don't have the "blue lights of death" thing either.

I am out of ideas... :|

Any help or pointers to solve this would be really appreciated!

Thanks a lot!

21 Mar 2013

1K should not be a problem, but check the used flash/ram sizes after compilation.

If you post your code, we can look at and discuss it. Otherwise we can hypothesize all week long but are unlikely to find the issue.

21 Mar 2013

Hi Igor,

Thanks for your reply, how do you check flash and ram size after compilation?

Here is my my code, slightly simplified to make it more easy to read :

init function called from main

int initFW(void)
{
    const uint8 const fw1 = {/*30 bytes here*/};
    const uint8 const fw2 = {/*100 bytes here*/};
    const uint8 const fw3 = {/*1100 bytes here*/};
    uint8  dBuf[4];
    int retval;
    t_uFrame *uFrame

    for (i = 0; i < sizeof(dBuf); i++) { dBuf[i] = 0; }                                                            // zero out dBuf
    dBuf[0] = 0x01;
    retval = memWrite(RST_ADDR, sizeof(dBuf), dBuf);          
    if(retval !=0)
    {

        return retval;
    }
    

    retval = memWrite(ADDRFW1, sizeof(fw1), (uint8*)fw1);     

    if(retval !=0)
    {
        return retval;
    }
    

    retval = memWrite(ADDRFW1, sizeof(fw2), (uint8*)fw2);     
  

    if(retval !=0)
    {   
        return retval;
    }
   

    retval = memWrite(ADDRFW1, sizeof(fw3), (uint8*)fw3);     

    if(retval !=0)
    {
        return retval;
    }

    for (i = 0; i < sizeof(dBuf); i++) { dBuf[i] = 0; }                                                          
    dBuf[0] = 0x01;
    retval = memWrite(0x32, 0x0004, dBuf);            

    if(retval !=0)
    {
        return retval;
    }

    retval = SpiFrameRead(&uFrame);
    if(retval !=0)
    {
        return retval;
    }

    return retval;
}

memWrite is a wrapper that write data on the spi bus with the appropriate commands.

The following function is the one that polls the SPI bus for some specific data but ends up crashing (it is called at the end of the function above).

spiFrameRead

int SpiFrameRead(t_uFrame *uFrame)
{
    int16                    retval;
    char tx = 0;

    spi.write(B1);
    spi.write(B2);
    spi.write(B3);
    spi.write(B4);
    spi.write(B5);
    spi.write(B6);

    //I never get out of this loop
    while(1)
    {
        tx = 0;
        if(spi.write(tx)== 0x87) { retval = 0; break; }
        pc.printf("s");
    }

    return retval;                           
}
21 Mar 2013

Either move out the array definitions out of the function, or mark them as static. Otherwise it's very well possible that the compiler will copy them onto the function's stack, since you declared them as local variables.

22 Mar 2013

Ok, thanks for the suggestion. I remember that I already tried to move the biggest array as a global variable, though. I'll try it asap.

22 Mar 2013

Your program hangs because the calls to write(0) in your loop, never return 0x87. What is returned by 'write' depends on your SPI device but I suspect that you read somewhere in the spec that it should return 0x87 at some point. I further suspect that this point has past because you have written already 6 words without checking the return value, maybe one of those was 0x87. Furthermore make sure that you set the correct word size.

22 Mar 2013

Hello Ad, I am aware of the SPI write function features. I know that I am not listening to the first 6 bytes, but this is not really the problem here : the printf call that is in the same loop as the if condition (i.e. the while(1) loop) prints on the serial port once everytime that the spi write function returns a character that is to be tested, right? So that printing should go on wether I receive the right character, 0x87, on the SPI bus or not. Which is precisely what does NOT happen :( It prints something like 50 times "s" and then crash. Same problem if I trade the printf for LED flash for example. What goes in and out of the SPI bus does not really matter at this point, it is more like why does the program crashes if I try to do anything in that part of the program.

25 Mar 2013

Hey everyone,

So I tried marking the arrays as static AND (afterwards) moving them as global variables. It does not work... I tried changing the SPI bus frequency to see that my program would print more "s" when I increased the frequency. It really looks like the mbed cannot stand spending more than a certain amount of time in that function : if it can poll faster, it will print more times, but it will still crash at the same moment or so... I am clueless on this one...!

25 Mar 2013

Can you publish the simplest program where this happens? Since apparently it goes wrong while waiting for a specific reply we should be able to test it simply by connecting MISO to ground for example.

I have used SPI myself to write to LCD devices, with 320x240x2 number of bytes writting to it for clearing the screen, and that never gave problems.

27 Mar 2013

Hey Erik,

Actually I solved the proble by segmenting the biggest array in slices of 256 bytes... It is still weird that a 1kb array causes the mbed to crash though...

27 Mar 2013

It is still strange, I had a look at the SPI source code, in spi::write the lib makes two blocking calls to check the SPI status register. If your code hangs in write it probably means that either the readable or writeable condition never becomes true. How this can happen I have no idea. The only thing I can think of is that another routine messes with one of the spi registers. Note that in some archtectures even reads are dangerous. So I'm thinking more about a timing problem than a memory problem because the lib itself is not concerned with arrays.