• Home
  • Archive
  • Tools
  • Contact Us

The Customize Windows

Technology Journal

  • Cloud Computing
  • Computer
  • Digital Photography
  • Windows 7
  • Archive
  • Cloud Computing
  • Virtualization
  • Computer and Internet
  • Digital Photography
  • Android
  • Sysadmin
  • Electronics
  • Big Data
  • Virtualization
  • Downloads
  • Web Development
  • Apple
  • Android
Advertisement
You are here:Home » An Introduction to FreeRTOS

By Abhishek Ghosh May 14, 2024 10:42 pm Updated on May 14, 2024

An Introduction to FreeRTOS

Advertisement

FreeRTOS is a real-time operating system (RTOS) for embedded systems. It is based on a microkernel architecture (explained below) and has been ported to various microcontrollers. FreeRTOS is an open-source RTOS designed for embedded systems and IoT devices. Richard Barry initiated its development in 2003, and since then, it has garnered significant traction in various industries due to its flexibility, portability, and robustness.

A microkernel, also known as a μ kernel or microkernel, is an operating system kernel that, unlike a monolithic kernel, performs only basic functions – usually memory and process management, as well as basic functions for synchronization and communication. All other functions are implemented as separate processes (servers) that communicate with the requesting programs (client), or as a program library that is integrated by the requesting programs in user mode.

The original FreeRTOS (can be referred to as Vanilla FreeRTOS) is supported on numerous single-core MCUs and SoCs. To support dual-core ESP targets, such as ESP32, ESP32-S3, and ESP32-P4, Espressif developed an implementation of FreeRTOS with dual-core symmetric multiprocessing (SMP) capabilities (can be referred to as IDF FreeRTOS). We program via ESP-IDF for IDF FreeRTOS, not the Vanilla FreeRTOS.

Advertisement

---

In this article, we are talking about the theories related to original FreeRTOS (Vanilla FreeRTOS). Implementation, use cases and examples are of various modified versions. IDF FreeRTOS is one of such modified versions. This is the official website of FreeRTOS. This is the official GitHub repository:

Vim
1
https://github.com/FreeRTOS/FreeRTOS

The thing to keep in mind is that microprocessors have become more powerful. As the power is increasing, the number of applications that require hardcoded real-time scheduling is shrinking.

 

Key Features of FreeRTOS

 

To ensure good maintainability, FreeRTOS is developed largely in C, only a few functions are implemented in assembler. The scheduler is configurable, so that pre-emptive and cooperative operation is possible. The operating system supports two different task classes from version 4 onwards. “Real” processes and coroutines that have little memory available. “Event Flags” are offered under the name “Binary Semaphore”. Mutexes are present in newer versions.

The package for download includes ready-made configurations for various architectures and various compiler environments. Furthermore, various demos (e.g. an IP stack) are included. On FreeRTOS.org there is extensive documentation on FreeRTOS, tutorials as well as documentation on the structure of an RTOS and a comparison of the implementations on different microcontrollers.

The provided examples will work with the 8051/8052 microcontroller. 8051/8052 is the original thing to start learning to program microcontrollers, that is still commonly used, followed by STM32 (STM32F1 is not costly), and ARM Cortex M. There are boards such as STM32 Nucleo-64 for the serious learners.

If you are using ESP line microcontrollers, then should read their documentation as well:

Vim
1
https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/freertos_idf.html

Task Management

FreeRTOS allows developers to create multiple tasks, each running independently and executing its specific function. Tasks can have different priorities, enabling the system to prioritize critical tasks over less important ones.

From Espressif’s documentation, task deletion in Vanilla FreeRTOS is called via vTaskDelete(). IDF FreeRTOS provides the same vTaskDelete() function. However, due to the dual-core, there are some behavioral differences when calling vTaskDelete() in IDF FreeRTOS. Please read documentation to avoid unpredictable behavior.

Scheduling

FreeRTOS employs a preemptive scheduling algorithm, enabling tasks with higher priority to preempt lower-priority tasks. This ensures that time-critical operations are executed without delay, making it suitable for real-time applications.

Example code:

Vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include "FreeRTOS.h"
#include "task.h"
#include "stdio.h"
 
// Task function prototypes
void vTask1(void *pvParameters);
void vTask2(void *pvParameters);
 
int main(void) {
    // Create Task 1
    xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
 
    // Create Task 2
    xTaskCreate(vTask2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
 
    // Start the FreeRTOS scheduler
    vTaskStartScheduler();
 
    // Should not reach here
    for(;;);
}
 
// Task 1 function
void vTask1(void *pvParameters) {
    (void) pvParameters; // Unused parameter
 
    for (;;) {
        printf("Task 1 is running...\n");
        vTaskDelay(pdMS_TO_TICKS(1000)); // Delay for 1 second
    }
}
 
// Task 2 function
void vTask2(void *pvParameters) {
    (void) pvParameters; // Unused parameter
 
    for (;;) {
        printf("Task 2 is running...\n");
        vTaskDelay(pdMS_TO_TICKS(2000)); // Delay for 2 seconds
    }
}

In the main() function, we create two tasks (vTask1 and vTask2) using xTaskCreate(). We assign different priorities to each task (1 for Task 1 and 2 for Task 2). The stack size is set to configMINIMAL_STACK_SIZE, which is a FreeRTOS configuration constant defining the minimum stack size for tasks.

We start the FreeRTOS scheduler with vTaskStartScheduler(). Once the scheduler starts, it will take over the execution of tasks, and the main() function will not return.

Each task function (vTask1 and vTask2) contains an infinite loop where it prints a message every second and every two seconds, respectively, using printf().

The vTaskDelay() function is used to introduce delays between successive iterations of the loop. It takes the delay time in ticks, which is converted from milliseconds using pdMS_TO_TICKS() macro.

Memory Management

FreeRTOS provides memory allocation and deallocation mechanisms tailored for embedded systems. It offers dynamic memory allocation schemes like heap_1, heap_2, and heap_4, allowing developers to choose the most suitable option based on their memory requirements and constraints. Example:

Vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "FreeRTOS.h"
#include "task.h"
#include "stdio.h"
 
// Task function prototypes
void vTask1(void *pvParameters);
 
int main(void) {
    // Create Task 1
    xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
 
    // Start the FreeRTOS scheduler
    vTaskStartScheduler();
 
    // Should not reach here
    for(;;);
}
 
// Task 1 function
void vTask1(void *pvParameters) {
    (void) pvParameters; // Unused parameter
 
    // Allocate memory dynamically
    char *ptr = (char *)pvPortMalloc(10 * sizeof(char));
 
    if (ptr != NULL) {
        sprintf(ptr, "Hello");
        printf("Dynamic memory allocation: %s\n", ptr);
 
        // Free the allocated memory
        vPortFree(ptr);
        printf("Memory freed successfully.\n");
    } else {
        printf("Memory allocation failed!\n");
    }
 
    // Delete the task
    vTaskDelete(NULL);
}

In the vTask1() function:

We allocate memory dynamically using the FreeRTOS memory allocation function pvPortMalloc(). We allocate memory for storing 10 characters. If the memory allocation is successful, we write the string “Hello” to the allocated memory using sprintf() and print it using printf().

We free the allocated memory using the FreeRTOS memory deallocation function vPortFree(). We delete the task itself using vTaskDelete(NULL).

Interrupt Handling

Efficient interrupt handling is crucial for real-time systems. FreeRTOS provides mechanisms to handle interrupts gracefully, ensuring minimal latency and deterministic response times. Example:

Vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "FreeRTOS.h"
#include "task.h"
#include "stdio.h"
 
// Simulated interrupt handler
void vInterruptHandler(void);
 
// Task function prototypes
void vTask1(void *pvParameters);
 
int main(void) {
    // Initialize FreeRTOS kernel
 
    // Simulated interrupt initialization
    // For the sake of this example, assume an interrupt is generated every 1 second
    // In a real application, this would be a hardware-specific setup
    // For demonstration purposes, we'll call the interrupt handler directly in a loop
 
    // Create Task 1
    xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
 
    // Start the FreeRTOS scheduler
    vTaskStartScheduler();
 
    // Should not reach here
    for(;;);
}
 
// Task 1 function
void vTask1(void *pvParameters) {
    (void) pvParameters; // Unused parameter
 
    for (;;) {
        // Task 1 operation
        printf("Task 1 is running...\n");
 
        // Delay for 500ms
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}
 
// Simulated interrupt handler
void vInterruptHandler(void) {
    // Handle the interrupt
    printf("Interrupt occurred!\n");
 
    // If needed, notify a task from the interrupt handler using a semaphore or other synchronization mechanism
}

The vInterruptHandler() function simulates an interrupt handler. In a real application, this function would handle the actual interrupt events from hardware peripherals. Inside the interrupt handler, you can perform time-critical operations or notify tasks using synchronization mechanisms like semaphores or event flags.

Timers

Timers in FreeRTOS allow developers to schedule tasks or execute callback functions periodically or after a specified delay. This feature is invaluable for implementing time-critical operations and managing tasks with precision. Example:

Vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "stdio.h"
 
// Timer callback function prototype
void vTimerCallback(TimerHandle_t xTimer);
 
// Task function prototypes
void vTask1(void *pvParameters);
 
// Timer handle
TimerHandle_t xTimer = NULL;
 
int main(void) {
    // Create Timer
    xTimer = xTimerCreate("Timer",             // Timer name
                           pdMS_TO_TICKS(1000),// Timer period in ticks (1000ms)
                           pdTRUE,             // Auto-reload
                           0,                  // Timer ID
                           vTimerCallback);    // Timer callback function
 
    // Check if timer creation was successful
    if (xTimer != NULL) {
        // Start the Timer
        xTimerStart(xTimer, 0);
    } else {
        printf("Failed to create timer!\n");
    }
 
    // Create Task 1
    xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
 
    // Start the FreeRTOS scheduler
    vTaskStartScheduler();
 
    // Should not reach here
    for(;;);
}
 
// Task 1 function
void vTask1(void *pvParameters) {
    (void) pvParameters; // Unused parameter
 
    for (;;) {
        // Task 1 operation
        printf("Task 1 is running...\n");
 
        // Delay for 500ms
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}
 
// Timer callback function
void vTimerCallback(TimerHandle_t xTimer) {
    // Timer callback operation
    printf("Timer callback: Timer expired!\n");
}

The vTimerCallback() function serves as the callback for the software timer. In this function, we perform the desired operation when the timer expires, such as printing a message indicating that the timer has expired.

Inter-Task Communication

FreeRTOS facilitates communication between tasks through various mechanisms such as queues, semaphores, mutexes, and event groups. These synchronization primitives enable seamless data exchange and coordination among tasks. Example:

Vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "stdio.h"
 
// Queue handle
QueueHandle_t xQueue = NULL;
 
// Task function prototypes
void vTask1(void *pvParameters);
void vTask2(void *pvParameters);
 
int main(void) {
    // Create Queue
    xQueue = xQueueCreate(5, sizeof(int)); // Queue size: 5, item size: sizeof(int)
 
    // Check if queue creation was successful
    if (xQueue != NULL) {
        // Create Task 1
        xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
 
        // Create Task 2
        xTaskCreate(vTask2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
 
        // Start the FreeRTOS scheduler
        vTaskStartScheduler();
    } else {
        printf("Failed to create queue!\n");
    }
 
    // Should not reach here
    for(;;);
}
 
// Task 1 function
void vTask1(void *pvParameters) {
    (void) pvParameters; // Unused parameter
 
    int txData = 0;
 
    for (;;) {
        // Send data to the queue
        if (xQueueSend(xQueue, &txData, portMAX_DELAY) == pdPASS) {
            printf("Task 1: Sent data to the queue: %d\n", txData);
            txData++; // Increment data for next transmission
        } else {
            printf("Task 1: Failed to send data to the queue!\n");
        }
 
        // Delay for 1 second
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}
 
// Task 2 function
void vTask2(void *pvParameters) {
    (void) pvParameters; // Unused parameter
 
    int rxData;
 
    for (;;) {
        // Receive data from the queue
        if (xQueueReceive(xQueue, &rxData, portMAX_DELAY) == pdPASS) {
            printf("Task 2: Received data from the queue: %d\n", rxData);
        } else {
            printf("Task 2: Failed to receive data from the queue!\n");
        }
    }
}

 

Architecture of FreeRTOS

 

FreeRTOS follows a modular architecture, comprising several core components. The kernel forms the heart of FreeRTOS and provides essential RTOS services such as task management, scheduling, and synchronization.

It employs a priority-based preemptive scheduler that ensures tasks with higher priority execute before lower-priority tasks. It supports both co-operative and preemptive scheduling modes.

FreeRTOS includes memory management components responsible for dynamic memory allocation and deallocation, catering to the memory requirements of tasks and system components. FreeRTOS offers a rich set of inter-task communication mechanisms like queues, semaphores, mutexes, and event groups, facilitating data exchange and synchronization between tasks. The Hardware Abstraction Layer (HAL) layer abstracts hardware-specific functionalities, enabling FreeRTOS to run on various microcontrollers and architectures with minimal modifications.

An Introduction to FreeRTOS


Image credit: FreeRTOS.org

 

Application of FreeRTOS

 

FreeRTOS finds applications in a wide range of industries and domains. It is used in automotive systems for tasks such as engine control, infotainment systems, and vehicle-to-vehicle communication. In industrial automation, FreeRTOS is employed in programmable logic controllers (PLCs), distributed control systems (DCS), and supervisory control and data acquisition (SCADA) systems for real-time control and monitoring.

FreeRTOS powers numerous consumer electronics devices such as smartwatches, digital cameras, home automation systems, and IoT devices, providing real-time responsiveness and efficient task management. FreeRTOS is also utilized in medical devices and healthcare systems for tasks like patient monitoring, diagnostic equipment control, and drug delivery systems, where real-time operation is critical.

 

Benefits of FreeRTOS

 

Being open-source, FreeRTOS offers full access to its source code, allowing developers to customize and tailor the operating system to meet their specific requirements.

It is highly portable and can run on various microcontrollers and architectures, making it suitable for a wide range of embedded systems and IoT devices.

It has a small memory footprint, making it suitable for resource-constrained embedded systems where memory and processing power are limited. FreeRTOS is scalable, allowing developers to configure the kernel based on the requirements of their application, thereby optimizing resource utilization and performance. Also, it is easy to add power management.

RTOSs make it easy to add middleware components such as TCP/IP stack, USB stacks, File System, Graphical User Interface etc.

 

Drawbacks of FreeRTOS

 

While FreeRTOS offers a plethora of advantages and is widely used in embedded systems and IoT devices, it’s important to acknowledge that no software is without its drawbacks. While FreeRTOS has extensive documentation, including reference manuals, API guides, and demo applications, some users find it insufficient, especially for complex scenarios or advanced features. This lack of comprehensive documentation can pose challenges for developers, particularly those new to the system.

Real-time programming and operating systems concepts can be challenging to grasp for developers transitioning from traditional programming paradigms. FreeRTOS, with its emphasis on real-time responsiveness and concurrent task management, may have a steeper learning curve for inexperienced developers compared to simpler operating systems.

While FreeRTOS is known for its small footprint and efficiency, there is still some overhead associated with task management, scheduling, and inter-task communication. In resource-constrained embedded systems, this overhead can impact overall performance and resource utilization, requiring careful optimization and configuration.

Unlike some commercial RTOS offerings that come with integrated development environments (IDEs) and debugging tools, FreeRTOS primarily provides the kernel and basic services. Developers may need to rely on third-party tools or integrate FreeRTOS with their preferred development environment, which can add complexity to the development process. While FreeRTOS provides various synchronization primitives such as queues, semaphores, mutexes, and event groups, handling complex synchronization scenarios involving multiple tasks and shared resources can be challenging. Developers may need to implement custom synchronization mechanisms or carefully design their application logic to avoid deadlocks and race conditions.

Real-time systems, including those built with FreeRTOS, often pose challenges for debugging and testing due to their concurrent and time-critical nature. Identifying and diagnosing issues related to task scheduling, timing constraints, and resource contention can be complex and time-consuming, requiring specialized debugging techniques and tools. While FreeRTOS has a large user base and active community forums, the level of support and availability of resources may vary depending on the specific platform or architecture. Developers working on less common or niche hardware may find it challenging to access relevant community support and resources.

Despite these drawbacks, FreeRTOS remains a popular choice for embedded system developers due to its flexibility, portability, and real-time capabilities.

Facebook Twitter Pinterest

Abhishek Ghosh

About Abhishek Ghosh

Abhishek Ghosh is a Businessman, Surgeon, Author and Blogger. You can keep touch with him on Twitter - @AbhishekCTRL.

Here’s what we’ve got for you which might like :

Articles Related to An Introduction to FreeRTOS

  • Basics of Watchdog Timer

    In this comprehensive guide, we explore the watchdog timer in detail, uncovering its features, functionalities, and applications in embedded systems.

  • How Interrupt Works

    In previous article, we have discussed the basics of interrupt. In order to be able to trigger an interrupt, the hardware connected to the main processor (CPU) must be interrupt-capable, i.e. generate an output signal (electrical voltage at an output pin) via the so-called interrupt line when a certain event occurs. The CPU generally has […]

  • Understanding Arduino Interrupts

    In the world of embedded systems and microcontroller programming, achieving real-time responsiveness is often a critical requirement. Whether it’s reading sensor data, detecting external events, or controlling actuators, the ability to respond swiftly and accurately can make all the difference. This is where Arduino interrupts come into play, offering a powerful mechanism to enhance control […]

  • What is Semaphor? Explained With Example

    A semaphore is a data structure consisting of an integer and the atomic usage operations “reserve/try” and “release”. It is suitable for managing limited resources.

performing a search on this website can help you. Also, we have YouTube Videos.

Take The Conversation Further ...

We'd love to know your thoughts on this article.
Meet the Author over on Twitter to join the conversation right now!

If you want to Advertise on our Article or want a Sponsored Article, you are invited to Contact us.

Contact Us

Subscribe To Our Free Newsletter

Get new posts by email:

Please Confirm the Subscription When Approval Email Will Arrive in Your Email Inbox as Second Step.

Search this website…

 

vpsdime

Popular Articles

Our Homepage is best place to find popular articles!

Here Are Some Good to Read Articles :

  • Cloud Computing Service Models
  • What is Cloud Computing?
  • Cloud Computing and Social Networks in Mobile Space
  • ARM Processor Architecture
  • What Camera Mode to Choose
  • Indispensable MySQL queries for custom fields in WordPress
  • Windows 7 Speech Recognition Scripting Related Tutorials

Social Networks

  • Pinterest (24.3K Followers)
  • Twitter (5.8k Followers)
  • Facebook (5.7k Followers)
  • LinkedIn (3.7k Followers)
  • YouTube (1.3k Followers)
  • GitHub (Repository)
  • GitHub (Gists)
Looking to publish sponsored article on our website?

Contact us

Recent Posts

  • Cloud-Powered Play: How Streaming Tech is Reshaping Online GamesSeptember 3, 2025
  • How to Use Transcribed Texts for MarketingAugust 14, 2025
  • nRF7002 DK vs ESP32 – A Technical Comparison for Wireless IoT DesignJune 18, 2025
  • Principles of Non-Invasive Blood Glucose Measurement By Near Infrared (NIR)June 11, 2025
  • Continuous Non-Invasive Blood Glucose Measurements: Present Situation (May 2025)May 23, 2025
PC users can consult Corrine Chorney for Security.

Want to know more about us?

Read Notability and Mentions & Our Setup.

Copyright © 2026 - The Customize Windows | dESIGNed by The Customize Windows

Copyright  · Privacy Policy  · Advertising Policy  · Terms of Service  · Refund Policy