Third parties maintain MPU ports to other microcontroller cores.
MPU costs and benefits
FreeRTOS MPU ports enable microcontroller applications to be more robust and more secure by first enabling tasks to run in either privileged or unprivileged mode, and second restricting access to resources such as RAM, executable code, peripherals, and memory beyond the limit of a task's stack. Huge benefit is gained from, for example, preventing code from ever executing from RAM as doing so will protect against many attack vectors such as buffer overflow exploits or the execution of malicious code loaded into RAM.
Use of an MPU necessarily makes application design more complex because first the MPU's memory region restrictions must be determined and described to the RTOS, and second the MPU restricts what application tasks can and cannot do.
Creating an application that constrains every task to its own memory region may be the most secure, but it is also the most complex to design and implement. Often it is best to use an MPU to create a pseudo process and thread model - where groups of threads are allowed to share a memory space. For example, create one memory space accessible to trusted first party code, and another that is only accessible to untrusted third party code.
The demo project in the FreeRTOS/Demo/CORTEX_MPU_Simulator_Keil_GCC directory, which uses Keil uVision
to build and simulate a GCC project, provides a worked example that does not require any particular hardware.
Additional FreeRTOS-MPU examples projects include the Nuvoton NuMaker-PFM-M2351 demo
and the NXP LPCXpresso55S69 demo demo, among others.
[The FreeRTOS-MPU demo projects located in the FreeRTOS/Demo/CORTEX_MPU_LPC1768_GCC_RedSuite and
FreeRTOS/Demo/CORTEX_MPU_LM3Sxxxx_Rowley directories were retired prior to the
release of FreeRTOS V9.0.0]
FreeRTOS MPU ports have been updated in response to the end-user feedback. This section describes the changes necessary to upgrade to FreeRTOS V10.4.0 or newer, and prior to that, to upgrade to FreeRTOS V10.3.0 or newer.
Changes in FreeRTOS version 10.4.0:
FreeRTOS V10.4.0 introduced a new variable __privileged_functions_start__
to indicate the starting location of the privileged code. It needs to be
exported from linker script in the same way as the pre-existing linker
variables such as __privileged_functions_end__.
If you get a linker error in an earlier created
project for unresolved symbol __privileged_functions_start__, you
need to export a variable __privileged_functions_start__ with the
value equal to __FLASH_segment_start__.
Heap memory is now placed in the privileged section, and as a result,
unprivileged tasks cannot call pvPortMalloc() or vPortFree().
FreeRTOS-MPU ports for ARM Cortex-M4 microcontrollers now support microcontrollers
with 16 MPU regions. To use 16 regions set configTOTAL_MPU_REGIONS
to 16 in FreeRTOSConfig.h.
Application writers can now override the default values for the for TEX, Shareable (S),
Cacheable (C) and Bufferable (B) bits for MPU regions covering Flash and RAM by defining
configTEX_S_C_B_FLASH and configTEX_S_C_B_SRAM respectively
Changes in FreeRTOS version 10.3.0:
It is now possible to prevent any privilege escalations originating from
outside of the kernel code (other than escalations performed by the hardware
itself when an interrupt is entered). To do so set
configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY to 1 in FreeRTOSConfig.h,
and define the linker variables __syscalls_flash_start__ and
__syscalls_flash_end__ to be the start and end addresses of the system calls memory
Compatible with the standard ARM Cortex-M3 and Cortex-M4F ports.
Tasks can be created to run in either Privileged mode or Unprivileged mode. Unprivileged
tasks can only access their own stack and up to three user definable memory regions (three per task).
User definable memory regions are assigned to tasks when the task is created, and can
be reconfigured at run time if required.
User definable memory regions can be parameterised individually.
For example, some regions may be set to read only, while others may be set to not executable
(execute never, or simply XN, in ARM terminology), etc.
No data memory is shared between Unprivileged tasks, but Unprivileged tasks can pass messages to
each other using the standard queue and semaphore mechanisms. Shared memory regions can be
explicitly created by using a user definable memory region but this is discouraged.
A Privileged mode task can set itself into Unprivileged mode, but once in Unprivileged mode it
cannot set itself back to Privileged mode.
The FreeRTOS API is located in a region of Flash that can only be accessed while the microcontroller
is in Privileged mode (calling an API function causes a temporary switch to Privilege mode).
The data maintained by the RTOS kernel (all non stack data that is private to the FreeRTOS source files)
is located in a region of RAM that can only be accessed while the microcontroller is in Privileged
System peripherals can only be accessed while the microcontroller is in Privileged mode. Standard
peripherals (UARTs, etc.) are accessible by any code but can be explicitly protected using a user
definable memory region.
Unprivileged Tasks: An unprivileged task only has access to its stack. In
addition, it can be granted access up to three user definable memory regions (three per
task). Unprivilged tasks can only be created using the
Note that xTaskCreate() API must not be used to create an
If a task wants to use the MPU then the following additional information has to be provided:
The address of the task stack.
The start, size and access parameters for up to three user definable memory regions.
The total number of parameters required to create a task is therefore quite large. To make creating
MPU aware tasks easier FreeRTOS-MPU uses an API function called
This allows all but one of the parameters to be defined in a const struct, with the struct being passed
(by reference) into xTaskCreateRestricted() as a single parameter.
A Privileged mode task can call
portSWITCH_TO_USER_MODE() to set
itself into Unprivileged mode. A task that is running in Unprivileged mode cannot set itself into
The memory regions allocated to a task can be changed using
vTaskAllocateMPURegions(). See the
xTaskCreateRestricted() and vTaskAllocateMPURegions() API documentation for more information.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.