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
When trying to start the RTOS first task, the processor drops in to
static void prvPortStartFirstTask( void )
" 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 SVCHandler and xPortPendSVCHandler PendSVHandler are present in the freeRTOSconfig.h (it was autogenerated by CubeMX)
I am using:
Eclipse with GCC
8k heap size
512byte task size
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, r0which goes on and on.
/* USER CODE BEGIN HardFaultIRQn 0 */
" 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 HardFaultIRQn 0 /
/ USER CODE BEGIN HardFaultIRQn 1 */
/* USER CODE END HardFault_IRQn 1 */
void prvGetRegistersFromStack( uint32t 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 uint32t r1;
volatile uint32t r2;
volatile uint32t r3;
volatile uint32t r12;
volatile uint32t 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. */
for( ;; );
Normally when people report a fault on the SVC 0 line it is not actually
that line that is causing the fault. What is actually happening is the
SVC 0 line jumps to the SVC handler which starts the first task, and the
first task is entered, and it is actually the task that causes the
fault.....but the debugger does not follow that sequence and it appears
as if it is the SVC 0 line that causes the fault.
Could that be happening in your case.
Try placing a break point in the SVC handler to see if it ever gets hit.
The SVC handler is called vPortSVCHandler() as is implemented in
thanks for the quick reply, I knew I forgot to add something, I did put a breakpoint in the SVC handler and no dice, I didn't reach the breakpoint, straight to the fault handler.
Is it possible that an interrupt is executing between the cpsie i
instruction and the SVC 0 instruction?
It's possible but I don't think so.
the peripherals are configured before the kernel is started with the standard cubeMX generated calls but the interrupts I didn't think were started until later in the user code. There's no user code between the set up routines and the call to the RTOS kernel.
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
/* USER CODE BEGIN 2 */
// HALGPIOWritePin(GPIOE, GPIOPIN9, GPIOPINSET);
// HALGPIOWritePin(LEDBatteryoutGPIOPort, LEDBatteryoutPin, GPIOPINRESET);
// HALGPIOWritePin(GPIOE, GPIOPIN9, GPIOPINRESET);
// HALGPIOWritePin(LEDBatteryoutGPIOPort, LEDBatteryoutPin, GPIOPINSET);
/* USER CODE END 2 */
/* Call init function for freertos objects (in freertos.c) */
/* Start scheduler */
Following on from Richard's comment about interrupts, i started digging and found some strange things happening with the systick timer (tim6). it appears to be set twice, once from halinit() and once from systemClockconfig(). it also appears to have an interrupt flag set just as the SVC 0 call is made. Currently, I am not seeing any change to the timer 6 configuration when I change the clock times in cubeMX so by increasing the clock frequency in cubeMX, this may be causing the issue seen. I will investigate further.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.