We use a S32k142 with active MPU to separate safety-critical and non-safety functions.
So far it works in common context (outside of interrupts). We don't have an OS (we don't need it and want to avoid complexity).
Our communication stack for LIN uses the receive interrupt to handle time critical code. The stack is a non-safety function and we try to let it run in user mode to prevent spurious writes.
As interrupt context has no access restrictions we have to run the code immediately in user mode.
Our solution:
If an interrupt occurs CONTROL (current mode) and LR (current stack pointer usage) register are saved in a backup. Related interrupts are disabled to prevent re-entrance while in user mode.
Return context for time critical code is placed on PSP (r0-r3,r12,LR,PC and xPSR). This context contains 0 for r0-r3 and r12, xPSR is 0x1000000u, PC is the address of time critical function and LR is set to a "naked" function address with "SVC #switchback".
We set CONTROL bit 0 to 1 and LR to "return to thread, PSP used, no FPC" (0xFFFFFFFDu). The interrupt has lowest priority. It can't be called from handler context (0xFFFFFFx1u, 0xFFFFFFx1u).
With an "BX LR" we return from interrupt to our time critical code. It runs and returns to our crafted "SVC #switchback" function which calls SVC to remove our modifications.
SVC adds 32 ( 8x4 bytes) to PSP, restores LR and CONTROL register from backup, enables related interrupts and calls "BX LR".
So far it works. If the interrupt occurs, critical code is executed immediately and returns after execution.
Problem:
Critical code ignores all MPU access rights, even supervisor rights as we have a section with no write rights for user and supervisor - it seems to still run in interrupt context.
"BX LR" with crafted LR should leave interrupt context.
Have we missed something like a register?
Regards,
Andreas