#007 — Hello FreeRTOS — Part 1

Kewal Shah
IoT Tidbits
Published in
11 min readMay 30, 2018

In this 3 part series, we are going to be talking about arguably the most popular real time operating system for resource constrained devices like micro-controllers. In this first post, we are going to talk about the fundamental of FreeRTOS.

Getting Started with RTOS

Over the years we have seen a tremendous shift in micro-controllers. Orthodoxly used for a specific tasks, with the growth in silicon industry these micro-controllers are becoming more and more sophisticated and capable of handling multiple applications simultaneously . A boost to IoT industry and a backbone for making connected world, is because of these micro-controllers integrated with WiFi/BLE/LTE, making remote access possible. Micro-controllers even today are a small and 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 random access memory (RAM) needed by the programs it executes. Now along with this shift in hardware there has been a shift in coding style and structure as well. One of such open sourced RTOS kernel is FreeRTOS.

What is FreeRTOS and Why

FreeRTOS is a class of RTOS that is designed and capable to be small enough to run on a micro-controller although its use is not limited to micro-controller applications. The FreeRTOS kernel was originally developed by Richard Barry around 2002 and has now been acquired by Amazon. Micro-controllers are used in deeply embedded applications (those applications where you never actually see the processors themselves, or the software they are running) that normally have a very specific and dedicated job to do. The size constraints, and dedicated end application nature, rarely warrant the use of a full RTOS implementation or indeed make the use of a full RTOS stack implementation possible. FreeRTOS therefore provides the real time scheduling functionality, inter-task communication, timing and synchronization primitives. This means it is more accurately described as a real time kernel, or real time executive. Additional functionality, such as a command console interface, or networking stacks, can then be included with add-on components.

Lets get started

The easiest scheduler to implement in software is the Round Robin coding technique. Developers simply add new code to the super loop and a task is now added. There is no need to create dynamic and memory expensive objects. Just keep adding code!
One of the biggest problems with a Round Robin approach is that the real-time performance of the system is affected every time new code is added. Round Robin with interrupts move to ISR and then return back to the super-loop. This is where RTOS comes into picture.

As we go in deep in this article we will explore each module of FreeRTOS and its functionality w.r.t. small memory constrained on embedded devices. To get started lets know about some of the RTOS fundamentals. The first basis fundamental is Task.

Task

Each task is a small program in its own right. It has an entry point and will normally run forever within an infinite loop without exit. A single function definition can be used to create any number of task. An application can consist of n number of tasks. If the processor running the application contains a single core, then only one task can be executing at any given time. Each created task has its own stack and its own copy of any variables defined within the task itself.

Task Priorities

  • Each task is assigned a priority from 0 to maximum configured priority. The FreeRTOS scheduler ensures that tasks in the Ready or Running state will always be given CPU time in preference to priority assigned to each task created.
  • Any number of tasks can share the same priority or different priority.
  • If time slicing is used, then Ready state tasks of equal priority will share the available processing time using a time sliced round robin scheduling scheme.
  • The idle task has priority zero. Wait what is IDLE task ? Look next.

Idle Task

The idle task is created automatically when the RTOS scheduler is started.
It ensures there is always at least one task that is able to run and is always in ready state. It is created at the lowest possible priority to ensure it does not use any CPU time if there are higher priority application tasks in the ready state. An idle task hook is a function that is called during each cycle of the idle task
There must always be at least one task that is ready to run. It is therefore necessary that the hook function does not call any API functions that might cause the idle task to block or suspend.

source: FreeRTOS
  • Consider a case wherein two tasks are running. Both the task print some string value after certain amount of delay(this forces the task to go in block state).
  • In the Figure, each time the tasks leave the Blocked state they execute for a
    fraction of a tick period before re-entering the Blocked state.
  • Most of the time there are no application tasks that are able to run (no application tasks in the Ready state) and, therefore, no application tasks that can be selected to enter the Running state.
  • While this is the case, the idle task will run. The amount of processing time allocated to the idle is the time until any any task is in ready state.

Task State

source: FreeRTOS
  • When a task is in the Running state the processor is executing the task’s code. All the other tasks are in Not Running states
  • When a task is in the Not Running state, its status having been saved ready for it to resume execution the next time the scheduler decides it should enter the Running state.
  • When a task resumes execution, it does so from the instruction it was about to execute before it last left the Running state.

These states can be further expanded through Task state machine diagram.

source: FreeRTOS
  • Running: When a task is actually executing it is said to be in the Running state
  • Ready: Ready tasks are those that are able to Execute, but are not since another task has been in the running state
  • Blocking: A task is said to be in the Blocked state if it is currently waiting for either a temporal or external Event i.e. Time Delay or Synchronization Events
    Temporal (time-related) event being either a delay period expiring, or an
    absolute time being reached. For example, a task may enter the Blocked state to wait for 10 milliseconds to pass.
    Synchronization events where the events originate from another task or interrupt. For example, a task may enter the blocked state to wait for data to arrive on a queue. Synchronization events cover a broad range of event types.
  • Suspended: Suspended is also a sub-state of Not Running. Tasks in the Suspended state are not available to the scheduler. The only way into the Suspended state is through a call to the vTaskSuspend() API function. Most applications do not use the Suspended state.

MultiTasking

Each executing program is a task (or thread) under control of the operating system. If an operating system can execute multiple tasks in this manner it is said to be multitasking.The use of a multitasking operating system can simplify the design. The multitasking and inter-task communications features of the operating system allow the complex application to be partitioned into a set of smaller and more manageable tasks.A conventional processor can only execute a single task at a time. Rapidly switching between different tasks, a multitasking operating system can make it appear as if each task is executing concurrently.

source: FreeRTOS

As we can see in the image above the execution pattern of three tasks with respect to time. The upper diagram demonstrates the concurrent execution pattern wherein each task appears to be executing simultaneously. But in actual for the single core processor, only one task is running at given instantaneous time.

Context Switching

As a task executes it utilizes the processor / micro-controller registers and accesses RAM and ROM just as any other program. These resources together (the processor registers, stack, etc.) comprise the task execution context.

  • As a task executes it utilizes the processor registers and accesses RAM and ROM just as any other program. These resources together (the processor registers, stack, etc.) comprise the task execution context.
  • While the task is suspended other tasks will execute and may modify the processor register values. Upon resumption of the previous executing task, it will not know that the processor registers have been altered and we might expect abnormal results.
  • To prevent this type of error it is essential that upon resumption a task has a context identical to that immediately prior to its suspension.
  • The operating system kernel is responsible for saving the context of a task. When the task is resumed its saved context is restored by the operating system kernel prior to its execution.
source: FreeRTOS

Let us say we had a task which was performing a simple addition of two numbers. When the task started it loaded the two values and as you can see, the task got swapped out from the CPU by the scheduler just before it was going to execute ADD instruction. Now on resumption the first instruction to be performed is going to be addition of the two loaded values in Reg1 and Reg2. The task will not know that the registers values have been altered by the different task and can result in wrong calculation. Hence before the task is swapped out from the CPU all the register values(context of the task) are saved and are restored whenever the task resume avoiding any abnormal output.

Scheduling

The scheduler is the part of the kernel responsible for deciding which task should be executing at any particular time. The kernel can block and later resume a task many times during the task lifetime.
The scheduler is invoked on every tick interrupt. As soon as the scheduler starts, it first saves the current task context on the stack and then increments the tick counter. Now it looks for other task that has unblocked after waiting for n ticks. A list is arranged in order of priority comparing all the task in ready state and running state. If a higher-priority task needs to enter the running state, then context switch takes place and the current running task is swapped out, giving CPU to the higher priority task.

Let us say we have two tasks that run on occurrence of an event. As a key is pressed, Key Press Event occurs and triggers the task vKeyHandlerTask. The vControlTask is triggered when the timer event occurs(This is not the tick timer event) and has priority higher then key handler task.

source: FreeRTOS
  • At start, no task is running since both are waiting for the respective event to occur. Processor time is given to the idle task.
  • At t1, a key press occurs, vKeyHandlerTask is now able to execute. It has a higher priority than the idle task so it is given processor time.
  • At t2, vKeyHandlerTask has completed processing the key and cannot continue until another key has been pressed so suspends itself and the idle task is again resumed.
  • At t3, a timer event indicates that it is time to perform vControlTask. It will now execute and has the highest priority. It will be scheduled to get processor time immediately.
  • Between t3 and t4, while vControlTask is still executing, a key press occurs. vKeyHandlerTask is now able to execute, but as it has a lower priority than vControlTask, it is not scheduled to get any processor time, hence it remains in ready state.
  • At t4, vControlTask completes processing and cannot restart until the next timer event. vKeyHandlerTask is now the task with the highest priority that is able to run so is scheduled processor time in order to process the previous key press.
  • At t5, the key press has been processed, and vKeyHandlerTask blocks itself to wait for the next key event. Now neither of our tasks are able to execute and the idle task is scheduled to get processor time.
  • Between t5 and t6 a timer event is processed, and vControlTask starts running
  • The next key press occurs at t6, but even before vKeyHandlerTask has completed processing the timer event occurs. Now both tasks are able to execute and need processor time. As vControlTask has the higher priority then vKeyHandlerTask, it is swapped out from the CPU before it has completed processing the key, and vControlTask is scheduled to get processor time.
  • At t8, vControlTask completes and blocks itself to wait for the next timer event. vKeyHandlerTask is again the highest priority task that is able to run so is it scheduled to get processor time so the key press processing can be resumed from where it was halted.

Tick

Tick is a magical trigger that FreeRTOS uses to know when to switch, which task is running or give up waiting for a event. The tick is just a timer that has a period set to match the desired tick rate. The timer interrupt is triggered every time the period is hit and invokes the scheduler. The kernel looks at which tasks are in the Ready state and if there is any higher priority tasks than the current one, it switches context to allow the higher task to run. Each tick interrupt checks if any task is blocked due to the delay function and updates its state if it has elapsed the desired time. To be able to select the next task to run, the scheduler itself must execute at the end of each periodic interrupt, called the tick interrupt. The length of the time is effectively set by the tick interrupt frequency, which is configured by the application. The time between two tick interrupts is called the tick period.

source: FreeRTOS
  • Lets us say two tasks are running and tick interrupt occurs at t1, t2, t3 and so on. Just as out application start running at t1, Task 1 starting executing and tick timer starts its function.
  • At t2, tick interrupt occurs which invokes the scheduler inside the kernel, to select the task to switch. The newly selected Task 2 now occupies the CPU time.
  • Next tick interrupt occurs at t3 and the invoked scheduler now decides which task will get the CPU time for next tick period. The process further continues for next n ticks.

To be continued in FreeRTOS part 2

--

--

Kewal Shah
IoT Tidbits

Embedded Freak, Robotics, IoT, Embedded Software, Connected Products