remaping stack from internal to external RAM

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

remaping stack from internal to external RAM

Jump to solution
1,928 Views
hartmutmeyer
Contributor II

I am using the LPC4357 with 32 MB SDRAM.

This extenal SDRAM needs to be initialized before it can be used,

doing this there is internal RAM required for startup.s and system.c

as well the default stack is located in internal RAM.

The board actualy in use has only 136 KB internal RAM,

splitted into different regions, so the max usable is only 64 KB ( 72 KB ).

My application requires more stack as is available after longer runtime

and a crash occures of course  if running out of stack.

Are there any examples how to use a stack in external SDRAM,

after initialization has completed ? Is this possible at all ?

I am using already a scatter-load-description file where stack and heap is

already defined there as regions.

I am also using "__user_setup_stackheap" what results in using the allocated heap,

but the stack will still be used from internal RAM.

Basicaly, the application is working but quite useless if stack-overflow occures...

Labels (2)
0 Kudos
1 Solution
1,360 Views
hartmutmeyer
Contributor II

Thanks for the hints, I have managed now to get the stack running from external SDRAM.

The application is running very well now without any stack-issues.

Finaly, all the declared stuff for the stack is not needed and may be removed.

Instead I am using now an assembler-file "userStack.s":

              AREA     USRSTACK,    CODE,    READONLY,    ALIGN=3

              EXPORT     ustack  

ustack   LDR  SP, =0x29DFFFF0               

             BX      LR

             ALIGN

             END

This code will be called within main()  just after systemInit():

main()

{

...

systemInit();

userInitStackHeap();

userStack();

...

}

The stack will grow down from the hardcoded address in upper SDRAM-region

and the user is responsible to reserve enough space here,

there must not occure collisions with heap, program-data or the framepointer.

Using __asm is possible as well instead of userStack.s:

__asm void userStack(void)

{

  LDR   SP, =0x29DFFFF0

  BX      LR

  ALIGN

}

Changing the stack already in userInitStackHeap() didn't work for my application, therefore there are two files.

The values are only working examples and are subject to change of course.

View solution in original post

0 Kudos
4 Replies
1,361 Views
hartmutmeyer
Contributor II

Thanks for the hints, I have managed now to get the stack running from external SDRAM.

The application is running very well now without any stack-issues.

Finaly, all the declared stuff for the stack is not needed and may be removed.

Instead I am using now an assembler-file "userStack.s":

              AREA     USRSTACK,    CODE,    READONLY,    ALIGN=3

              EXPORT     ustack  

ustack   LDR  SP, =0x29DFFFF0               

             BX      LR

             ALIGN

             END

This code will be called within main()  just after systemInit():

main()

{

...

systemInit();

userInitStackHeap();

userStack();

...

}

The stack will grow down from the hardcoded address in upper SDRAM-region

and the user is responsible to reserve enough space here,

there must not occure collisions with heap, program-data or the framepointer.

Using __asm is possible as well instead of userStack.s:

__asm void userStack(void)

{

  LDR   SP, =0x29DFFFF0

  BX      LR

  ALIGN

}

Changing the stack already in userInitStackHeap() didn't work for my application, therefore there are two files.

The values are only working examples and are subject to change of course.

0 Kudos
1,360 Views
lpcxpresso_supp
NXP Employee
NXP Employee

It sounds like you're not using  __user_setup_stackheap() correctly. Your startup code only needs an initial stack sufficient to complete the early setup. You can define more than one stack region in your startup code. Once you've configured the external SDRAM, change the stack pointer. Check this link for more info.:

http://www.keil.com/support/man/docs/armlib/armlib_chr1359122863069.htm

You didn't say whether you're using an RTOS. Stack setup can differ depending on the RTOS. Some allocate stack space from the heap, others use static memory (or both).

Thanks and regards,

LPCXpresso Support

0 Kudos
1,360 Views
hartmutmeyer
Contributor II

RTOS is not used in my application.

The default stack and heap is now set to 0x400 only.

In the application there will be done iterative deepening,

the demand for stack may grow depending on runtime.

There is defined in "stackheap.h" :

#define    USER_HEAP_BASE    0x28801000

#define    USER_HEAP_SIZE      0x01400000

In main.c there will be executed "userInitStackHeap():

#include    "stackheap.h"

__asm  void  userInitStackHeap(void)

{

    IMPORT     __use_two_region_memory

    EXPORT    __user_setup_stackheap

    EXPORT    __heap_base

    EXPORT    __heap_limit 

 

__heap_base  EQU    USER_HEAP_BASE

__heap_limit    EQU   USER_HEAP_BASE + USER_HEAP_SIZE

__user_setup_stackheap

    LDR     R0, =  __heap_base

    LDR     R2, =  __heap_limit 

    BX    LR

    ALIGN

}

I use scatter-load-description as well:

LR_IROM1    0x1A000000    0x00080000  {

  ER_IROM1    0x1A00.0000   0x00080000  {

    *.o (RESET, +First)

    *(InRoot$$Sections)

    .ANY (+RO)

   }

  RW_IRAM1    0x10000000    0x00008000  {

     system_LPC43xx.o  (+RW +ZI)

   }

  RW_IRAM2    0x20000000    0x00010000  {

     startup_LPC43xx.o  (+RW +ZI)                           ; may be put in RW_IRAM1 as well

  }

  RW_RAM1   0x28000000     0x01DFFFFF  {

     .ANY   (+RW +ZI)

  }

ARM_LIB_HEAP      0x28801000    EMPTY   0x1400000  {}

ARM_LIB_STACK   0x29DF0000    EMPTY      -0x40000 {}

}

The application is working and heap is fully used,

but the stack will not be remaped.

0 Kudos
1,360 Views
bernhardfink
NXP Employee
NXP Employee

You can put the stack pointer to wherever you like at any point in time, just by changing the content of the stack pointer register. The stack is a hardware controlled mechanism, so from the point in time you set the SP register to a specific address it will work from there.

This means that for the basic initialization tasks you need to provide an address in internal RAM. After the external SRAM or SDRAM has been made accessible (whenever this is) you can change the stack pointer to an external address. Using an intrinsic or an assembler instruction.

What you should avoid at this point in time is the usage of application functions (for example interrupts) which use the stack. Otherwise you might lose something when you switch the stack pointer.

To emphasize it again:  the initial setting of the stack pointer is required, but if you do this with a linker macro or if you set it in assembler in startup.s or in C in the cr_startup_xxxx.c file is in principle a don't care. 

For the heap it's different, that's a software controlled memeory area and the embedded libraries or any other heap management from an RTOS needs to know the position and the size of this area. But the same principle applies to the heap settings. You only need to have it set before it is used. 

It is not something the linker needs to know, you can do the required things in code as well. But one thing of course needs to be considered: if you don't give the linker this information, then you need to keep the area you intend to use for stack & heap free, so don't provide it to the linker as available area.

Regards,

NXP Support Team.

0 Kudos