CMSIS-RTOS2  Version 2.2.0
Real-Time Operating System: API and RTX Reference Implementation
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
MPU Protected Zones

Memory Protection Unit (MPU) is available on many Cortex-M devices and allows restricted access to memory regions and peripherals. The Cortex-M Reference Manuals provide detailed information about the MPU.

An MPU Protected Zone is a set of multiple memory regions and peripherals with specified access rights. One or more RTOS threads can be assigned to an MPU Protected Zone.

The figure below illustrates the concept for MPU Protected Zones that isolate various threads.

rtos_mpu.png
Process isolation with MPU in RTX RTOS

Sections below explains how to use MPU Protected Zones.

Function references

Summary of functions that implement MPU Protected Zone functionality:

Define MPU Protected Zones

In the architectural design phase an application is logically split into functionalities with the same integrity level (same safety requirements). They can safely operate within the same MPU Protected Zone and hence access same memory areas and peripherals.

MPU protected zones are defined in an MPU table where each row describes an individual MPU zone and each cell in the row specifies an MPU region within that zone. For details see section MPU Functions in CMSIS-Core(M) documentation.

CMSIS-Zone provides a utility that allows graphic configuration of MPU protected zones and generates MPU table in the CMSIS format.

Note
Interrupt handlers bypass the MPU protection. For this reason, it is required that all interrupt handlers are verified according to the highest integrity level to exclude unintended memory accesses.

Zone Identifiers

Zone ID is used to refer to a specific MPU protected zone. Zone ID value equals to the row index (starting from 0) in the MPU table that describes corresponding MPU Protected Zone. An MPU Protected Zone is assigned to one or more RTOS threads. This is done by providing the Zone ID value in thread attributes osThreadAttr_t when creating the thread with the osThreadNew function.

Example:

/* ThreadA thread attributes */
const osThreadAttr_t thread_A_attr = {
.name = "ThreadA", // human readable thread name
.attr_bits = osThreadZone(3U) // assign thread to MPU protected zone 3
};
osThreadNew(ThreadA, NULL, &thread_A_attr);

Load MPU Protected Zone

When switching threads the RTOS kernel compares Zone IDs of the currently running thread and the next thread to be executed. If the Zone Ids are different then a callback function osZoneSetup_Callback is called. This function shall be implemented in the user application code to actually switch to the new MPU Protected Zone. In the function the user should load the MPU Protected Zone according to the Zone Id provided in the argument.

Example:

/* Update MPU settings for newly activating Zone */
void osZoneSetup_Callback (uint32_t zone) {
if (zone >= ZONES_NUM) {
// Here issue an error for incorrect zone value
}
ARM_MPU_Load(mpu_table[zone], MPU_REGIONS);
}

RTOS Objects and MPU Protection

To access RTOS objects from the application RTOS APIs rely on a numeric xxx_id parameter associated with the object as explained in CMSIS-RTOS C API v2. For example

osEventFlagsId_t evt_flags;
evt_flags = osEventFlagsNew(NULL);
osEventFlagsSet(evt_flags, 1);

The allocation of an RTOS object to the memory in a specific MPU Protected Zone does not provide access restriction. The access restriction can be bypassed if another thread calls the CMSIS-RTOS2 API with the object ID of the RTOS object as argument. The CMSIS-RTOS2 function is executed in handler mode and therefore can access and modify the RTOS object without raising a Memory Fault. To enable access control for RTOS objects the Safety Classes concept is introduced in CMSIS-RTOS2.

Handle Memory Access Faults

A memory access fault is triggered when a thread tries to access memory or peripherals outside of the MPU Protected Zone loaded while the thread is running. In such case Memory Management Interrupt (MemoryManagement_IRQn) is triggered by the processor and its handling function is executed according to the exception vector table specified in the device startup file (by default MemManage_Handler(void) ).

The MemManage_Handler() interrupt handler is application specific and needs to be implemented by the user. In the handler it is possible to identify the thread that caused the memory access fault, the corresponding zone id and the safety class. This information can be used to define actions for entering a safe state. Fault Handling provides more details on the available system recovery possibilities.