FreeRTOS, OpenRTOS and in most cases SafeRTOS are supplied as source code for static linking into the users application. The build process
therefore results in a single executable binary image. Typically such an image will include a C start up routine to set up the C run time
environment, before calling main() to execute the users application. The interrupt vector table will also be statically configured and
included at a predetermined location within the same binary.

The table below provides an indication of the sequence of processing booting such a system will require, along with some guidance on the time
required for this processing to complete. Note that any numbers provided are indicative only and realistic. Actual times achievable will
depend on the architecture being used, the clock frequencies configured, and the configuration of the memory interface.

#

Description

Timing

1

Configure the CPU clocks for the performance level required.

Typically requires a few register writes, followed by a short delay for clocks to lock. This will
take in the order of a few microseconds, depending on the architecture being used.

This is an optional step. It could be performed later from C code but can boost the boot time if
it is performed prior to initializing memory.

2

Initialize static and global variables that contain only the value zero (bss).

Including FreeRTOS in an application would typically only add an extra couple of hundred write accesses
to be performed within a very tight assembly loop. This will add in the region of a few microseconds
to the time taken when compared to that taken were the RTOS kernel not included.

3

Initialize variables that contain a value other than zero.

Including FreeRTOS in an application would typically not add any extra time to this step.

4

Perform any other hardware set up required.

Often it is desirable to configure peripherals prior to starting the RTOS scheduler. How long this takes will
depend on the complexity of the peripherals being used, but on the class of microcontroller targeted by
FreeRTOS the total time would typically require a few milliseconds only.

5

Create application queues, semaphores and mutexes.

Typically the majority of queues, semaphores and mutexes will be created prior to the RTOS scheduler being started.

By way of example, on a ARM Cortex-M3 device, using the ARM RVDS compiler with optimization set to 1 (low),
creating a queue, semaphore or mutex will take approximately 500 CPU cycles.

6

Create application tasks.

Typically the majority of tasks will be created prior to the RTOS scheduler being started.

By way of example, on a ARM Cortex-M3 device, using the ARM RVDS compiler with optimization
set to 1 (low), creating each task will take approximately 1100 CPU cycles.

7

Start the RTOS scheduler.

The RTOS scheduler is started by calling vTaskStartScheduler(). The start up process includes configuring the
tick interrupt, creating the idle task, and then restoring the context of the first task to run.

By way of example, on a ARM Cortex-M3 device, using the ARM RVDS compiler with optimization set to 1 (low),
starting the RTOS scheduler will take approximately 1200 CPU cycles.

Under these test conditions the context switch time is not not dependent
on whether a different task was selected to run or the same task was
selected to continue running.

The ARM Cortex-M port performs all task context switches in the PendSV
interrupt. The quoted time does not include interrupt entry time.

The quoted time includes a short section of C code. It has been determined
that 12 CPU cycles could have been saved by providing the entire implementation
in assembly code. It is considered that the benefit of maintaining a short
section of generic C code (for reasons of maintenance, support, robustness,
automatic inclusion of features such as tracing, etc.) outweighs the benefit
of removing 12 CPU cycles from the context switch time.

The Cortex-M CPU registers that are not automatically saved on interrupt
entry can be saved with a single assembly instruction, then restored again
with a further single assembly instruction. These two instructions on their
own consume 12 CPU cycles.

Three of the example memory allocation schemes
supplied with FreeRTOS allocate memory from a statically allocated array that is
dimensioned by the configTOTAL_HEAP_SIZE constant in FreeRTOSConfig.h.
These are just normal statically allocated arrays, and therefore appear in the RAM
usage figures provided by many tool chains. The tool chain is in effect showing
the heap as consumed RAM, even though at that point the heap is completely free
as no memory has actually been allocated.

C applications require some RAM for things like static variables, buffers, etc. but
will rarely use all the RAM available on a microcontroller. Many of the FreeRTOS
demo applications dimension the heap to use up all the RAM that is left over,
making it appear as if the application is using all the RAM available.

Event management is built into the queue functionality. This means the queue data structures contain all the RAM that other RTOS
systems sometimes allocate separately. There is no concept of an event control block within FreeRTOS.

Use the xPortGetFreeHeapSize() and (where available) the xPortGetMinimumEverFreeHeapSize()
API functions to see how much FreeRTOS heap is being allocated but never
used, and adjust
accordingly.

If heap_1.c, heap_2.c, heap_4.c or heap_5.c are being used, and nothing
in your application is ever calling malloc() directly (as opposed to pvPortMalloc()), then ensure the
linker is not allocated a heap to the C library because it will never
get used.

Set configMAX_PRIORITIES and configMINIMAL_STACK_SIZE (found in portmacro.h) to the minimum values acceptable to your application.

Recover the stack used by main(). The stack used upon program entry is not required once the RTOS scheduler has
been started (unless your application calls vTaskEndScheduler(), which is only supported directly in the distribution for
the PC and Flashlite ports, or uses the stack as an interrupt stack as is done
in the ARM Cortex-M and RX ports). Every task has its own stack allocated so the stack allocated to main() is available for reuse once
the RTOS scheduler has started.

Minimise the stack used by main(). The idle task is automatically created when you create the first application task.
The stack used upon program entry (before the RTOS scheduler has started) must therefore be large enough for a nested call to
xTaskCreate(). Creating the idle task manually can half this stack requirement. To create the idle task manually:

Locate the function prvInitialiseTaskLists() in Source\tasks.c.

The idle task is created at the bottom of the function by a call to xTaskCreate(). Cut this line from Source\tasks.c
and paste it into main().

Rationalise the number of tasks. The idle task is not required if:

Your application has a task that never blocks, and ...

Your application does not make any calls to vTaskDelete().

Reduce the data size used by the definition BaseType_t (this can increase execution time).

There are other minor tweaks that can be performed (for example the task priority queues don't require event management), but if you get
down to this level - you need more RAM!

The quoted ROM/Flash footprint figures are genuine. If you write a tiny FreeRTOS test program and it appears to consume more ROM than expected
then it is probably because of the libraries that are being included in your build, not because of FreeRTOS. In particular, GCC string handling and any floating point
library is going to bloat your code.

FreeRTOS includes a very cut down open source implementation of many string handling functions in a file called printf-stdarg.c.
Including this in your project can greatly reduce both the amount of ROM used by the build, and the size of the stack required to
be allocated to any task making a string handling library call (sprintf() for example). Note that printf-stdarg.c is open source,
but not covered by the FreeRTOS license. Ensure you are happy with the license conditions stated in the file itself before use.

Also, most linkers will remove unused code by default, but the GNU linker will only remove unused code if you explicitly tell it to.

Check the output .map file to find exactly how ROM/Flash is being used.

Two calls to pvPortMalloc() are made when a task is created. The first allocates the task control block, the second allocates
the task stack. The stack used by main() is not used by tasks, but (depending on the port) may be used by interrupts.

This is completely application dependent, and not always easy to calculate. It depends on the function call depth, number of local variables
allocated, number of parameters in function calls made, etc. The stack must always be large enough
to contain the execution context (all the processor registers).

The FreeRTOS download contains a demo application for each port. A task created
using that port must not be allocated a stack size that is lower than the value
of configMINIMAL_STACK_SIZE used in the demo application. The RTOS kernel itself
only uses configMINIMAL_STACK_SIZE to set the size of the stack used by the idle task.
Tasks that allocate more variables than the idle task, or have a larger function
call nesting depth than the idle task, will require a larger stack.

The stack of each task is filled with 0xa5 bytes upon creation which allows the
high water mark to be viewed using suitable debugging tools, and obtained using
the uxTaskGetStackHighWaterMark()
API function. The RTOS kernel can also be built to include
stack overflow detection.

Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2015 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd..
See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.