2 \addtogroup CMSIS_RTOS_ProcessIsolation Process Isolation
3 \ingroup CMSIS_RTOS CMSIS_RTOSv2
6 This chapter explains mechanisms available for process isolation support in CMSIS-RTOS2 API.
8 See \ref fusa_process_isolation for a summary of other related pages such as RTX configuration and safety user requirements.
11 CMSIS-RTOS2 API defines a set of features to protect critical parts of an application against software flaws that may exist in other parts of an application.
14 - <b>\ref rtos_process_isolation_mpu</b> for memory access protection in the system.
16 RTOS threads can access only memory regions and peripherals based on their MPU Protected Zone assignment. Non-privileged thread code cannot accidentally modify critical RTOS kernel data or memory belonging to other zones.
19 - <b>\ref rtos_process_isolation_safety_class</b> for access protection to RTOS objects.
21 The RTOS objects with a higher safety class assigned to them cannot be modified via RTOS API functions from threads that have lower safety class assigned.
24 - <b>\ref rtos_process_isolation_thread_wdt</b> to verify execution times of threads.
26 Each thread can maintain own thread watchdog and in case of timing violations, corresponding thread watchdog alarm will be triggered.
29 - <b>\ref rtos_process_isolation_faults</b> in case of a detected failure (for example thread watchdog alarm or MPU Fault).
31 The RTOS provides functions to block execution of malfunctioning components and with that dedicate system resources for operation of the safety critical threads.
34 Section \ref fusa_process_isolation lists safety requirements for Process Isolation functions.
37 \addtogroup rtos_process_isolation_mpu MPU Protected Zones
39 Memory Protection Unit (MPU) is available on many Cortex-M devices and allows restricted access to memory regions and peripherals. <a href="../../Core/html/index.html#ref_man_sec"><b>The Cortex-M Reference Manuals</b></a> provide detailed information about the MPU.
41 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.
43 The figure below illustrates the concept for MPU Protected Zones that isolate various threads.
45 \image html rtos_mpu.png "Process isolation with MPU in RTX RTOS"
47 Sections below explains how to use MPU Protected Zones.
48 - \ref rtos_process_isolation_mpu_refs
49 - \ref rtos_process_isolation_mpu_def
50 - \ref rtos_process_isolation_mpu_load
51 - \ref rtos_process_isolation_mpu_objects
52 - \ref rtos_process_isolation_mpu_fault
54 \section rtos_process_isolation_mpu_refs Function references
56 Summary of functions that implement MPU Protected Zone functionality:
58 - \ref osThreadNew : \copybrief osThreadNew
59 - \ref osThreadZone : \copybrief osThreadZone
60 - \ref osThreadGetZone : \copybrief osThreadGetZone
61 - \ref osThreadTerminateZone : \copybrief osThreadTerminateZone
62 - \ref osZoneSetup_Callback : \copybrief osZoneSetup_Callback
64 \section rtos_process_isolation_mpu_def Define MPU Protected Zones
66 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.
68 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 <a href="../../Core/html/group__mpu__functions.html"><b>MPU Functions</b></a> in CMSIS-Core(M) documentation.
70 <a href="https://arm-software.github.io/CMSIS_5/Zone/html/index.html" target="_blank"><b>CMSIS-Zone</b></a> provides a utility that allows graphic configuration of MPU protected zones and generates MPU table in the CMSIS format.
73 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.
75 \subsection rtx_process_isolation_mpu_id Zone Identifiers
76 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.
77 An MPU Protected Zone is assigned to one or more RTOS threads. This is done by providing the Zone ID value in thread attributes \ref osThreadAttr_t when creating the thread with the \ref osThreadNew function.
82 /* ThreadA thread attributes */
83 const osThreadAttr_t thread_A_attr = {
84 .name = "ThreadA", // human readable thread name
85 .attr_bits = osThreadZone(3U) // assign thread to MPU protected zone 3
87 osThreadNew(ThreadA, NULL, &thread_A_attr);
90 \section rtos_process_isolation_mpu_load Load MPU Protected Zone
92 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 \ref 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.
96 /* Update MPU settings for newly activating Zone */
97 void osZoneSetup_Callback (uint32_t zone) {
99 if (zone >= ZONES_NUM) {
100 // Here issue an error for incorrect zone value
103 ARM_MPU_Load(mpu_table[zone], MPU_REGIONS);
107 \section rtos_process_isolation_mpu_objects RTOS Objects and MPU Protection
108 To access RTOS objects from the application RTOS APIs rely on a numeric xxx_id parameter associated with the object as explained in \ref rtos_api2. For example
111 osEventFlagsId_t evt_flags;
112 evt_flags = osEventFlagsNew(NULL);
113 osEventFlagsSet(evt_flags, 1);
116 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.
117 To enable access control for RTOS objects the \ref rtos_process_isolation_safety_class concept is introduced in CMSIS-RTOS2.
119 \section rtos_process_isolation_mpu_fault Handle Memory Access Faults
121 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 (<a href="../../Core/html/group__NVIC__gr.html "><b>MemoryManagement_IRQn</b></a>) 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 \token{MemManage_Handler(void)} ).
123 The \e 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. \ref rtos_process_isolation_faults provides more details on the available system recovery possibilities.
125 \addtogroup rtos_process_isolation_safety_class Safety Classes
127 \ref rtos_process_isolation_mpu_objects explains that MPU Protected Zones do not provide full access protection to RTOS objects accessed via CMSIS-RTOS2 API. The concept of a safety class fills this gap.
129 Every RTOS object, including thread is assigned with a numeric safety class value. A thread cannot modify an RTOS object if its safety class value is higher than the safety class value of the thread.
130 For example, it is not possible to change the priority or suspend a thread that has a higher safety class value than the thread that is currently executed.
132 \section rtos_process_isolation_safety_class_refs Function references
134 Summary of functions and macros that implement safety classes:
136 - \ref osSafetyClass : \copybrief osSafetyClass
137 - \ref osThreadGetClass : \copybrief osThreadGetClass
138 - \ref osSafetyWithSameClass : \copybrief osSafetyWithSameClass
139 - \ref osSafetyWithLowerClass : \copybrief osSafetyWithLowerClass
140 - \ref osKernelProtect : \copybrief osKernelProtect
141 - \ref osThreadSuspendClass : \copybrief osThreadSuspendClass
142 - \ref osThreadResumeClass : \copybrief osThreadResumeClass
143 - \ref osKernelDestroyClass : \copybrief osKernelDestroyClass
145 \ref rtos_process_isolation_safety_class_assign lists CMSIS-RTOS2 API functions that support safety class assignment when creating RTOS objects.
146 \ref rtos_process_isolation_safety_class_error lists CMSIS-RTOS2 API functions that verify safety class assignment before execution.
147 \section rtos_process_isolation_safety_class_assign Assign Safety Class to an RTOS Object
149 It is possible to create any objects regardless of the safety class after the kernel initialize with \ref osKernelInitialize, but before the kernel is started with \ref osKernelStart. This allows to setup a system before actually starting the RTOS kernel.
151 Threads of a higher safety class can create RTOS objects that belong to a lower or same safety class. For the object types listed below, the \e attr_bits can have an optional safety class value that is assigned when the RTOS object is created with the \e <i>os<Object>New</i> function. The macro \ref osSafetyClass encodes the value for the \e attr_bits field in the attr struct. For example:
154 const osEventFlagsAttr_t evt_flags_attr = {
155 .attr_bits = osSafetyClass(SAFETY_CLASS_SAFE_MODE_OPERATION)
157 osEventFlagsId_t evt_flags;
158 evt_flags = osEventFlagsNew(&evt_flags_attr);
161 The following object types support safety class assignment when creating an object with corresponding \e os<Object>New function:
163 - \ref osThreadAttr_t \copybrief osThreadAttr_t Used in the \ref osThreadNew function.
164 - \ref osEventFlagsAttr_t \copybrief osEventFlagsAttr_t Used in the \ref osThreadNew function.
165 - \ref osTimerAttr_t \copybrief osTimerAttr_t Used in the \ref osTimerNew function.
166 - \ref osMutexAttr_t \copybrief osMutexAttr_t Used in the \ref osMutexNew function.
167 - \ref osSemaphoreAttr_t \copybrief osSemaphoreAttr_t Used in the \ref osSemaphoreNew function.
168 - \ref osMemoryPoolAttr_t \copybrief osMemoryPoolAttr_t Used in the \ref osMemoryPoolNew function.
169 - \ref osMessageQueueAttr_t \copybrief osMessageQueueAttr_t Used in the \ref osMessageQueueNew function.
171 If safety class is not provided when creating the RTOS object then it inherits the safety class of the current running thread that creates the object. If the object is created before kernel is started and no safety class is provided, then it receives default safety class 0. This simplifies integration of third-party code that can be classified as non-safety critical.
173 \section rtos_process_isolation_safety_class_error Handle Object Access Violation
175 RTOS API call returns error code \ref osErrorSafetyClass if the requested object manipulation cannot be performed because the target object has higher safety class than the safety class of the running thread. For example:
177 status = osEventFlagsSet(evt_flags, 1);
178 if (status == osErrorSafetyClass)
180 //handle the safety class error
185 Following functions compare the safety class of the running thread with the safety class of the target object.
187 In \ref CMSIS_RTOS_KernelCtrl functions:
189 Comparison is done with safety class configured with \ref osKernelProtect
191 - \ref osKernelRestoreLock
192 - \ref osKernelSuspend
193 - \ref osKernelProtect
194 - \ref osKernelDestroyClass
196 In \ref CMSIS_RTOS_ThreadMgmt functions:
198 - \ref osThreadSetPriority
199 - \ref osThreadSuspend
200 - \ref osThreadResume
201 - \ref osThreadDetach
203 - \ref osThreadTerminate
204 - \ref osThreadSuspendClass
205 - \ref osThreadResumeClass
207 In \ref CMSIS_RTOS_ThreadFlagsMgmt functions:
208 - \ref osThreadFlagsSet
210 In \ref CMSIS_RTOS_EventFlags functions:
211 - \ref osEventFlagsNew
212 - \ref osEventFlagsSet
213 - \ref osEventFlagsClear
214 - \ref osEventFlagsWait
215 - \ref osEventFlagsDelete
217 In \ref CMSIS_RTOS_TimerMgmt functions:
223 In \ref CMSIS_RTOS_MutexMgmt functions:
225 - \ref osMutexAcquire
228 In \ref CMSIS_RTOS_SemaphoreMgmt functions:
229 - \ref osSemaphoreNew
230 - \ref osSemaphoreAcquire
231 - \ref osSemaphoreRelease
232 - \ref osSemaphoreDelete
234 In \ref CMSIS_RTOS_PoolMgmt functions:
235 - \ref osMemoryPoolNew
236 - \ref osMemoryPoolAlloc
237 - \ref osMemoryPoolFree
238 - \ref osMemoryPoolDelete
240 In \ref CMSIS_RTOS_Message functions:
241 - \ref osMessageQueueNew
242 - \ref osMessageQueuePut
243 - \ref osMessageQueueGet
244 - \ref osMessageQueueReset
245 - \ref osMessageQueueDelete
249 \addtogroup rtos_process_isolation_thread_wdt Thread Watchdogs
251 CMSIS-RTOS defines <b>Thread Watchdogs</b> that allow to control timing constraints for thread execution (<a href="https://en.wikipedia.org/wiki/Temporal_isolation" target="_blank"><b>temporal isolation</b></a>).
253 Each thread has an independent watchdog timer that is started with the function \ref osThreadFeedWatchdog(uint32_t ticks). The \token{ticks} value specifies the timeout before it expires. Within this time interval the function \ref osThreadFeedWatchdog must be called again within the thread to restart the watchdog timer.
255 If the thread watchdog is not restarted during the specified amount of ticks the Watchdog Alarm callback \ref osWatchdogAlarm_Handler(osThreadId_t thread_id) is triggered and can be used to recover the system or proceed to the system shutdown.
257 Figure below explains the concept with an example:
259 \image html thread_watchdogs.png "Example use of Thread Watchdogs"
261 \ref rtos_process_isolation_faults provides more details on the available possibilities for system recovery.
262 \note If the application suspends a thread from scheduling by calling \ref osThreadSuspend or \ref osThreadSuspendClass, the thread watchdog still continues to run, and it is expected to expire and trigger \ref osWatchdogAlarm_Handler because the thread will not be serviced as expected.
263 \note Hence it may be necessary to differentiate handling of thread watchdogs that expired unexpectedly from the thread watchdog alarms of intentionally suspended threads.
265 \section rtos_process_isolation_thread_wdt_refs Function references
267 Summary of functions that implement thread watchdog functionality
269 - \ref osThreadFeedWatchdog : \copybrief osThreadFeedWatchdog
270 - \ref osWatchdogAlarm_Handler : \copybrief osWatchdogAlarm_Handler
272 \addtogroup rtos_process_isolation_faults Fault Handling
274 When a failure, or an error is detected in a system (for example \ref rtos_process_isolation_mpu_fault "memory access fault", \ref rtos_process_isolation_thread_wdt "thread watchdog alarm", or others) CMSIS-RTOS2 API allows to stop further execution of selected RTOS threads. This can be used to block malfunctioning components or free computing resources and so enable execution of the safety critical threads.
276 Following approaches are available:
277 - function \ref osThreadTerminateZone can be called in case of a fault exception. It will terminate all threads from the specified MPU Protected Zone (for example, can be the zone that has caused the fault). The function cannot be called in thread context or interrupts other than faults. Note that \ref osFaultResume can be called at the end of the handling code to return program execution into a known context and let kernel schedule the next thread ready for execution.
278 - function \ref osThreadSuspendClass can be called in case of a thread watchdog alarm or other errors handled in thread context. It allows to suspend operation of threads based on the safety class assignment. Function \ref osThreadResumeClass can be used to resume operation of threads based on their safety class. \ref rtos_process_isolation_thread_wdt contains an example that demonstrates fault handling concept for thread watchdogs.
280 Function \ref osKernelDestroyClass fully removes RTOS objects of specific safety classes from the system. This can be useful to do before restarting operation of terminated or suspended threads.
282 \section rtos_process_isolation_faults_refs Function references
284 Following CMSIS-RTOS2 functions and macros support fault handling:
286 - \ref osThreadGetZone : \copybrief osThreadGetZone
287 - \ref osThreadTerminateZone : \copybrief osThreadTerminateZone
288 - \ref osThreadGetClass : \copybrief osThreadGetClass
289 - \ref osSafetyWithSameClass : \copybrief osSafetyWithSameClass
290 - \ref osSafetyWithLowerClass : \copybrief osSafetyWithLowerClass
291 - \ref osThreadSuspendClass : \copybrief osThreadSuspendClass
292 - \ref osThreadResumeClass : \copybrief osThreadResumeClass
293 - \ref osKernelDestroyClass : \copybrief osKernelDestroyClass
294 - \ref osFaultResume : \copybrief osFaultResume
295 - \ref osWatchdogAlarm_Handler : \copybrief osFaultResume