thomask wrote on Tuesday, December 15, 2009:
Hi!
We’ve just discovered a potential problem of the Cortex-M3 port on the STM32. We’re using FreeRTOS 6.0.1 in a custom project based on the STM32 firmware library examples.
The problem shows up after starting the scheduler, and causes seemingly random data corruption.
The official start scripts provided in the Firmware Library set the initial stack to 0x20000400 after a reset:
CMSIS/Core/CM3/startup/gcc/startup_stm32f10x_hd.s:
.equ Initial_spTop, 0x20000400
g_pfnVectors:
.word Initial_spTop
.word Reset_Handler
.word NMI_Handler
So the processor will use 1kB of stack initially. The real stack value is initialized in the first few instructions of the reset handler:
LDR r0, =_estack // see linker script, typically 0x10000 on a 64k device.
MSR msp, r0
The problem is, that FreeRTOS’ vPortStartFirstTask() will _reset_ the stack pointer to the initial value taken from the NVIC table!
void vPortStartFirstTask( void )
{
__asm volatile(
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, \n"
" ldr r0, \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" svc 0 \n" /* System call to start first task. */
);
}
This will reload the MSP to 0x20000400 and causes hard-to-debug memory corruption afterwards.
There are two possible work-arounds:
- replace the NVIC lookup by “ldr r0,
=_estack \n”, and place a warning in the port’s documentation
- or convince ST to modify their start
scripts
I think, option 1 is the best solution. Option 2 is bad, because the stack might be in external RAM that needs initialization after reset.
best regards,
Thomas Kindler