I've been reading various sections in the ARM Information Center to try and find my answer, however I came to a point where the documentation confused me so I'm hoping someone here can help.
I understand that there are two stacks in Cortex-M processors:
I'm trying to figure out how each one is used by the ARM core.
The documentation in the ARM Information Center when discussing the Cortex-M3 states the following:
The main stack is used at reset, and is always used in Handler mode (when entering an exception handler). The process stack pointer is only available as the current stack pointer when in Thread mode.
Okay, this tells me that the MSP is used at reset. However, the documentation also states the following:
Used to execute application software. The processor enters Thread mode when it comes out of reset.
Used to handle exceptions. The processor returns to Thread mode when it has finished all exception processing.
Okay, so this is what confuses me. If the MSP is used at reset and is always used in Handler mode, and the PSP is used in Thread mode, then how can the MSP be used at reset if the processor is in Thread mode at reset?
Simple answer: your final paragraph is incorrect. Thread mode uses the MSP by default.
You don't say what processor you're using, so let's assume a Cortex-M3. Check out the description of the CONTROL
register at the bottom of this page: the SPSEL
bit controls which stack is in use, defaults to MSP for both Thread and Handler mode, and is only writable in Thread mode.
Additionally, though it wasn't part of your question, Thread mode is privileged by default too. Setting the nPRIV
bit in the same register makes Thread mode unprivileged.
In summary: Handler mode is always privileged and always uses the MSP. By default, the same is true for Thread mode, but the CONTROL
register allows this to be changed.
A bit more context...
If you were writing a small operating system, for example, it would be typical to want Thread mode code to be unprivileged. It also makes task switching much easier if Thread mode code uses the PSP because then your task switch code, which will inevitably be running in Handler mode (typically in the PendSV handler on a Cortex-M), can make use of its own stack without affecting the stacks of the tasks it's trying to switch.
To do this, the operating system's initialisation code would typically have to (in this order):
MSR
instruction to make the PSP point to the top of this region (this requires privilege but also must be done from Thread mode because SPSEL
ignores writes in Handler mode)MSR
instruction to set the SPSEL
bit in the CONTROL
register, switching the running code to using the PSP and the newly-prepared stack spaceISB
instruction to ensure that all following instructions use the PSP as requiredMSR
once more to set the nPRIV
bit in the CONTROL
register, immediately removing privilege from Thread modeThe running Thread mode code then becomes the idle task.