CM33 hard fault while trying to yield from secure

While debugging a bad driver on the secure side (which ended up stuck in an endless loop), I realized that FreeRTOS crashes to a secure hard fault while trying to make the corresponding task yield. Of course I am calling portALLOCATE_SECURE_CONTEXT at the start of the calling task. I guess there is some ISR setting I still need to correct.
Any pointers on which one that might be?

(MCU is an STM32L5)

I presume you are running FreeRTOS with trustzone support, as per this link, Using FreeRTOS on ARMv8-M Microcontrollers - FreeRTOS - so running FreeRTOS on the non-secure side but making calls into the secure side - is that right? Which version of FreeRTOS are you using (the comments at the top of the source files will say) - asking as there have been changes in the most recent code to statically allocate a fixed number of secure contexts.

If I understand then you have a FreeRTOS task calling a secure side function that accesses a driver. How is the task yielding before the crash - is it trying to enter the Blocked state because it called an API function with a timeout, or something else?

Yes, I am using FreeRTOS with trustzone support, running on the non-secure side but calling a secure function.
In my case that function was a secure driver (accessing the TRNG hardware) which stayed in a loop because of a different error. But after an additional tests, it looks like anything which goes into a long/endless loop on the secure side had the same effect: After some time RTOS tries to switch to another task and on that generated a secure hard fault.

The files say FreeRTOS Kernel V10.4.6 which is what is marketed as the latest 202112.00 on the download page.

That should not happen. Have you tried to analyze the hard fault and find out the offending line? Is it possible that you need more secure stack size - What is the value that you pass to portALLOCATE_SECURE_CONTEXT?

You should also consider enabling Memory Management Fault, Bus Fault, and Usage Fault exceptions. If you are using CMSIS, this document provides a way to enable these:


1 Like

I started with 32 words which should be more than enough for a secure side function with one internal 32Bit variabel, but also multiplying that by 4 does not make a difference.

I have not yet found a good way to look back since the stack traces directly back to “signal handler called”
I know that I have seen similar things in the past when SVC was executed with interrupts disabled (as seen in my last thread) but I did not touch those.

EDIT: Looks like my timer tick (I use lptim for ticks) is the culprit, now I “just” need to find out why. I can see that it was promoted by HFSR.FORCED being set but I have no clue why since from my understanding secure context alone should not change priorities.

Have you increased the size of the secure side stack. If there is a context switch it needs to hold the task’s context so 80 words is likely to be a minimum - but start with 200 to test if it helps.

From my current state of debugging it looks like the RTOS context switch is not even starting because the µC context-switch to handle the tick interrupt is already what is failing. UFSR=0x10 indicate a µC stack overflow. Though I have no idea why that should happen since there is around 50kB empty memory left for that.
I guess I’ll find out eventually :grimacing:
Do I read this correctly in stating that the secure psp reached its limit? Is that one handled by FreeRTOS?

Second EDIT: I found it :slightly_smiling_face:: configMINIMAL_SECURE_STACK_SIZE is also used inside the task.c itself and my setting of 32 taken because I don’t remember why was too low for that one already. Taking 1024 (is this in bytes or words?) from the CORTEX_MPU_M33F_Simulator_Keil_GCC demo repairs everything.

Thank you for taking time to report back.

Ok, I looked it up myself, it is in Bytes instead of words used in the standard task stack.
For reference: xTaskCreate does
pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) )
wheres SecureContext_AllocateContext does
pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );