Hello,
I am struggling with the placement of the stack in a LPC1769. This controller has two RAM banks, each 32kB. I was very surprised when my application started behaving weirdly today as the RAM usage only reached about 15.9kB (data variables suddenly changing their value, weird HardFault Exceptions). During debugging I discovered that the stack is placed at address 0x10004000, growing towards 0x10000000 where the data area starts (growing up). So effectively the stack starts at 16kB, growing towards the user data. Of course it collides with the data area very soon, even though the RAM is not used completely.
Now I want to move the stack at least to the end of the RamLoc32 area (alias RAM; the first 32kB RAM block), but even better to the RamAHB32 block (alias RAM2). I tried doing this in LPCXpresso and MCUXpresso with the option
--defsym=__user_stack_top=__top_RAM2
(placed under Project -> Properties -> C/C++ Build -> Settings -> MCU Linker -> Miscellaneous -> Other options), but this has no effect (in the user program, I read the initial stack pointer value with
uint32_t stack = __get_MSP();
but is always is around 10003900 and the application crashes again). In MCUXpresso I even tried the Heap and Stack placement in MCUXpresso Style under Project -> Properties -> C/C++ Build -> Settings -> MCU Linker -> Managed Linker Script, but this has no effect as well. After changing the setting, I cleaned and rebuilt the project, no effects at all.
Can someone help me out?
Kind regards,
Jan
There's no mechanism in play to setup the application stack pointer. When the board resets, the established boot context is that of the secondary bootloader. It's the responsibility of the secondary bootloader to establish the entire application boot context. The PC is the second vector, the SP is the first vector.
Thanks and regards,
MCUXpresso Support
You should read the FAQ section on the Freemarker linker templates. Create a "linkscripts" folder in your project, and locate the file stack.ldt there. The default stack.ldt file used is located in <install_dir>\ide\Wizards\linker. This template contains the line:
PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_${DATA} - ${STACK_OFFSET});
Replace the __top_${DATA} text with __top_${RAM2}
You should find your initial stack at the end of the RamAHB32 memory.
Thanks and regards,
MCUXpresso Support
Thanks for your fast reply! I didn't knew that MCUXpresso utilizes this tool. I will try it tomorrow.
Still, I think it is quiet confusing and I don't understand why my approach does not work. The MCUXpresso manual explicitly states that --defsym=__user_stack_top=__top_RAM2 should work (refer chapter 12.9.2), at least there it does not say anything about Freemaker. So why doesn't defsym work? The default linker file utilizes this__user_stack_top and you suggest to just remove it. Also, the current linker script generated by MCUXpresso (I didn't make any changes to Freemaker) states:
.stack ORIGIN(RamAHB32) + LENGTH(RamAHB32) - 0x800 - 0: ALIGN(4)
{
_vStackBase = .;
. = ALIGN(4);
_vStackTop = . + 0x800;
} > RamAHB32
So why does the __get_MSP() return something around 0x10004000 and not something around 0x2007c000 where RamAHB32 is located?
Possibly the tool is not resolving the RAM2 alias. Try
--defsym=__user_stack_top=__top_RamAHB32
This works for me.
Thanks and regards,
MCUXpresso Support
It didn't work with this setting. Anyway, I was using the MCUXpresso Managed Linker Scripts in MCUXpresso Style where I can select the stack location from a drop down list.
But, what I didn't thought about, was that my application uses the AN10866 secondary USB Bootloader. In this application, not a LPC1769 is configured, but a compatible, though less memory, LPC1764. If I change the setting in the bootloader project (or create a new project) and update the bootloader, the stack pointer actually moves to the desired location.
But why do I have to change this setting in the bootloader? Doesn't the linker script from my second location apply? Do I explicitly have to state in the bootloader code that my application should load the stackpointer etc. from the application code?
The bootloader starts the application with this:
#define USER_START_SECTOR 4
#define MAX_USER_SECTOR 17
...
#define USER_FLASH_START (sector_start_map[USER_START_SECTOR])
#define USER_FLASH_END (sector_end_map[MAX_USER_SECTOR])
...
void execute_user_code(void)
{
void (*user_code_entry)(void);
unsigned *p; // used for loading address of reset handler from user flash
/* Change the Vector Table to the USER_FLASH_START
in case the user application uses interrupts */
SCB->VTOR = (USER_FLASH_START & 0x1FFFFF80);
// Load contents of second word of user flash - the reset handler address
// in the applications vector table
p = (unsigned *)(USER_FLASH_START +4);
// Set user_code_entry to be the address contained in that second word
// of user flash
user_code_entry = (void *) *p;
DEBUG_OUT("Running user app from flash.\n");
// Jump to user application
user_code_entry();
}
So the vector table is updated. Shoudn't update this the Stack Pointer as well? My application is, of course, configured to start at 0x4000.
Thanks!
Jan