Free RTOS
Free RTOS
Free RTOS
Nicolas Melot
Introduction
FreeRTOS is an free and opensource RealTime Operating system developed by Real Time Engineers Ltd. Its
design has been developed to fit on very small embedded systems and implements only a very minimalist set of
functions: very basic handle of tasks and memory management, just sufficient API concerning synchronization, and
absolutely nothing is provided for network communication, drivers for external hardware, or access to a filesystem.
However, among its features are the following characteristics: preemptive tasks, a support for 23 microcontroller
architectures1 by its developers, a small footprint2 (4.3Kbytes on an ARM7 after compilation 3), written in C and
compiled with various C compiler (some ports are compiled with gcc, others with openwatcom or borland c++). It also
allows an unlimited number of tasks to run at the same time and no limitation about their priorities as long as used
hardware can afford it. Finally, it implements queues, binary and counting semaphores and mutexes.
1 http://www.freertos.org/a00090.html
2 http://www.freertos.org/FAQMem.html#QSize
3 http://www.freertos.org/FreeRTOS_Features.html
4
Nicolas Melot Study of an operating system: FreeRTOS Tasks
1 Tasks
Several functions are available to manage tasks: task creation (vTaskCreate()), destruction (vTaskDelete()),
priority management (uxTaskPriorityGet(), vTaskPrioritySet()) or delay/resume ((vTaskDelay(), vTaskDelayUntil(),
vTaskSuspend(), vTaskResume(), vTaskResumeFromISR()). More options are available to user, for instance to create a
critical sequence or monitor the task for debugging purpose.
5
Nicolas Melot Study of an operating system: FreeRTOS Tasks
It is important to underline that a if a task can leave by itself the “Running” state (delay, suspend or wait for an
event), only the scheduler can “switch in” again this task. When a task wants to run again, its state turns to “Ready” an
only the scheduler can choose which “Ready” task is run at a given time.
Not running
Suspended
VtaskSuspend()
VtaskSuspend() called
called
VtaskResume()
called
Scheduler
Ready activity Running
VtaskSuspend() Event
called Blocking API
function called
Blocked
Any created task should never end before it is destroyed. It is common for task's code to be wrapped in an infinite
loop, or to invoke vTaskDestroy(NULL) before it reaches its final brace. As any code in infinite loop can fail and exit
this loop, it is safer even for a repetitive task, to invoke vTaskDelete() before its final brace. An example of a typical task
implementation is available on Text 3.
A task can be created using vTaskCreate() (Text 2). This function takes as argument the following list:
● pcName: given name to the task. This is useless to FreeRTOS but is intented to debugging purpose only.
● usStackDepth: length of the stack for this task in words. The actual size of the stack depends on the
micro controller. If stack with is 32 bits (4 bytes) and usStackDepth is 100, then 400 bytes (4 times 100) will be
allocated for the task.
● pvParameters: a pointer to arguments given to the task. A good practice consists in creating a dedicated
6
Nicolas Melot Study of an operating system: FreeRTOS Tasks
structure, instantiate and fill it then give its pointer to the task.
● uxPriority: priority given to the task, a number between 0 and MAX_PRIORITIES – 1. This is
discussed in section 2.
● pxCreatedTask: a pointer to an identifier that allows to handle the task. If the task does not have to be
handled in the future, this can be leaved NULL.
/* Should the task implementation ever break out of the above loop
then the task must be deleted before reaching the end of this function.
The NULL parameter passed to the vTaskDelete() function indicates that
the task to be deleted is the calling (this) task. */
vTaskDelete( NULL );
}
Text 3: A typical task (from “Using the FreeRTOS Real Time Kernel”).
A task is destroyed using xTaskDestroy() routine. It takes as argument pxCreatedTask which is given when the
task was created. Signature of this routine is given in Text 4 and an example can be found in Text 3.
When a task is deleted, it is responsibility of idle task to free all allocated memory to this task by kernel. Notice
that all memory dynamically allocated must be manually freed.
7
Nicolas Melot Study of an operating system: FreeRTOS Scheduling
2 Scheduling
Task scheduling aims to decide which task in “Ready” state has to be run at a given time. FreeRTOS achieves
this purpose with priorities given to tasks while they are created (see 1.2). Priority of a task is the only element the
scheduler takes into account to decide which task has to be switched in.
Every clock tick makes the scheduler to decide which task has to be waken up, as shown in Figure 3.
Kernel
Task 1
Task 2
Time
t1 t3
Figure 3: Every clock tick makes the
scheduler to run a "Ready" state task
and to switch out the running task.
2.1 Priorities
FreeRTOS implements tasks priorities to handle multi tasks scheduling. A priority is a number given to a task
while it is created or changed manually using vTaskPriorityGet() and vTaskPrioritySet() (See FreeRTOS manual). There
is no automatic management of priorities which mean a task always keeps the same priority unless the programmer
change it explicitly. A low value means a low priority: A priority of 0 is the minimal priority a task could have and this
level should be strictly reserved for the idle task. The last available priority in the application (the higher value) is the
highest priority available for task. FreeRTOS has no limitation concerning the number of priorities it handles.
Maximum number of priorities is defined in MAX_PRIORITIES constant in FreeRTOSConfig.h (see section 8.1), and
hardware limitation (width of the MAX_PRIORITIES type). If an higher value is given to a task, then FreeRTOS cuts it
to MAX_PRIORITIES – 1. Figure 4 gives an example of a application run in FreeRTOS. Task 1 and task 3 are event
based tasks (they start when a event occurs, run then wait for the event to occur again), Task 2 is periodic and idle task
makes sure there is always a task running.
This task management allows an implementation of Rate Monotonic for task scheduling: tasks with higher
frequencies are given an higher priority whereas low frequencies tasks deserve a low priority. Eventbased or continuous
tasks are preempted by periodic tasks.
8
Nicolas Melot Study of an operating system: FreeRTOS Scheduling
Idle task
Time
t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13
Task 3 preempts idle task Task 2 preempts idle task Event processing is
delayed until every higher
priority tasks are
suspended or blocked
Task 1
Task 2
Time
t1 t2 t3 t4 t5
Figure 5: Two tasks with a equivalent priority are
run after each other in turn.
2.3 Starvation
There is no mechanism implemented in FreeRTOS that prevents task starvation: the programmer has to make
sure there is no higher priority task taking all running time for itself. It is also a good idea to let the idle task to run,
since it can handle some important work such as free memory from deleted tasks, or switching the device into a
sleeping mode.
3 Queue management
Queues are an underlying mechanism beyond all tasks communication or synchronization in a FreeRTOS
environment. They are an important subject to understand as it is unavoidable to be able to build a complex application
with tasks cooperating with each other. They are a mean to store a and finite number (named “length”) of fixedsize
9
Nicolas Melot Study of an operating system: FreeRTOS Queue management
data. They are able to be read and written by several different tasks, and don't belong to any task in particular. A queue
is normally a FIFO which means elements are read in the order they have been written. This behavior depends on the
writing method: two writing functions can be used to write either at the beginning or at the end of this queue.
portBASE_TYPE xQueueReceive(
xQueueHandle xQueue,
const void * pvBuffer,
portTickType xTicksToWait
);
Text 5: normal method to read in a queue: it reads an element then removes it.
pvBuffer is a pointer to the buffer where the read value will be copied to. This memory must be allocated and
must be large enough to handle the element read from the queue.
xTicksToWait defines the maximum time to wait. 0 prevents the task from waiting even if a value is not
available, whereas if INCLUDE_vTaskSuspend is set and xTicksToWait equals MAX_DELAY, the task waits
indefinitely.
pdPASS is returned if a value was sucessfully read before xTicksToWait is reached. If not, errQUEUE_EMPTY
is returned from xQueueReceive().
After reading an element in a queue, this element is normally removed from it; however, an other read function
given in allows to read an element without having it to be deleted from the queue.
portBASE_TYPE xQueuePeek(
xQueueHandle xQueue,
const void * pvBuffer,
portTickType xTicksToWait
);
Text 6: It also possible to read in a queue without without removing the element from it.
10
Nicolas Melot Study of an operating system: FreeRTOS Queue management
attempt to write on the same queue, the higher priority task is chosen first. If several tasks with the same priority are
trying to write on a queue, then the first one to wait is chosen. Figure 6 gives a good illustration on how queues work.
A prototype is available on Text 7. It describes the normal method to write on a queue. Text 8 gives the
underlying function behind xQueueSend and the function to be used if the user wants the last written element to be read
first (Last In, First Out or LIFO).
xQueue is the queue to write on. This value is returned by the queue creation method.
pvItemToQueue is a pointer to an element which is wanted to be copied (by value) to the queue.
xticksToWait is the number of ticks to wait before the task gives up to write on this queue. If xTicksToWait is 0,
the task won't wait at all if the queue is full. If INCLUDE_vTaskSuspend if defined to 1 inf FreeRTOSConfig.h (section
8.1) and xTicksToWait equals MAX_DELAY, then the task has no time limit to wait.
XqueueSend returns pdPASS if the element was successfully written to the queue before the maximum waiting
time was reached, or errQUEUE_FULL if the maximum time was elapsed before the task could write on the queue.
uxQueueLenght gives the number of elements this queue will be able to handle at any given time. uxItemSize is
the size in byte of any element stored in the queue. xQueueCreate returns NULL if the queue was not created due to lack
11
Nicolas Melot Study of an operating system: FreeRTOS Queue management
of memory available; if not, the returned value should be kept to handle the newly created queue.
A queue is created to allow task 1 and task B to communicate. The queue can hold a maximum
of 5 values. When a queue is created, it doesn't contain any value so it's empty
Task 1 Task 2
Task 1 writes a value on the queue; the value is sent to the back. Since the queue was
previously empty, the value is now both the first and the last value in the queue.
Task 1 10 Task 2
Task 1 sends again an other value. The queue contains now the previously written value and
this newly added value. The previous value remains at the front of the queue while the new one
is now at its back. Three spaces are still available.
Task 1 20 10 Task 2
Task 2 reads a value in the queue. It will receive the value in the front of the queue, which is the
first task one inserted.
Task 1 20 10 Task 2
Task 2 has removed an item. The second item is moved to be the one in the front of the queue.
This is the value task 2 will read next time it tries to read a value. 4 spaces are now available.
Task 1 20 Task 2
12
Nicolas Melot Study of an operating system: FreeRTOS Resources management
xTicksToWait is the time, in clock ticks, for the task to wait before it gives up with taking the semaphore. If
xTicksToWait equals MAX_DELAY and INCLUDE_vTaskSuspend is 1, then the task won't stop waiting.
If the take operation succeed in time, the function returns pdPASS. If not, pdFALSE is returned.
The function returns pdPASS if the give operation was successful, or pdFAIL if the semaphore was already
available, or if the task did not hold it.
13
Nicolas Melot Study of an operating system: FreeRTOS Resources management
The semaphore is not available, so the task is blocked, wating for the semaphore.
xSemaphoreTake()
xGiveSemaphoreFromISR() xSemaphoreTake()
xGiveSemaphoreFromISR() xSemaphoreTake()
xSemaphoreTake()
Another interrupt occurs and gives another semaphore. In the meanwhile, the task is processing
the first interrupt.
xGiveSemaphoreFromISR() xSemaphoreTake()
When the task has finished to preccess its first work, it waits for another semaphore and gets it
directly, since an interrupt occurred. The task is now able to process the second interrupt.
xSemaphoreTake()
14
Nicolas Melot Study of an operating system: FreeRTOS Resources management
4.2 Mutexes
Mutexes are designed to prevent mutual exclusion or deadlocking. A mutex is used similarly to a binary
semaphore, except the task which take the semaphore must give it back. This can be though with a token associated with
the resource to access to. A task holds the token, works with the resource then gives back the token; in the meanwhile,
no other token can be given to the mutex. A good illustration is shown in Figure 8.
Two tasks want to access a resource. But only a task which holds the mutext is allowed to work Task 2 is blocked until Task 1 has finished to work with the resource, and has given back the
with it. mutex.
Task 1 Task 1
Ressource to Ressource to
protect protect
Mutext Mutext
Task 2 Task 2
Task 1 tries to take the mutex. Since it is available, it gets it and is allowed to work with the Task 1 has given back the mutex and task 2 can take it and is allowed to work with the resource.
resource.
Task 1 Task 1
Ressource to Ressource to
protect protect
Mutext Mutext
Task 2 Task 2
Task 2 tries to take the same mutex, but task 1 stil has it.Task 2 is not permitted to access the Task 2 gives back the mutex. It is now available to whichever task that need to work with the
resource. associated resource.
Task 1 Task 1
Ressource to Ressource to
protect protect
Mutext Mutext
Task 2 Task 2
4.3.1.1 Creation
As described above, a counting semaphore can be taken a limited maximum times and is initialized to be
available for an arbitrary number of take operations. These characteristics are given when the semaphore is created.
15
Nicolas Melot Study of an operating system: FreeRTOS Resources management
uxMaxCount is the capacity of the counting semaphore, its maximum ability to be taken.
Returned value is NULL if the semaphore was not created, because of a lack of memory, or a pointer to the new
semaphore and can be used to handle it.
5 Handling interrupts
An interrupt is a mechanism fully implemented and handled by hardware. Software and more particularly
FreeRTOS tasks or kernel can only give methods to handle a given interrupt, or it can raise some by calling an hardware
instruction. We will suppose we are using a micro controller that handles 7 different levels of interrupts. The more an
interrupt number is important, the more it will be priority over other interrupts. Depending on hardware, this is not
always the case. interrupts priorities are not, in any case, related to tasks priorities, and will always preempt them.
A function defined as an interrupt handler cannot use freely FreeRTOS API: access to queues or semaphores is
forbidden through the normal functions described in previous section, but FreeRTOS provides some specialized
functions to be used in that context: for instance, in an interrupt handler, a V() operation to a semaphore must be
realized using xSemaphoreGiveFromISR() instead of xSemaphoreGive(). The prototypes for these method can be
different as they can involve some particular problems (this is the case of xSemaphoreGiveFromISR() which
implements a mechanism to make the user to be aware that this give operation makes the interrupt to be preempted by a
higher priority interrupt unlocked by this give operation).
● configKERNEL_INTERRUPT_PRIORITY sets the interrupt priority level for the tick interrupt.
16
Nicolas Melot Study of an operating system: FreeRTOS Handling interrupts
never be preempted by the kernel, but are forbidden to use FreeRTOS API functions.
Priority 7
Priority 1
Figure 10 proposes a solution to reduce significantly the time an ISR can run. An ISR “gives” a semaphore and
unblock a 'Handler” task that is able to handler the ISR, making the ISR execution much shorter.
ISR
When handler task has
'Handler' task finished its job, it waits
again the semaphore the
next ISR will provide, and
Task 1 allow the lower priority
task to run again
17
Nicolas Melot Study of an operating system: FreeRTOS Handling interrupts
Handling this can be very important as many instructions, affectations for instance, may look atomic but require
several hardware instructions (load variable address to a registry, load a value to another registry and move the value to
the matching memory address using the two registries).
Text 14: A critical section protected against both scheduler “switch out” operations, and
hardware interrupts.
A task can start a critical section with taskENTER_CRITICAL() and stop it using taskEXIT_CRITICAL(). The
system allow a critical section to be started while an other one is already opened: this makes much easier to call external
functions that can need such a section whereas the calling function also need it. However, it is important to notice that in
order to end a critical section, taskEXIT_CRITICAL() must be called exactly as much as taskSTART_CRITICAL was.
Generaly speaking, these two functions must be called as close as possible in the code to make this section very short.
Such a critical section is not protected from interrupts which priority is greater than
configMAX_SYSCALL_INTERRUPT_PRIORITY (if defined in FreeRTOSConfig.h; if not, prefer to consider the
value configKERNEL_INTERRUPT_PRIORITY instead) to create a context change.
18
Nicolas Melot Study of an operating system: FreeRTOS Handling interrupts
Notice it is important that FreeRTOS API functions must not be called when the scheduler is stopped.
When Calling xTaskResumeAll() is called, it returns pdTRUE if no task requested a context change while
scheduler was suspended and returns pdFALSE if there was.
6 Memory management
In a small embedded system, using malloc() and free() to allocate memory for tasks, queues or semaphores can
cause various problems: preemption while allocating some memory, memory allocation and free can be an
nondeterministic operations, once compiled, they consume a lot of space or suffer from memory fragmentation.
Instead, FreeRTOS provides three different ways to allocate memory, each adapted to a different situation but all
try to provide a solution adapted to small embedded systems. Once the proper situation identified, the programmer can
choose the right memory management method once for all, for kernel activity included. It is possible to implement its
own method, or use one of the three FreeRTOS proposes and which can be found in heap_1.c, heap_2.c or heap_3.c (or
respecctively in sections 8.2, 8.3 and 8.4).
6.1 Prototypes
All implementations respect the same allocation/free memory function prototypes. These prototypes stands in
two functions.
xWanted size is the size, in byte, to be allocated, pv is a pointer to the memory to be freed. pvPortMalloc returns
a pointer to the memory allocated.
19
Nicolas Melot Study of an operating system: FreeRTOS Memory management
Since the use of this scheme suppose all memory is allocated before the application actually starts, and there will
have no need to reallocate or free memory, FreeRTOS simply adds a task TCB (Task Control Block, the structure
FreeRTOS uses to handle tasks) then all memory it needs, and repeat this job for all implemented tasks. Figure 11 gives
a illustration about how the memory is managed.
This memory management allocates a simple array sized after the constant configTOTAL_HEAP_SIZE in
FreeRTOSConfig.h, and divides it in smaller parts which are allocated for memory all tasks require. This makes the
application to appear to consume a lot of memory, even before any memory allocation.
A B C
Stack
ConfigTOTAL_HEAP_SIZE
Free space
TCB
Stack
TCB
Stack Stack
TCB TCB
As the previous strategy, FreeRTOS uses a large initial array, which size depends on configTOTAL_HEAP_SIZE
and makes the application to appears to consume huge RAM. A difference with the previous solution consists in an
implementation of vPortFree(). As memory can be freed, the memory allocation is also adapted. Let's consider the big
initial array to be allocated and freed in such a way that there are three consecutive free spaces available. First is 5 bytes,
second is 25 and the last one is 100 bytes large. A call to pvPortMalloc(20) requires 20 bytes to be free so has to reserve
20
Nicolas Melot Study of an operating system: FreeRTOS Memory management
it and return back its reference. This algorithm will return the second free space, 25 bytes large and will keep the
remaining 5 bytes for a later call to pvPortMalloc(). It will always choose the smallest free space where can fit the
requested size.
A B C
Free space
TCB TCB TCB
Stack
Stack
TCB TCB
Stack Stack Stack
Figure 12: The algorithm will always use the smallest free space
where the requested portion can fit.
Such an algorithm can generate a lot of fragmentation in memory if allocations are not regular, but it fits if
allocations remains constant in size and number.
21
Nicolas Melot Study of an operating system: FreeRTOS Memory management
Text 17: Thread safe wrappers for malloc() and free() are another solution to manage memory.
22
Nicolas Melot Study of an operating system: FreeRTOS Memory management
Conclusion
FreeRTOS is an operating system designed for small embedded system: but if its memory footprint can be very
small, its functionalities are also very limited: no support for thread, minimalist memory management, no driver is
available to handle resources on usual bus such as USB or PCI, no support for any communication protocols such as an
IP stack and nothing is available to handle any file system; even inputoutput primitives are not available. However basic
functions of an operating system are implemented; this is enough for the design of very small and rather complex
applications.
23
Nicolas Melot Study of an operating system: FreeRTOS Memory management
References
This works makes references to FreeRTOS documentation books “Using the FreeRTOS Real Time kernel”
available to download on http://www.freertos.org/a00104.html. Illustrations used in this report can be found in this book.
This report also makes reference to FreeRTOS API published on http://www.freertos.org/a00106.html and on the book
FreeRTOS Reference manual http://www.freertos.org/a00104.html.
24
Nicolas Melot Study of an operating system: FreeRTOS Illustrations
7 Illustrations
Figure 1: Simplified life cycle of a task : Only one task can be "running" at a given time, whereas the “not running state
can be expanded“..................................................................................................................................................................7
Figure 2: Life cycle of a task................................................................................................................................................9
Figure 3: Every clock tick makes the scheduler to run a "Ready" state task and to switch out the running task...............13
Figure 4: An hypothetic FreeRTOS application schedule..................................................................................................15
Figure 5: Two tasks with a equivalent priority are run after each other in turn..................................................................15
Figure 6: Possible scenario with a queue and two tasks.....................................................................................................21
Figure 7: A binary semaphore is equivalent to a queue which can contain one element...................................................25
Figure 8: Usual use case of a mutex...................................................................................................................................27
Figure 9: Interrupt organization in FreeRTOS....................................................................................................................31
Text 1: A typical task signature............................................................................................................................................6
Text 2: Task creation routine.................................................................................................................................................7
Text 3: A typical task (from “Using the FreeRTOS Real Time Kernel”).............................................................................7
Text 4: Deleting a task..........................................................................................................................................................7
Text 5: normal method to read in a queue: it reads an element then removes it.................................................................10
Text 6: It also possible to read in a queue without without removing the element from it.................................................10
Text 7: function to write on a queue in FIFO mode............................................................................................................11
Text 8: xQueueSendToBack: a synonym for xQueSend; xQueueSendToFront write on a queue in LIFO mode..............11
Text 9: Queue creation function..........................................................................................................................................11
Text 10: creating a semaphore.............................................................................................................................................13
Text 11: taking a semaphore................................................................................................................................................13
Text 12: giving a semaphore...............................................................................................................................................13
Text 13: Creation of a counting semaphore.........................................................................................................................16
Text 14: A critical section protected against both scheduler “switch out” operations, and hardware interrupts................18
Text 15: Creation of a counting semaphore........................................................................................................................19
Text 16: Prototypes for memory allocation/deallocation....................................................................................................19
Text 17: Thread safe wrappers for malloc() and free() are another solution to manage memory........................................22
25
Nicolas Melot Study of an operating system: FreeRTOS Appendix
8 Appendix
8 Appendix.........................................................................................................................................................................26
8.1 An example of FreeRTOSConfig.h.........................................................................................................................27
8.2 heap_1.c..................................................................................................................................................................29
8.3 heap_2.c...................................................................................................................................................................31
8.4 heap_3.c..................................................................................................................................................................37
26
Nicolas Melot Study of an operating system: FreeRTOS Appendix
***************************************************************************
* *
* If you are: *
* *
* + New to FreeRTOS, *
* + Wanting to learn FreeRTOS or multitasking in general quickly *
* + Looking for basic training, *
* + Wanting to improve your FreeRTOS skills and productivity *
* *
* then take a look at the FreeRTOS eBook *
* *
* "Using the FreeRTOS Real Time Kernel a Practical Guide" *
* http://www.FreeRTOS.org/Documentation *
* *
* A pdf reference manual is also available. Both are usually delivered *
* to your inbox within 20 minutes to two hours when purchased between 8am *
* and 8pm GMT (although please allow up to 24 hours in case of *
* exceptional circumstances). Thank you for your support! *
* *
***************************************************************************
1 tab == 4 spaces!
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
27
Nicolas Melot Study of an operating system: FreeRTOS Appendix
#include <i86.h>
#include <conio.h>
/*
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
**/
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 256 ) /* This can
be made smaller if required. */
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 32 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 1
#define configIDLE_SHOULD_YIELD 1
#define configUSE_CO_ROUTINES 1
#define configUSE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_ALTERNATIVE_API 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configCHECK_FOR_STACK_OVERFLOW 0 /* Do not use this option on the PC
port. */
#define configUSE_APPLICATION_TASK_TAG 1
#define configQUEUE_REGISTRY_SIZE 0
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0 /* Do not use this option on the
PC port. */
28
Nicolas Melot Study of an operating system: FreeRTOS Appendix
#endif /* FREERTOS_CONFIG_H */
8.2 heap_1.c
/*
FreeRTOS V6.0.0 Copyright (C) 2009 Real Time Engineers Ltd.
***************************************************************************
* *
* If you are: *
* *
* + New to FreeRTOS, *
* + Wanting to learn FreeRTOS or multitasking in general quickly *
* + Looking for basic training, *
* + Wanting to improve your FreeRTOS skills and productivity *
* *
* then take a look at the FreeRTOS eBook *
* *
* "Using the FreeRTOS Real Time Kernel a Practical Guide" *
* http://www.FreeRTOS.org/Documentation *
* *
* A pdf reference manual is also available. Both are usually delivered *
* to your inbox within 20 minutes to two hours when purchased between 8am *
* and 8pm GMT (although please allow up to 24 hours in case of *
* exceptional circumstances). Thank you for your support! *
* *
***************************************************************************
1 tab == 4 spaces!
29
Nicolas Melot Study of an operating system: FreeRTOS Appendix
*/
/*
* The simplest possible implementation of pvPortMalloc(). Note that this
* implementation does NOT allow allocated memory to be freed again.
*
* See heap_2.c and heap_3.c for alternative implementations, and the memory
* management pages of http://www.FreeRTOS.org for more information.
*/
#include <stdlib.h>
#include "FreeRTOS.h"
#include "task.h"
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* Allocate the memory for the heap. The struct is used to force byte
alignment without using any nonportable code. */
static union xRTOS_HEAP
{
#if portBYTE_ALIGNMENT == 8
volatile portDOUBLE dDummy;
#else
volatile unsigned long ulDummy;
#endif
unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];
} xHeap;
/* Ensure that blocks are always aligned to the required number of bytes.
*/
#if portBYTE_ALIGNMENT != 1
if( xWantedSize & portBYTE_ALIGNMENT_MASK )
{
/* Byte alignment required. */
xWantedSize += ( portBYTE_ALIGNMENT ( xWantedSize &
portBYTE_ALIGNMENT_MASK ) );
}
#endif
vTaskSuspendAll();
{
/* Check there is enough room left for the allocation. */
if( ( ( xNextFreeByte + xWantedSize ) < configTOTAL_HEAP_SIZE ) &&
( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check
for overflow. */
30
Nicolas Melot Study of an operating system: FreeRTOS Appendix
{
/* Return the next free byte then increment the index past
this
block. */
pvReturn = &( xHeap.ucHeap[ xNextFreeByte ] );
xNextFreeByte += xWantedSize;
}
}
xTaskResumeAll();
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
{
if( pvReturn == NULL )
{
extern void vApplicationMallocFailedHook( void );
vApplicationMallocFailedHook();
}
}
#endif
return pvReturn;
}
/**/
8.3 heap_2.c
/*
FreeRTOS V6.0.0 Copyright (C) 2009 Real Time Engineers Ltd.
***************************************************************************
* *
* If you are: *
* *
* + New to FreeRTOS, *
* + Wanting to learn FreeRTOS or multitasking in general quickly *
* + Looking for basic training, *
* + Wanting to improve your FreeRTOS skills and productivity *
31
Nicolas Melot Study of an operating system: FreeRTOS Appendix
* *
* then take a look at the FreeRTOS eBook *
* *
* "Using the FreeRTOS Real Time Kernel a Practical Guide" *
* http://www.FreeRTOS.org/Documentation *
* *
* A pdf reference manual is also available. Both are usually delivered *
* to your inbox within 20 minutes to two hours when purchased between 8am *
* and 8pm GMT (although please allow up to 24 hours in case of *
* exceptional circumstances). Thank you for your support! *
* *
***************************************************************************
1 tab == 4 spaces!
/*
* A sample implementation of pvPortMalloc() and vPortFree() that permits
* allocated blocks to be freed, but does not combine adjacent free blocks
* into a single larger block.
*
* See heap_1.c and heap_3.c for alternative implementations, and the memory
* management pages of http://www.FreeRTOS.org for more information.
*/
#include <stdlib.h>
#include "FreeRTOS.h"
32
Nicolas Melot Study of an operating system: FreeRTOS Appendix
#include "task.h"
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/* Allocate the memory for the heap. The struct is used to force byte
alignment without using any nonportable code. */
static union xRTOS_HEAP
{
#if portBYTE_ALIGNMENT == 8
volatile portDOUBLE dDummy;
#else
volatile unsigned long ulDummy;
#endif
unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];
} xHeap;
/* Define the linked list structure. This is used to link free blocks in order
of their size. */
typedef struct A_BLOCK_LINK
{
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the
list. */
size_t xBlockSize; /*<< The size of the
free block. */
} xBlockLink;
/* Create a couple of list links to mark the start and end of the list. */
static xBlockLink xStart, xEnd;
/* Keeps track of the number of free bytes remaining, but says nothing about
fragmentation. */
static size_t xFreeBytesRemaining;
/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH.
*/
/*
* Insert a block into the list of free blocks which is ordered by size of
* the block. Small blocks at the start of the list and large blocks at the end
* of the list.
*/
#define prvInsertBlockIntoFreeList( pxBlockToInsert )
\
{
\
xBlockLink *pxIterator;
\
size_t xBlockSize;
\
\
xBlockSize = pxBlockToInsert>xBlockSize;
\
33
Nicolas Melot Study of an operating system: FreeRTOS Appendix
\
/* Iterate through the list until a block is found that has a larger size
*/ \
/* than the block we are inserting. */
\
for( pxIterator = &xStart; pxIterator>pxNextFreeBlock>xBlockSize <
xBlockSize; pxIterator = pxIterator>pxNextFreeBlock ) \
{
\
/* There is nothing to do here just iterate to the correct
position. */ \
}
\
\
/* Update the list to include the block being inserted in the correct */
\
/* position. */
\
pxBlockToInsert>pxNextFreeBlock = pxIterator>pxNextFreeBlock;
\
pxIterator>pxNextFreeBlock = pxBlockToInsert;
\
}
/**/
#define prvHeapInit()
\
{
\
xBlockLink *pxFirstFreeBlock;
\
\
/* xStart is used to hold a pointer to the first item in the list of free
*/ \
/* blocks. The void cast is used to prevent compiler warnings. */
\
xStart.pxNextFreeBlock = ( void * ) xHeap.ucHeap;
\
xStart.xBlockSize = ( size_t ) 0;
\
\
/* xEnd is used to mark the end of the list of free blocks. */
\
xEnd.xBlockSize = configTOTAL_HEAP_SIZE;
\
xEnd.pxNextFreeBlock = NULL;
\
\
/* To start with there is a single free block that is sized to take up the
\
entire heap space. */
\
pxFirstFreeBlock = ( void * ) xHeap.ucHeap;
34
Nicolas Melot Study of an operating system: FreeRTOS Appendix
\
pxFirstFreeBlock>xBlockSize = configTOTAL_HEAP_SIZE;
\
pxFirstFreeBlock>pxNextFreeBlock = &xEnd;
\
\
xFreeBytesRemaining = configTOTAL_HEAP_SIZE;
\
}
/**/
vTaskSuspendAll();
{
/* If this is the first call to malloc then the heap will require
initialisation to setup the list of free blocks. */
if( xHeapHasBeenInitialised == pdFALSE )
{
prvHeapInit();
xHeapHasBeenInitialised = pdTRUE;
}
35
Nicolas Melot Study of an operating system: FreeRTOS Appendix
xFreeBytesRemaining = xWantedSize;
}
}
}
xTaskResumeAll();
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
{
if( pvReturn == NULL )
{
extern void vApplicationMallocFailedHook( void );
vApplicationMallocFailedHook();
}
}
#endif
36
Nicolas Melot Study of an operating system: FreeRTOS Appendix
return pvReturn;
}
/**/
if( pv )
{
/* The memory being freed will have an xBlockLink structure
immediately
before it. */
puc = heapSTRUCT_SIZE;
vTaskSuspendAll();
{
/* Add this block to the list of free blocks. */
prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) );
xFreeBytesRemaining += pxLink>xBlockSize;
}
xTaskResumeAll();
}
}
/**/
8.4 heap_3.c
/*
FreeRTOS V6.0.0 Copyright (C) 2009 Real Time Engineers Ltd.
***************************************************************************
* *
* If you are: *
* *
* + New to FreeRTOS, *
* + Wanting to learn FreeRTOS or multitasking in general quickly *
* + Looking for basic training, *
* + Wanting to improve your FreeRTOS skills and productivity *
* *
* then take a look at the FreeRTOS eBook *
* *
* "Using the FreeRTOS Real Time Kernel a Practical Guide" *
37
Nicolas Melot Study of an operating system: FreeRTOS Appendix
* http://www.FreeRTOS.org/Documentation *
* *
* A pdf reference manual is also available. Both are usually delivered *
* to your inbox within 20 minutes to two hours when purchased between 8am *
* and 8pm GMT (although please allow up to 24 hours in case of *
* exceptional circumstances). Thank you for your support! *
* *
***************************************************************************
1 tab == 4 spaces!
/*
* Implementation of pvPortMalloc() and vPortFree() that relies on the
* compilers own malloc() and free() implementations.
*
* This file can only be used if the linker is configured to to generate
* a heap memory area.
*
* See heap_2.c and heap_1.c for alternative implementations, and the memory
* management pages of http://www.FreeRTOS.org for more information.
*/
#include <stdlib.h>
#include "FreeRTOS.h"
38
Nicolas Melot Study of an operating system: FreeRTOS Appendix
#include "task.h"
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/**/
vTaskSuspendAll();
{
pvReturn = malloc( xWantedSize );
}
xTaskResumeAll();
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
{
if( pvReturn == NULL )
{
extern void vApplicationMallocFailedHook( void );
vApplicationMallocFailedHook();
}
}
#endif
return pvReturn;
}
/**/
39