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 ) ?
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.
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
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:
Change the HAL to use a timer other than the SysTick as shown in the image below:
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.
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.