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...
解決済! 解決策の投稿を見る。
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.
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.
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
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.
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.