Stack checking

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Stack checking

1,674 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mohsin on Wed Jan 12 10:47:52 MST 2011
Hi All,

          I am using the example "Monitor Stack Usage Example V1.1" for LPC1114. The example uses [B]StackHeapInit()[/B] function to initialise the stack area with a constant values 0xdeadbeef and this function is called from startup code  [B]ResetISR()[/B]

void StackHeapInit(void)
{
    register unsigned long *StackPointer asm("sp");
    unsigned long *StackLimit = (unsigned long *)&_pvHeapStart;

    while(StackLimit < StackPointer)
        *(StackLimit++) = stackinitconst;
}

void ResetISR(void)
{
    unsigned char *pulSrc, *pulDest;

    [B]StackHeapInit();[/B]
  
    // Other initialisation

}

The problem is, if I call the function [B]StackHeapInit[/B] from with [B]ResetISR[/B] it causes my code to behave a bit odd (causes the display on the LCD to shift left/right)

It seems to work fine when [COLOR=Blue]I do the initialisation within ResetISR  instead of calling other function [/COLOR]as follows.

void ResetISR(void)
{
    unsigned char *pulSrc, *pulDest;

     register unsigned long *StackPointer asm("sp");
    unsigned long *StackLimit = (unsigned long *)&_pvHeapStart;

    while(StackLimit < StackPointer)
        *(StackLimit++) = stackinitconst;
  
    // Other initialisation

}

[COLOR=Red]Also even if I call a dummy function within ResetISR without doing any stack checking the problem occurs[/COLOR]

void ResetISR(void)
{
     unsigned char *pulSrc, *pulDest;

    [B]dummy_function();[/B]
   
     // Other initialisation

}

void dummy_function(void)
{
     // [B]do nothing[/B].
}

Any clues please as to what might cause this.

    Thanks
    Mohsin
0 Kudos
Reply
7 Replies

1,593 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by CodeRedSupport on Fri Jan 14 11:00:40 MST 2011
If I had to guess, I'd guess your StackHeapInit function (and also the dummy_function) uses the stack. The call subsequently initializes the (entire) stack to a predetermined value. If the function has local variables (or created a local frame), then one or more registers are corrupted. At the very least, the prolog restored a corrupt context to any registers stored on the stack.  The generated code isn't doing what you think it should, and the fact the same operation works when you do not make a call is a clear indication.
0 Kudos
Reply

1,593 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mohsin on Fri Jan 14 10:40:42 MST 2011
Thanks for your reply.  Even I have used the example code and it works fine.

As I was getting some odd behaviour on the LCD (on our hardware)  I was able to catch the error.


[LIST]
[*]As said earlier, I was getting the odd behaviour even if I removed all the stack check code and just put a dummy function in the reset handler.
[/LIST]

[LIST]
[*]Doing the initialisation within the reset handler without calling another function seems to solve the problem (as far as I am not getting any odd behaviour on the LCD and the code is also working as expected).
[/LIST]
But still I think we need to get to the buttom of this issue.
         Regards,
         Mohsin
0 Kudos
Reply

1,593 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by CodeRedSupport on Thu Jan 13 07:45:34 MST 2011
This isn't an example that we at CodeRed are particularly familar with, as it is one of NXP's examples.

The reason for suggesting moving the call to StackHeapInit() from the start of ResetISR() is that we would not normally recommend making an calls before the startup code has carried out the copying/initialisation of any global data.

However I have just had a quick look at the source code, and I believe that the call to StackHeapInit() here probably wouldn't cause any problem as it doesn't appear to use any global data directly.

I've also just tried running the version of this application that ships with LPCXpresso v3.6.1 (which is looks to be slightly updated compared to the version that is available on the NXP website), and it seems from my very quick test to execute as I would perhaps expect.

Thus I would suggest considering upgrading to LPCXpresso 3.6.1 and testing the version of the code that provides.

However as you mention LCD, you  are obviously not running this code on a vanilla LPCXpresso1114 board? So can you provide details of your hardware, and also information on any changes you have made to the example code itself.

Regards,
CodeRedSupport
0 Kudos
Reply

1,593 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mohsin on Thu Jan 13 03:53:42 MST 2011
Thanks for your reply. I am using LPCXpresso v3.5.6 [Build 234] [04/11/2010].

1) If I do the initialisation just before the call to __main() it still does not work properly.

Also I have noted that using the debugger we can see the LCD not working properly but while loading the hex file using flash magic, it happens but not that often.

I have also seen the linker file in the stack example has the following comment. But I am getting odd behaviour even without using the debugger.

/*
    Note: (ref: M0000066)
    [COLOR=Red]Moving the stack down by 16 is to work around a GDB bug.
    This space can be reclaimed for Production Builds.[/COLOR]
*/   
    _vRamTop = __top_RamLoc8 ;
    _vStackTop = _vRamTop - [COLOR=Red]16[/COLOR];


Below is my reset handler:

void Reset_Handler(void)
{
    unsigned char *pulSrc, *pulDest;

    //
    // Copy the data segment initializers from flash to SRAM.
    //
    pulSrc = &_etext;
    for(pulDest = &_data; pulDest < &_edata; )
    {
        *pulDest++ = *pulSrc++;
    }

    //
    // Zero fill the bss segment.
    //
    for(pulDest = &_bss; pulDest < &_ebss; pulDest++)
      *pulDest = 0;

#ifdef __USE_CMSIS
    SystemInit();
#endif
   
    /*
    **    Iinitialise the stack with a constant.
    */
    [FONT=Arial][COLOR=Red][SIZE=2]StackHeapInit[/SIZE][/COLOR][/FONT][COLOR=Red]();[/COLOR]

   
    //
    // Call the application's entry point.
    // __main() is the entry point for redlib based applications (which calls main())
    // main() is the entry point for newlib based applications
    //
    if (__main)
        __main() ;
    else
        main() ;

    //
    // main() shouldn't return, but if it does, we'll just enter an infinite loop
    //
    while (1) {
        ;
    }
}

Can you please suggest me what is the right solution ?
   Regards,
   Mohsin
0 Kudos
Reply

1,593 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by CodeRedSupport on Wed Jan 12 22:49:54 MST 2011
You need to move your calls below the "other initialisation" in ResetISR.  You didn't specify the LPCXpresso release you're using, and the ResetISR code is different depending on the release. It was recently updated. The "other initialisation" code should zero fill the .bss section, then copy the .data section initial values from flash to their RAM runtime location. An additional call is provided to initialise the C++ library (if used). If you're using RedLib, there's also a call to __main(). This performs the RedLib before branching to your main() routine. Probably the best place to do your initialisation is just before the call to __main().


Quote: mohsin
Thanks for your reply. Can you please provide some information on how to [FONT=Arial][SIZE=2]relocate the call to  StackHeapInit (or dummy_function) [I]after [/I]the .bss and .data initialization?

Regards,
Mohsin

[/SIZE][/FONT]

0 Kudos
Reply

1,593 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mohsin on Wed Jan 12 14:06:57 MST 2011
Thanks for your reply. Can you please provide some information on how to [FONT=Arial][SIZE=2]relocate the call to  StackHeapInit (or dummy_function) [I]after [/I]the .bss and .data initialization?

Regards,
Mohsin

[/SIZE][/FONT]
0 Kudos
Reply

1,592 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by CodeRedSupport on Wed Jan 12 13:10:15 MST 2011
[FONT=Arial][SIZE=2]
Relocate the call to  StackHeapInit (or dummy_function) [I]after [/I]the .bss and .data initialization, and report back. [/SIZE][/FONT]
0 Kudos
Reply