STM32CubeMX is a very easy to use configuration and code generation tool for STM32 microcontrollers. It comes with middleware packages, like FreeRTOS. By default, FreeRTOS is indirectly invoked via CMSIS-OS wrapper APIs which are designed to switch between different underlying OSes such as FreeRTOS, RTX Kernel. However, employing CMSIS-OS wrapper APIs is not succinct, causing difficulties for using FreeRTOS documents and libraries.
In this article, I will show how to use native FreeRTOS in my STM32F0Discovery board. Tools involved are STM32CubeMX and STM32CubeIDE, both of which are provided for free by STMicro.
Configuration and Code Generation
STM32CubeMX is used to configure the MCU and generate initialization code.
First, click File -> New Project, then in the opened dialog, select STM32F0Discovery, and click Start Project.
In FREERTOS tab of Pinout & Configuration view, select CMSIS-V1 as FreeRTOS interface.
In SYS tab of Pinout & Configuration view, select TIM1 as timebase source. It is recommended to use a HAL timebase source (TIM1, in this case) other than systick.
In Project tab of Project Manager view, fill in a project name and a toolchain/IDE (STM32CubeIDE, in this case).
After the above steps, click GENERATE CODE, and wait for a few seconds. Then open the project in STM32CubeIDE.
Removing CMSIS-OS Wrapper
To get rid of CMSIS-OS wrapper, we need to copy FreeRTOS headers to main.h first.
In main.c of the opened project, find the following line (it can be deleted after copying FreeRTOS headers to main.h):
#include "cmsis_os.h"
Right click on the file name “cmsis_os.h”, and choose Open Declaration.
In cmsis_os.h, find the following lines:
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.h"
Copy the 6 lines above to main.h, put them below the following line:
#include "stm32f0xx_hal.h"
Then we can delete example code generated by STM32CubeMX.
In main.c, find and delete the following lines:
#include "cmsis_os.h"
// ...
osThreadId defaultTaskHandle;
// ...
void StartDefaultTask(void const * argument);
// ...
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
// ...
osKernelStart();
// ...
void StartDefaultTask(void const * argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for(;;)
{
osDelay(1);
}
/* USER CODE END 5 */
}
Blinking LEDs
The STM32F0Discovery board comes with two user LEDs, green LD3 and red LD4. To verify whether the native FreeRTOS works, I create two dummy tasks, each toggling one of the LEDs every 1000 microseconds.
First, declare prototypes of two task functions after /* USER CODE BEGIN 0 */.
void vTask1(void *pvParameters);
void vTask2(void *pvParameters);
Create two tasks after /* USER CODE BEGIN RTOS_THREADS */.
xTaskCreate(vTask1, "Task 1", 256, NULL, 1, NULL);
xTaskCreate(vTask2, "Task 2", 256, NULL, 1, NULL);
Start the FreeRTOS scheduler after /* Start scheduler */.
vTaskStartScheduler();
Then implement the two task functions after /* USER CODE BEGIN 4 */.
void vTask1(void *pvParameters)
{
for(;;)
{
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
vTaskDelay(1000);
}
}
void vTask2(void *pvParameters)
{
for(;;)
{
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
vTaskDelay(1000);
}
}
Finally, build the project, upload it to the STM32F0Discovery board. The two user LEDs blink as expected.
This was really helpful. Thank you
‘defaultTask’ will be olways generated / regenerated by CubeMX.
I see sadly no other solution than manual removing CubeMX generated code like:
osKernelStart();
after every regeneration, after every smallest change in ‘configuration tool’.
I find it very bad solution from side of STM32CubeMX defelopers team.
This info is very helpfull. Thanks
Of course that every time that code is re-generated, cubemx will add the code corresponding to the deleted one
I’ve experienced bugs with cmsis os