Getting a hardfault with two threads

So i’m learning FreeRTOS on STM32 and currently following a tutorial to get things started. Following are my concerns with the first one being the most:

  • I have two threads, but upon running a scheduler, I see a hardfault. But when I run a single thread, I see no issues. I initially thought it’d be related to the stack size but each thread is taking up 130 * 4 = 520 bytes.

  • TaskHandle_t is a pointer to struct tskTaskControlBlock. Then why is the address of the xTaskBlinky passed to the last parameter of xTaskCreate(), which takes TaskHandle_t * const pxCreatedTask )?

     // main.c
    
     TaskHandle_t xTaskBlinky = NULL;
     TaskHandle_t xTaskBlinky1 = NULL;
     
     void vTask1_Handler(void *params);
     void vTask2_Handler(void *params);
     
     void SystemClock_Config(void);
    
     int main(void)
     {
     	/* MCU Configuration--------------------------------------------------------*/
     
     	/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
     	HAL_Init();
     
     	/* Configure the system clock */
     	SystemClock_Config();
     
     	xTaskCreate(vTask1_Handler, "Blinky", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskBlinky);
     	xTaskCreate(vTask2_Handler, "Blinky1", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskBlinky1);
     
     	vTaskStartScheduler();
     	while (1);
     }
    
     void vTask1_Handler(void *params)
     {
     	while(1);
     }
     
     void vTask2_Handler(void *params)
     {
     	while(1);
     }
    

    And the program goes into the infinite loop upon running a scheduler:

      * @brief  This is the code that gets called when the processor receives an 
      *         unexpected interrupt.  This simply enters an infinite loop, preserving
      *         the system state for examination by a debugger.
      * @param  None     
      * @retval None       
     */
         .section  .text.Default_Handler,"ax",%progbits
     Default_Handler:
     Infinite_Loop:
       b  Infinite_Loop
       .size  Default_Handler, .-Default_Handler

but each thread is taking up 130 * 4 = 520 bytes .

How do you determine that? Is that the value of configMINIMAL_STACK_SIZE?

TaskHandle_t is a pointer to struct tskTaskControlBlock . Then why is the address of the xTaskBlinky passed to the last parameter of xTaskCreate() , which takes TaskHandle_t * const pxCreatedTask ) ?

The last parameter to xTaskCreate() is an output parameter to return the handle of the created task. You can find the detailed documentation of xTaskCreate() here: This page describes the RTOS xTaskCreate() FreeRTOS API function which is part of the RTOS task control API. FreeRTOS is a professional grade, small footprint, open source RTOS for microcontrollers.

Where did you get the project from? The line you show is a default handler - how do you determine that it is hard fault? Are SVC_Handler, PendSV_Handler and Systick_Handler installed correctly as mentioned on this page: FreeRTOS - Open Source RTOS Kernel for small embedded systems. You should also try the other debugging options (like defining malloc failed hook, defining configASERT) described on the same page.

See this page for specifically debugging hard fault: Debugging and diagnosing hard faults on ARM Cortex-M CPUs

Thanks.

Well, 130 is the value of configMINIMAL_STACK_SIZE

SCB->ICSR->VECTACTIVE is 0x3 indicating it’s a hardfault

And I have the following defined inside stm32f4xx_it.h , but wondering if i really need this file if i’m using freertos.

void PendSV_Handler(void);
void SysTick_Handler(void);
void SVC_Handler(void);

Looks like the interrupts are defined in port.h but even excluding stm32f4xx_it.h from the project didn’t help

Where did you get this project from? Do you have the following in your FreeRTOSConfig.h:

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

Thanks.

Yes, I have these #defines in FreeRTOSConfig.h. And I created an STM32 Project in eclipse, and copied over the kernel files

Please follow the instructions here to determine what is causing hard fault: https://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

If you share your project, I can take a look too.

Thanks.

Recommend making sure you replace the default handler on interrupt vectors with a handler that lets you know which interrupt it was that occurred. Alternatively you can add some assembly code to the handler to determine with interrupt is being processed - more info on that here https://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

Also suggest you have configASSERT() defined, stack overflow protection set to 2, are using a very recent version of FreeRTOS to benefit from additional programmatic checks that your configuration matches the hardware, a malloc failed hook defined, etc. This is the best starting place to learn about these things: https://www.freertos.org/FAQHelp.html

any way I could attach a project?

You can use any means to share - Google Drive, GitHub, or Anything else etc.

https://drive.google.com/drive/folders/1S8ODYQOFWbV67VkJmMrhxWgr3L9yYS7r

replace the default handler on interrupt vectors with a handler that lets you know which interrupt it was that occurred.

thing is all NVIC registers are 0. which handler would let me know about the interrupt that occurred?

you have configASSERT() defined, stack overflow protection set to 2

are you referring to configCHECK_FOR_STACK_OVERFLOW?

You are excluding the file stm32f4xx_it.c from compilation which excludes the following default SysTick_Handler:

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

The result is that the HAL_IncTick(); is never called and the ST HAL won’t work. The correct way to do is the following:

  1. Change the HAL to use a timer other than the SysTick as shown in the image below:
  2. Remove the definition of SysTick_Handler, PendSV_Handler and SVC_Handler from both stm32f4xx_it.h and stm32f4xx_it.c but do not exclude these files.

Another issue is that the include paths are configured to full paths on your machine which do not exist on other machines. Better to use relative paths there.

Thanks.

Thanks for taking your time out.

Regards to your comments, it would complain if I didn’t have SysTick_Handler() commented out cause it’s it’s defined inside port.c and declared in FreeRTOSConfig.h
#define xPortSysTickHandler SysTick_Handler

Is the main reason behind not using SysTick is to avoid the conflict with the definition in port.c?

Yes, we do not want to use the default SysTick_Handler, PendSV_Handler and SVC_Handler in stm32f4xx_it.c and therefore I asked you to comment those out. Do not exclude the file from project because other handlers in the file stm32f4xx_it.c are still needed.

Is the main reason behind not using SysTick is to avoid the conflict with the definition in port.c ?

Yes, we want to use SysTick_Handler, PendSV_Handler and SVC_Handler in port.c.

Thanks.