Hi all,
I have seen similar faults described elsewhere and have tried all the recommendations I found so far so but no luck yet so apologies if this has been covered to death. I am relatively new to using freeRTOS so apologies if I haven’t included all the information
The problem:
When trying to start the RTOS first task, the processor drops in to
~~~
static void prvPortStartFirstTask( 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.
/
” cpsie f n”
” dsb n”
” isb n”
” svc 0 n” / System call to start first task. */
” nop n”
);
}
~~~
and by stepping through the assembly code, I get to svc 0 and then the micro immediately falls in to a hard fault handler.
I initially had 3 simple tasks; 1 sets up an LCD and displays a splash screen and 2 blank tasks. This worked, and I stored it on my work respository. When I began to build up one of the blank tasks to send and recieve basic serial commands I ran in to hard fault issues. After some fettling later I can’t even even get past the start first task function. I reverted to my known working version from the repository and still no joy.
the #define vPortSVCHandler SVC
Handler and xPortPendSVCHandler PendSVHandler are present in the freeRTOSconfig.h (it was autogenerated by CubeMX)
I am using:
STM32f427
Eclipse with GCC
CubeMX
FreeRTOS 9
heap4
8k heap size
512byte task size
3 tasks
If anyone has any advice or recommendations I would truly apreciate it, I am going round in circles.
It is possibly worth noting, I modified the fault handler to help track down the issue using the code bellow but I get to line
bx r2
and the compiler jumps to a random line of
movs r0, r0
which goes on and on.
~~~
void HardFault
Handler(void)
{
/* USER CODE BEGIN HardFaultIRQn 0 */
__asm__("BKPT");
__asm volatile
(
" tst lr, #4 n"
" ite eq n"
" mrseq r0, msp n"
" mrsne r0, psp n"
" ldr r1, [r0, #24] n"
" ldr r2, handler2_address_const n"
" bx r2 n"
" handler2_address_const: .word prvGetRegistersFromStack n"
);
/* USER CODE END HardFault
IRQn 0 */
while (1)
{
}
/* USER CODE BEGIN HardFaultIRQn 1 */
/* USER CODE END HardFault_IRQn 1 */
}
void prvGetRegistersFromStack( uint32
t *pulFaultStackAddress )
{
/* These are volatile to try and prevent the compiler/linker optimising them
away as the variables never actually get used. If the debugger won’t show the
values of the variables, make them global my moving their declaration outside
of this function. */
volatile uint32t r0;
volatile uint32
t r1;
volatile uint32t r2;
volatile uint32
t r3;
volatile uint32t r12;
volatile uint32
t lr; /* Link register. */
volatile uint32t pc; /* Program counter.
/
volatile uint32_t psr;/ Program status register. */
r0 = pulFaultStackAddress[ 0 ];
r1 = pulFaultStackAddress[ 1 ];
r2 = pulFaultStackAddress[ 2 ];
r3 = pulFaultStackAddress[ 3 ];
r12 = pulFaultStackAddress[ 4 ];
lr = pulFaultStackAddress[ 5 ];
pc = pulFaultStackAddress[ 6 ];
psr = pulFaultStackAddress[ 7 ];
/* When the following line is hit, the variables contain the register values. */
__asm__("BKPT");
for( ;; );
}
~~~