Home STM32 STM32 RTOS STM32 FreeRTOS Tutorial: Setup with CubeMX, Task Creation, and Priorities

STM32 FreeRTOS Tutorial: Introduction to Real-Time Operating Systems

FreeRTOS is a powerful real-time operating system (RTOS) for STM32 microcontrollers, enabling multitasking with precise control over task scheduling. In this tutorial, you’ll learn how to set up STM32 FreeRTOS using STM32CubeMX, create tasks, assign priorities, and understand why using FreeRTOS in STM32 is better than bare-metal code for complex embedded projects.

STM32 FreeRTOS Tutorial

This tutorial is the first installment in a comprehensive series and will focus on the following key topics:

  1. Setting up FreeRTOS using CubeMX – A step-by-step guide to configuring FreeRTOS in your project.
  2. Benefits of using an RTOS – Understanding why a real-time operating system is advantageous for embedded applications.
  3. Creating tasks with and without CubeMX – Exploring different approaches to task creation and management.
  4. Using priorities to address common issues – Leveraging task priorities to resolve scheduling and resource conflicts effectively.

VIDEO TUTORIAL

You can check the video to see the complete explanation and working of this project.

Check out the Video Below

What is FreeRTOS? (Real-Time OS Overview)

FreeRTOS (Free Real-Time Operating System) is an open-source, lightweight RTOS designed for microcontrollers like STM32. It enables task scheduling, inter-task communication, and real-time responsiveness. Developers use FreeRTOS in STM32 for multitasking, running sensors and comms stacks concurrently, and simplifying timing challenges in embedded systems.

This tutorial introduces RTOS (Real-Time Operating System) for STM32 microcontrollers. You will learn how to set up FreeRTOS using CubeMX, create tasks, and understand how using an RTOS can make your programs run more smoothly and efficiently. This is a great starting point for anyone looking to manage multiple tasks in STM32 projects.

Important Features of RTOS:

  1. Multitasking – Run multiple tasks at the same time without conflicts.
  2. Task Priorities – Make sure important tasks run first.
  3. Predictable Timing – Tasks respond quickly and reliably when needed.
  4. Communication Between Tasks – Tasks can share information safely using queues, semaphores, and mutexes.

STM32CubeMX FreeRTOS Configuration

The image below shows the configuration for the FreeRTOS.

STM32 FreeRTOS Configuration

I am choosing version 1, because it is supported by majority of STM32 devices.

Open the ‘Tasks and Queues‘ tab. Here you will see a predefined default task. Open it to see more information about this task.

FreeRTOS Default Task

The Task details are explained below:

  • Task Name: defaultTask – This is just the name of the task. You use this name in your code to work with this task.
  • Priority: osPriorityNormal – This decides how important the task is. Normal priority means it runs after high-priority tasks but before low-priority ones. It helps the CPU know which task to run first.
  • Stack Size (Words): 128 – This is the memory the task can use for its variables and function calls. Think of it as the workspace for the task.
  • Entry Function: StartDefaultTask – This is the function that will run when the task starts. You put the task’s code inside this function.
  • Code Generation Option: Default – CubeMX will generate the task using its standard method.
  • Parameter: NULL – If you wanted to give some information to the task when it starts, you could put it here. NULL means no information is passed.
  • Allocation: Dynamic – Memory for the task is given at runtime. The other option is static, where memory is reserved before the program runs.

We will create another task for the test. Below is the image showing the task properties.

FreeRTOS New Task

I am calling it Task2, with normal priority, 128 Stack Size and the entry function is defined as Task2_init. We will write this entry function in our code.

When using FreeRTOS, you cannot use the default SysTick timer for the system time base because FreeRTOS uses it internally to manage task switching and delays.
So, you need to choose a different timer as the time base for your system (like TIMx) in STM32CubeMX. This ensures the system clock keeps running correctly while FreeRTOS manages tasks.

RTOS Systick Timer setup

Why Use FreeRTOS in STM32 Projects

Imagine you want to toggle two pins at the same time, each with its own delay. With simple programming, this is hard because the microcontroller can only do one instruction at a time. So, the first pin has to finish toggling before the second one can start, even if both are inside a while loop.

This is where RTOS helps. By creating two separate tasks, each task can handle one pin independently. FreeRTOS will switch between the tasks quickly, making it appear as if both pins are toggling at the same time.

FreeRTOS tasks working

If you scroll down in the main.c file, you will see the entry functions for the tasks we defined in the cubeMX. These functions contain the code that runs for each task—one for each pin.

void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  for(;;)
  {
      HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
      osDelay(1);
  }
  /* USER CODE END 5 */ 
}

/* USER CODE BEGIN Header_Task2_init */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Task2_init */
void Task2_init(void const * argument)
{
  /* USER CODE BEGIN Task2_init */
  /* Infinite loop */
  for(;;)
  {
	  HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
	  osDelay(1);
  }
  /* USER CODE END Task2_init */
}

In this example, we toggle pin PA0 within the default task and pin PA1 within Task2. The FreeRTOS scheduler manages the execution, ensuring that both tasks receive sufficient CPU time to run properly.

The oscilloscope reading below shows the output when the above code was executed.

Oscilloscope showing the pin toggling

How to Create Tasks in STM32 FreeRTOS

In order to create a new Task, we have to follow some set of steps, and they are as follows:-

1.) Define a ThreadID for the task. This variable will store the unique ID of the task, once created. Later, all the operations will require this ID.

osThreadId Task3Handle;

2.) Define the entry function for the task. This is the main function of the task. Your program will be written inside it. Remember that the tasks in the Free RTOS, are not designed to handle any return value. So, the entry function should always have an infinite loop, inside which, your whole program should be written.

void Task3_init (void const * argument)
 {
     while (1)
     {
         // do something
         osDelay (1000);  // 3 sec delay
     }
 }

3.) Inside our main function, we need to define the task first and than create it.

// define thread
   osThreadDef(Task3, Task3_init, osPriorityBelowNormal, 0, 128);
   //create thread
   Task3Handle = osThreadCreate(osThread (Task3), NULL);
  • osThreadDef takes the parameters as the name of the task, the entry function, the priority, instance, and the stack size.
  • After the task is defined, we can create it using osThreadCreate, and assign the ID to the Task3Handle

Task Priorities in STM32 FreeRTOS (with Code)

So far, we have seen how to perform multitasking using FreeRTOS. However, using multiple tasks can sometimes lead to certain challenges. One common issue arises when multiple tasks try to access the same resource at the same time.

For example, consider sending data over UART from three different tasks simultaneously:

  • When we write a program for this, the transmission will not happen exactly at the same time.
  • Instead, each task will send its data one after another — the first task sends for 1 second, then the second task for another second, and so on.
  • This occurs because the tasks are sharing the same resource (UART) and have the same priority.
  • The second task has to wait for the first task to finish before it gets control, and similarly, the third task waits for the second.

To avoid these situations, we use different priorities for different tasks. That means we have to redefine our task priorities in the main function.

osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
osThreadDef(Task2, Task2_init, osPriorityAboveNormal, 0, 128);
osThreadDef(Task3, Task3_init, osPriorityBelowNormal, 0, 128);
  • Now the Task2 have the highest priority, than Default task, and Task3 have the lowest.
  • When the program runs, Task2 will execute first, than default task and at last the Task3.
  • All three tasks will send the data at the same time, with Task2 sending the data first, then default task and at last the Task3.
FreeRTOS tasks running with different priorities

In this STM32 FreeRTOS tutorial, we’ve explored how to configure RTOS using STM32CubeMX, create multiple tasks, and assign priorities. Using FreeRTOS in STM32 not only simplifies multitasking but also improves timing accuracy and application structure. Stay tuned for future guides on advanced FreeRTOS topics like queues, semaphores, and task notifications.

PROJECT DOWNLOAD

Info

You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.

Project FAQs

Subscribe
Notify of

13 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
KomKGT
2 years ago

Hello Master I’m new comer in FreeRTOS so I have one question.How to calculate the “stack size” in each Task?

zengkai
2 years ago

very useful!

Charoon
3 years ago

Very good knowledge tutorial STM32F4 with FreeRTOS

misso
3 years ago

your website is the best tutorial material I ever found.

negin shiran
4 years ago

thank you for the nice tutorial!

Farid
4 years ago

thank you for job!

Ulhas
4 years ago

Please make single pdf file for this excellent tutorial series on RTOS

noads
4 years ago

voting system lies.. counting and result not matching… good job!..

fraook
5 years ago

where is the code download? I installed chrome just to download your code.

Toan
5 years ago

Could you help me to use modul NFC modul v3 for stm32cubemx and Keilc v5 thanks