Exercises related to Robust Design Patterns - Part 3
MPU Protection
How to handle an exception
Exercice 1
We have seen during the lecture that an exception is raised in case a memory violation occures. Checking the manual contained in the repository (or, though not the source of truth but easier to read)):
- can you name what function is called? What does its default implementation?
- can you infer what thread triggered the violation when the exception handler is called?
- what other pieces of information may one get?
Solution
- The function used is
MemManage_Handler()
. Its default implementation corresponds toasvoid Default_Handler(void) { while(1); }
MemManage_Handler()
is mapped toDefault_Handler
. The example below is taken from one of thestartup_ARMCM*.c
contained inCMSIS/RTOS2/RTX/Examples/Blinky/RTE/Device/ARMCM*
:void MemManage_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
- Yes, the thread ID is available.
- From the manual:
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.
rtos_process_isolation_faults
provides more details on the available system recovery possibilities..
Understanding memory partitioning and zoning
Exercice 2
Look at the following zone to ressource allocation:
- Assume the idle task, belonging to Zone_Idle, is run in unpriviledged
mode. Is there any issue with the above assignments? Could there be any
issue as it can access - at least from the table above - to sensitive
areas like
ARM_LIB_STACK
? (note:ARM_LIB_STACK
is reserved for the ARM C library stack) - Take the above ressource allocation and the line of code
What does this line do with regard to where
static uint32_t sensor_val __attribute__((section("ram_shared"))) = 0U;
sensor_val
is put in memory?
Solution
- This does not cause a safety problem since the resources are only available in privileged mode while the idle thread runs unprivileged.
- It puts the variable into a section named
ram_shared
. This section is part of the memory regionRAM_SHARED
that is enabled for access in all MPU Protected Zones defined in the example (except idle task).
Exercice 3
Look at the following code defining threads attributes:
static uint64_t stack_thrTire[64]; // Stack of Tire Thread
static osThreadId_t tid_thrTire; // Thread id of Tire Thread
const static osThreadAttr_t attr_thrTire = { // Thread attributes of Tire Thread
.name = "TireThread",
#ifdef SOME_MAGIC
.attr_bits = osThreadUnprivileged | osThreadZone(ZONE_NORMAL_OP) | osSafetyClass(SAFETY_CLASS_NORMAL),
#else
.attr_bits = osThreadUnprivileged,
#endif
.cb_mem = NULL,
.cb_size = 0,
.stack_mem = &stack_thrTire,
.stack_size = sizeof(stack_thrTire),
.priority = 11,
.tz_module = 0,
.reserved = 0};
- What does
SOME_MAGIC
do in your opinion? - Do you see any major differences compared to the way attributes for instantiating tasks have been defined so far?
Solution
- It is used to activate Safety Classes and MPU as the corresponding attributes are used.
- The stack (
stack_thrTire
) is explicitly allocated.
Safety Class
Activating the functionality
Exercice 4
If you access
RTX_Config.h
you will see that OS_SAFETY_CLASS
exists. Please answer following questions:
- is it sufficient to activate
OS_SAFETY_CLASS
to get the functionality? - if not, what else should one activate?
- what is one cannot do when this is activated?
- how many files are modified when this flag is activated?
Solution
- No, it is not. Check
RTX_Config.h
, lines 78-79. OS_SAFETY_FEATURES
needs to be activated as well.- Threads assigned to lower classes cannot modify higher class threads.
- 11 (though
OS_SAFETY_CLASS
becomesRTX_SAFETY_CLASS
)
Understanding its way of working
Exercice 5
These are just exemplary questions related to a functionality you are now
familiar with: semaphores. The questions related to the code present in the
development branch
(thus, version > 5.9.1
)
- what is the check concerning SAFETY_CLASS done when acquiring a semaphore?
- what does a call to
svcRtxSemaphoreDelete
do when destroying a semaphore?
Solution
- Here we can see that the correctness of class is checked prior to
acquiring the semaphore for real.
Here the corresponding code :#ifdef RTX_SAFETY_CLASS // Check running thread safety class thread = osRtxThreadGetRunning(); if ((thread != NULL) && ((thread->attr >> osRtxAttrClass_Pos) < (semaphore->attr >> osRtxAttrClass_Pos))) { EvrRtxSemaphoreError(semaphore, (int32_t)osErrorSafetyClass); //lint -e{904} "Return statement before end of function" [MISRA Note 1] return osErrorSafetyClass; } #endif
- There are multiple steps involved. Namely:
- the validity of the semaphore object/ID is checked
- the safety class is checked, thus ensuring the caller is allowed to run the operation
- all tasks waiting on the semaphore are released
- finally the semaphore is destroyed from the kernel objects pool