as is recommended by ARM. In the event of a fault, the processor
switches to the MSP stack. So, to handle a fault, MSP needs to
be set up to point to a small dedicated stack. In your v7 M3 gcc port.c you have:
void vPortStartFirstTask( void )
{
__asm volatile(
" ldr r0, =0xE000ED08 n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] n"
" ldr r0, [r0] n"
" msr msp, r0 n" /* Set the msp back to the start of the stack. */
" cpsie i n" /* Globally enable interrupts. */
" svc 0 n" /* System call to start first task. */
" nop n"
);
}
That would cause a fault to overwrite whatever is at thebase of the (linker allocated) stack pool, no ?
For my M0 port, I changed it to this:
void vPortStartFirstTask( void )
{
#ifdef DRN_print_diagnostics
int answer = 46;
#endif
// Ensure that normal processing runs on PSP ("Process" Stack
// Pointer, in "thread mode" or "normal mode"). Processor starts
// out of reset using MSP, so unless the RTL has already switched, we
// need to switch here.
debug_printf("CONTROL register=%08x, stack in use is %sn",
__get_CONTROL(), (__get_CONTROL()&0x2) ? "PSP, OK." : "MSP, need to switch.");
if( (__get_CONTROL()&0x2) == 0 ) {
// Ooops, we're using MSP "Main" Stack Pointer
// Set up "process" stack pointer and switch to it
__set_PSP(__get_MSP()); // copy current stack pointer value into PSP
__set_CONTROL(0x00000002); // switch to "process" stack pointer PSP
debug_printf("After stack pointer switch: CONTROL register=%08x, stack in use is %sn",__get_CONTROL(), (__get_CONTROL()&0x2)?"PSP":"MSP");
debug_printf("The answer is %d (should be 46)n",answer); // verify stack is not munged
}
// Handler mode (as in processing a hard fault) ALWAYS uses MSP
// ('Main' stack pointer). So, in order for a fault to be trapped
// safely, MSP must point to a dedicated and safe stack area.
// Set MSP to a "safe reserved area", so an exception can run safely...
#define FAULT_STACK_SIZE 100
static int MSP_stack[FAULT_STACK_SIZE];
__set_MSP((int)&MSP_stack[FAULT_STACK_SIZE-2]);
__asm volatile(
" ldr r0, =0x0 n" /* cm0 has fixed vector table at address 0x0 */
" ldr r0, [r0] n"
// DRN: Next line is hazardous; MSP needs to point to a separate
// DRN: safe stack, otherwise a fault will clobber stack of someone else...
// DRN: NO: " msr msp, r0 n" /* Set the msp back to the start of the stack. */
" cpsie i n" /* Globally enable interrupts. */
" svc 0 n" /* System call to start first task. */
" nop n"
);
}
Do I have this right ?Also, does the built-in debug support use the MSP
(for example, to support semi-hosted IO, implemented
via BKPT instructions) ? Thanks as always,
Best Regards, Dave