SVC call causing hard fault

sgilbert wrote on Wednesday, January 10, 2018:

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 PendSV_Handler 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, r0which goes on and on.

void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 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 HardFault_IRQn 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 uint32_t r0;
volatile uint32_t r1;
volatile uint32_t r2;
volatile uint32_t r3;
volatile uint32_t r12;
volatile uint32_t lr; /* Link register. */
volatile uint32_t 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( ;; );
}

rtel wrote on Wednesday, January 10, 2018:

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
FreeRTOS/source/portable/[compiler]/ARM_CM4F/port.c

sgilbert wrote on Wednesday, January 10, 2018:

Hi Richard,

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.

rtel wrote on Wednesday, January 10, 2018:

Is it possible that an interrupt is executing between the cpsie i
instruction and the SVC 0 instruction?

sgilbert wrote on Wednesday, January 10, 2018:

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. */
 HAL_Init();

 /* USER CODE BEGIN Init */

 /* USER CODE END Init */

 /* Configure the system clock */
 SystemClock_Config();

 /* USER CODE BEGIN SysInit */

 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_ADC1_Init();
 MX_CRC_Init();
 MX_DAC_Init();
 MX_I2C1_Init();
 MX_I2C2_Init();
 MX_SPI1_Init();
 MX_SPI4_Init();
 MX_UART4_Init();
 MX_USART1_UART_Init();
 MX_TIM7_Init();

 /* USER CODE BEGIN 2 */

//  while(1)
//  {
//	  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, GPIO_PIN_SET);
//	  HAL_GPIO_WritePin(LED_Battery_out_GPIO_Port, LED_Battery_out_Pin, GPIO_PIN_RESET);
//	  HAL_Delay(1000);
//	  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, GPIO_PIN_RESET);
//	  HAL_GPIO_WritePin(LED_Battery_out_GPIO_Port, LED_Battery_out_Pin, GPIO_PIN_SET);
//	  HAL_Delay(1000);
//  }

 /* USER CODE END 2 */

 /* Call init function for freertos objects (in freertos.c) */
 MX_FREERTOS_Init();

 /* Start scheduler */
 osKernelStart();

sgilbert wrote on Wednesday, January 10, 2018:

Quick update:

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 hal_init() and once from systemClock_config(). 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.

@sgilbert
I exactly get the same issue. Hard fault after:
" svc 0 \n" /* System call to start first task. */

The two times call for HAL_InitTick() I get too and I have no idea what happens respectively how I may fix the hard fault.

How did you fix it?

The similar problem after calling prvPortStartFirstTask() somehow program jumps to empty SVC_Handler() instead of to vPortSVCHandler() and then crashes.
Development is in the Cube IDE for stm32F407 MCU.
The Kernel was used from the latest FreeRTOS LTC version. Did anybody find solution?

Does your FreeRTOSConfig.h have these lines?

#define vPortSVCHandler    SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

Thanks.

Yes, it does, but I commented them out because of was getting multiple definition of ‘SVC_Handler’ error, as result of its definition presence in both FreeRTOSConfig.h and port.c files.

Thanks.

It was bad idea to comment them out in FreeRTOSConfig.h. I have to find other way to solve multi definition error.
Thanks Gaurav, I found temporary solution, just excluded from compilation …/Core/Src/stm32f4xx_it.c and don’t have now multiple definition errors. Do you have any other suggesting?

Remove the other definitions which most probably should be in a file named like stmxxxxx_it.c.

If you are using STM32Cube IDE, the best way to generate a FreeRTOS project is to follow the following steps:

  1. Enable FreeRTOS in the configuration tool: Middleware --> FreeRTOS --> Interface.
  2. Change HAL Tick from SysTick to some other timer (say TIM6): System Core --> SYS --> Timebase Source.

If you follow these steps, the generated stmxxxxx_it.c file will be correct and won’t have duplicate symbols.

If you then want to replace FreeRTOS with the latest version, you can replace in the Middlewares\Third_Party\FreeRTOS directory in the generated source.

The default generated project will have CMSIS wrapper which is not necessary - you can delete it and directly use FreeRTOS APIs.

Thanks.

Thank you Gaurav very much. It is very helpful.
Also question regarding adding to existing FreeRTOS software in stm32CUBE IDE module for FreeRTOS + TCP. What should I take in account in order to avoid conflicts with the existing RTOS files?

You can only compile one copy of FreeRTOS in your project. So there should be no issue when you add FreeRTOS+TCP.

Thanks.