FreeRTOS is a cross-platform, real-time operating system that has been ported to several architectures. It has a simple but powerful API to deal with tasks, scheduler, queues, semaphores and timers. Learning it is an enriching experience and a knowledge that can be reused widely due to its portability. If you are not convinced yet, it is available under a modified GPL license that allows commerical use without having to pay royalties.
The code snippet below demonstrates how a task can be created and deleted. Task creation may fail if there is not enough heap space available to allocate task structures and stack. FreeRTOS has three different memory allocation implementations, available in separate code files called heap_1.c, heap_2.c and heap_3.c. You have to choose one of the three. If you choose heap_3.c, the C compiler’s implementation of malloc and free are used, the heap space is determined based on the linker configuration. If interested in AVR32, see Using the GNU Linker Scripts on AVR UC3 Devices.
/* a task */
static void run(void *pvParameters)
/* create task */
p = xTaskCreate(run,
(const signed portCHAR *)"task",
if ( p != pdPASS )
/* delete task */
Task scheduling is a topic unto itself. FreeRTOS divides processor time equally among tasks with the same priority. Tasks with higher priority always preempt lower priority tasks, no other lower priority task will run until the higher priority task blocks. Tasks can block on calls such as vTaskDelay, vTaskDelayUntil, xQueueSend, xQueuePeek, xQueueReceive, xSemaphoreTake and a few others.
A task needs to perform activities. Most tasks are implemented as endless loops that wake up on some event, perform some activity and go back to waiting. An advantage of using queues is that they are multitask safe and thus an effective synchronization mechanism between tasks. You can use them to queue activities that a task must perform, serializing their execution. This is useful if multiple tasks must have access to a shared resource controlled by a single task.
The code snippet below demonstrates how to create queues, and add and retrieve items.
xQueueHandle queue = 0;
queue = xQueueCreate(10, sizeof(unsigned int));
unsigned int id = 0;
xQueueSend(xQueueIO, (void *)&id, (portTickType)0);
p = xQueueReceive(queue, &id, (portTickType)0);
if (p == pdPASS)
Timers are a useful mechanism to stop long running activities and to start activities at periodic intervals. The code snippet below demonstrates how to use the tick counter maintained by FreeRTOS to implement timers. The portTICK_RATE_MS macro is used to convert milliseconds to ticks. If the port of FreeRTOS for your board is not configured properly the value of portTICK_RATE_MS may not be correct.
static portTickType tickUntil;
static portTickType startTick;
/* assign tick count when timer elapses i.e. after 1000 ms */
startTick = xTaskGetTickCount();
tickUntil = startTick + (portTickType)(1000 / portTICK_RATE_MS);
/* this code happens in a task function */
currentTick = xTaskGetTickCount();
if (tickUntil > startTick
&& (currentTick > tickUntil
|| (currentTick < startTick
&& currentTick < tickUntil))) /* no overflow of tickUntil */
/* timer elapsed */
else if (currentTick < startTick
&& currentTick > tickUntil) /* overflow of tickUntil */
/* timer elapsed */
See the ticklines below for reference, as soon as the tick count enters the red region we consider the timer to have elapsed. The first tickline is for the normal condition and the second is for the case when tickUntil overflows.