Showing results for 
Search instead for 
Did you mean: 

Cortex-M33/STM32U5 - unprivileged mode in secure not working?!

42Bastian Schick
Associate II

Ask this at, but maybe it is STM32U5 specific:

I try run an unprivileged application in secure mode and get a strange behavior:

STM32U5 has TZ enabled, all application runs in secure mode.

1) LR = 0xffff_fff9, CONTROL = 1 => BX LR increments the SP, but all registers become 0 (including PC and XPSR!)

2) When setting CONTROL = 1 and executing SVC, SP is decremented correctly, but nothing is stored on the stack?

I check all errata I could find, but no hint.

If TZ is disabled, the system behaves normal.

42Bastian Schick
Associate II

Dummy reply.

Pierre PARIS
ST Employee

Hello @42Bastian Schick ,

Thank you for your question.

Here is some guidance:

  • According to ARM documentation, you define the Thread mode with the MSP use in a unprivileged level. "After any Thread mode transition from privileged to unprivileged execution, software must issue an ISB instruction to ensure instruction fetch correctness." 
  • How are you executing SVC instruction ? Like this :


#define EnablePrivilegedMode() __asm("SVC #0") 


  • Most likely the problem can be because the MPU isolate the memory for unprivileged application. You can read more here (see table 13). What address are you trying to reach ?
  • GTZC can protect against non-secure and optionally unprivileged transactions initiated by masters other than
    the Cortex-M33. Here is a STM32U5-Security-Overview. Do you have any illegal access detected ?
  • Can you tell me more about the application ? Are you using any peripherals/external memories/DMA channel? For your information, when the TZ is activated, peripherals are set as non secure and unprivileged after reset.

Best Regards,


42Bastian Schick
Associate II

The application is our RTOS.

The switch between kernel (privileged) and user process (unprivileged) works correct with TZ disabled on SoC level.

So MPU settings should be correct and there is no access violation directly after the return or after the "svc".

But since the "return" pops all 0 (that is r0..r3,r12,lr and xpsr), the next instruction will cause an invalidate instruction exception.

And since "svc" does not push anything onto the stack, the following code crashes, as the stack contains nonsense.

It is weird, that SP is correctly updated in both cases.

Whether I place my SP in 0x3000.0000 or 0x2000.0000 RAM does not change anything.

There is no change of security, so no "SG".

There is no MPU error.


42Bastian Schick
Associate II

I made an example, the absolute minimum which just runs.

Same behavior "svc" with CONTROL == 0 => registers pushed

CONTROL == 1 => SP reduced, no registers pushed.

The attached ELF can be flashed. Run until "HelloSciopta", single step "svc" => registers pushed and PC at sc_sysSVC.

Do it again, set CONTROL == 1 before step. Single step, PC at sc_sysSVC, but no registers pushed.

Pierre PARIS
ST Employee

Thank you for your ELF file @42Bastian Schick , I flashed it and get this error :


  • Can you please check your linker file ? That might be a memory zone definition overlap...
  • Also what are your OB configuration ? (RDP level? User config? and Write Protection with page size?)

Best Regards,


42Bastian Schick
Associate II

Yes there are memory regions with the same start address, but of size 0. So you can ignore the warning.



I hope above makes sense. CubeProgrammer does not allow to "dump" the OB info nicely 😞


WRP2 same, only 0x081...

I attached a new ELF which I flashed w/o error/warning with CubeProgrammer.