We are using the IMXRT1052 with the FreeRTOS port provided by the MCUXpresso SDK.
I've recently seen a problem where FreeRTOS looks like it is corrupting the Cortex-M7 Main Stack Pointer (MSP).
We have a main() function which creates an object and some other variables on the MSP (so, an automatic). The object creates a FreeRTOS timer to call one of its methods. The main() function then creates some tasks, and starts the FreeRTOS scheduler. I place a breakpoint in the timer function created by the object, and when it occurs, I find that the object data is corrupted (this is a problem because the timer function makes use of this data!).
Investigating further at this breakpoint, I find that the MSP pointer (the stack on which the object was created) has a *higher* address than it was immediately before the RTOS scheduler was started (e.g. the MSP before RTOS entry is 0x81ffff20, and when the first timer function is entered, it is at 0x81ffffe0), which may well explain why the data is corrupted!
When I dig a little deeper, I find that the FreeRTOS porting function prvPortStartFirstTask() in port.c has an instruction ("msr msp, r0") which explicitly sets the stack pointer back to the MSP address at the start of the application vector table (which is 0x82000000).
Is there any reason why the FreeRTOS port does this to the MSP? This is *not* part of any context switch; this is done with the Process Stack Pointer (PSP), not the MSP.
The items placed on the stack by the main() function should still be there (i.e. the main() function never exits) and so I would say it is not correct for them to be corrupted in this way.
That is a nasty thing to do. It took us 3 1/2 man days to find the cause of our corruption. And of course having found your nastiness it's easy to find this post. Welcome to the club if you've just found my comment after wasting 3 days everyone else.
Thanks for your fast response; I think I will remove this instruction in our copy.
It is quite surprising, I must say, personally, I (and my colleague!) thought doing this with the stack is a little dodgy; I don't suppose NXP would consider removing the instruction?
Failing that, perhaps it should be mentioned in a document somewhere (is there any SDK documentation, perhaps)?
As an add-on: that FreeRTOS port is described in the following article: FreeRTOS: how to End and Restart the Scheduler
Thanks Erich - that's a useful post!
good observation! On Cortex-M, the MSP stack is used for the interrupts (they stack on the MSP).
So with resetting the MSP it makes the whole stack size typically allocated for the startup/main() available for the interrupts.
The default port for M3/M4/M7 does this, because there is a vector table offset register used for this.
For M0(+) the default port does not do this, because not all ports have this.
So technically it should not be a problem for you to disable/remove that stack reset.
On the other side it might be better if you would have that variable(s) on the MSP stack as normal variables: that way you can fully re-use the MSP stack?
I hope this helps,