FreeRTOS Tutorial: Introduction & Essentials
FreeRTOS Tutorial: Updated August 18, 2021
While building our latest IoT product, our development team found that documentation for FreeRTOS was dated and often flat-out wrong. To help others as they make their way through this process, we decided to document and release our findings as a FreeRTOS tutorial for developers. Here are the essentials for FreeRTOS.
What is FreeRTOS (Simple)?
FreeRTOS is an operating system (OS) for low energy and resource microcontrollers. Until this day it is being developed and includes a “growing set” of IoT libraries.
It's the industry standard and used by many large companies.
Why use FreeRTOS?
- Kernel is also low energy
- Supports a wide range of different architectures
- A growing library of tools
- Frequent updates
- Includes MQTT
- And more!
What is RTOS and FreeRTOS?
RTOS is a simple operating system with a scheduler that is designed to have a predictable execution pattern. This is useful for embedded systems since they have real-time constraints. Real-time constraints/requirements are events that must occur and conclude within a strictly defined time.
The Scheduler in FreeRTOS and RTOS can achieve real-time guarantees by having predictable execution of tasks.
- User must assign a priority to each task (thread of execution).
- Scheduler will use these assignments to figure out which task to run next and in which order to run the other tasks.
FreeRTOS is a class of RTOS that is further simplified to run on microcontrollers.
Microcontroller here is defined as a small resource-constrained processor that incorporates, on a single chip, the processor itself, read-only memory (ROM or Flash) to hold the program to be executed, and the RAM needed by the programs it executes.
- Program is executed directly from read-only memory.
FreeRTOS provides real-time scheduling for the single core, inter-task communication, timing, and synchronization primitives.
- Closer to being a true real-time kernel
- Can add additional functionality as needed
- Command console interface
- Networking stacks
- More ...
How Tasks Work
RTOS needs at least one core to run (hypothetically this means multiple core systems are ideal ESP32 for example has 2 cores).
Real-time tasks can be structured into independent tasks thanks to the RTOS. Each task is executed independently of another task.
- This means no 2 tasks depend on other tasks or the scheduler to do their job
- Only one task in an application is run at a time. The RTOS scheduler is responsible for figuring that out.
- Tasks may be stopped and started as the Scheduler deems necessary.
- Since A task has no knowledge of the scheduler, the Scheduler needs to handle the overhead of saving the memory state of the current task before switching to another task.
- This is achieved by giving each task its own Stack.
- Simple implementation
- Little to no restrictions on what Tasks can do
- Fully prioritized
- Higher ram usage since each Task has its own stack.
- Swapping between tasks has a time penalty.
- When a user or users can execute multiple tasks simultaneously.
- Can simplify the design of complex software.
- Allows complex applications to be broken down into smaller tasks
- Can make software testing simpler
- User doesn’t need to worry about managing timing and sequencing
Multitasking vs Concurrency
In a simpler one-chip system, an OS can give the illusion that it is running applications concurrently by quickly switching between applications.
In a true concurrent system, each task is being run at the same time. In a multitasking system, we are quickly switching between tasks and giving the illusion of concurrency
- Part of the kernel that decides which task to run and at what time, and for how long.
- Can and most likely will suspend tasks and then later resume them at a different time.
The algorithm(s) used by the scheduler to decide which tasks to run.
Tasks can be involuntary suspended or suspend themselves
- I.E a task may be forced to stop by the scheduler or choose to stop itself.
- A task can choose to suspend itself if it is waiting for resources to become available or for an event to occur.
- Sleeping tasks don’t take any processing time.
The resources that a Task uses (RAM, Processor, Registers, etc) while it is being executed is known as a context.
Remember, Tasks almost never know when they are going to be switched out or switched in. Tasks don’t even know when it has happened to them.
- Example. Let’s say we have a line of code that goes into memory and adds 2 numbers stored in memory. As it is trying to add a switch occurs, the Kernel decides to execute a different task. When the Kernel executes task 2 it changes the memory that stores the 2 numbers we tried to add in task 1. When we resume task 1 if the kernel didn’t handle context switching we would end up with the wrong sum.
Context Switching is the act of saving the context of a task (Memory, Registers, place of execution, etc) when switching out and restoring the context back to the way it was before the switch happened.
Kernel is responsible for this.
Real Time Application
Are events that should occur under a constrained time period.
- Events that occur in the real world have deadlines, and the embedded system should be fast enough to respond to these deadlines in real-time
Software Engineers are encouraged to assign a priority for each task to ensure that important tasks are executed first, or to ensure equal allocation of resources if all tasks are equal.
- Tasks that have strict deadlines should be prioritized.
- Identify which task would have a higher severity when it comes to missing deadlines.
In-Depth Developer Guides
- Devetry Github here
- Official Docs here
- OS Building Blocks RTOS Implementation
- Understanding Kernel and Reference Manual here
- Docs for Kernel Development here
- * Secondary Docs here
- API Reference for Kernel here
- FreeRTOS Libraries here