void LED01Tog(void const * argument){ /* USER CODE BEGIN LED01Tog */ /* Infinite loop */ for(;;) { HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10); osDelay(500); } /* USER CODE END LED01Tog */}
We added two LED toggle functions, compiled our code, and found that the tasks could start normally.
MX_FREERTOS_Init(); /* Start scheduler */ osKernelStart();
The main function contains the function to initialize tasks and the function to enable task scheduling in CubeMX. In the task scheduling function, I found that it was just the line vTaskStartScheduler();
So it was very strange why this function could not schedule.
Then I commented out the HAL library functions, called the task scheduling function myself, and found that task scheduling was also functioning normally.
osThreadDef(LED02, LED02Tog, osPriorityIdle, 0, 128); LED02Handle = osThreadCreate(osThread(LED02), NULL); vTaskSuspend(LED02Handle); vTaskStartScheduler();
And it was also possible to successfully schedule vTaskSuspend to stop the task.
However, there is a situation that can lead to FreeRTOS startup failure.
When our timer is not configured as a hardware timer but uses the system timer instead, we are strongly advised not to use systick as the clock source when using FreeRTOS.
Because if the systick is selected, both the system clock and the operating system clock will rely on Systick. However, we need an interrupt to switch between tasks during task scheduling.
void SysTick_Handler(void){ /* USER CODE BEGIN SysTick_IRQn 0 */ /* USER CODE END SysTick_IRQn 0 */ HAL_IncTick();#if (INCLUDE_xTaskGetSchedulerState == 1 ) if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {#endif /* INCLUDE_xTaskGetSchedulerState */ xPortSysTickHandler();#if (INCLUDE_xTaskGetSchedulerState == 1 ) }#endif /* INCLUDE_xTaskGetSchedulerState */ /* USER CODE BEGIN SysTick_IRQn 1 */ /* USER CODE END SysTick_IRQn 1 */}
But using Systick may lead to task scheduling failures.
We can see that the priority of the system timer is the lowest, which is 15. At this point, if we use HAL_Delay during FreeRTOS task scheduling, it will lead to tasks not being scheduled properly.
That is to say, when calling HAL_Delay() in the interrupt function, we must ensure that the priority of systick is higher than that of the interrupt function.
Therefore, CubeMX recommends using a general-purpose timer as the system clock source.
In fact, there are many reasons that can lead to tasks not being scheduled in FreeRTOS, but most of the time they are related to the timer.
Just like last time when my counterfeit STM32 could not start, it was initially due to the inability to use the timer, which turned out to be a counterfeit chip, leading to FreeRTOS not starting scheduling.
Therefore, if your FreeRTOS encounters problems, it is worth checking whether the timer is functioning normally.