Massive stack overflow on task when kernel starts. Any ideas?

In one of the pictures you shared, I saw that secure registers are being used which indicates that your core is running secure. Please ensure to set it to 1.

@jefftenney already linked it, here it is again - FreeRTOS-Kernel/portable/ARMv8M/non_secure/portable/GCC/ARM_CM33_NTZ/portasm.c at V11.1.0 · FreeRTOS/FreeRTOS-Kernel · GitHub.

1 Like

Okay that makes sense, I placed a breakpoint at vRestoreContextOfFirstTask() and SVC_Handler(). SVC_Handler and then vRestoreContextOfFirstTask() were reached okay, upon reaching the breakpoint, I stepped into vRestoreContextOfFirstTask() and then the hardfault occurred, I stepped through the asm line by line and it seems to make through the entire code, and occurs right when branching to EXC_RETURN

Just for reference, this is the source code I am using: https://github.com/ARM-software/CMSIS-FreeRTOS/blob/main/Source/portable/ARMv8M/non_secure/port.c
and for the portable I am using GCC->NTZ

This is a good find. Lines up with the other evidence (LR = 0xFFFFFFBD) indicating thread mode, PSP, non-secure at the time of the hard fault.

@aggarg’s suggestion is worth trying again – set configRUN_FREERTOS_SECURE_ONLY to 1. It changes the value of that first EXC_RETURN exactly where your hard fault is happening.

1 Like

Yes that did help, I was able to reach the breakpoint in my test task! The Tick Count still shows as 0 in the FreeRTOS view window but the massive stack overflow for the running task is gone! I am just going to assume that information about the tick count is incorrect?

Glad you got it working. Apparently your M33 enables trustzone by default.

That could be a problem. If you let the test task run for a while, and then break in the debugger, the tick count should not be zero anymore. If it is still zero, you’ll need to get the system tick working.

Thank you for all the help and thank you too @aggarg as well, really appreciate you both taking the time to assist. I was able to get the tick count showing properly.

Now what I am unsure of is why the entire memory space would have TrustZone enabled. Reading this from port.c

The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only
i.e. the processor boots as secure and never jumps to the non-secure side.
The Trust Zone support in the port must be disabled in order to run FreeRTOS
on the secure side.

Since I only enabled configRUN_FREERTOS_SECURE_ONLY but not configENABLE_TRUSTZONE

I am executing in a “non-secure” ram address space right now since I’m at the beginning stage of development. My understanding was that if I am accessing a “secure ram” (ie loading code or allocating stack and heap space there) then I would need to enable secure side.

Currently my very minimal bootloader just moves to 0x20000000 (NS RAM) and then executes code from flash. My thought was, maybe since the vector table is at 0x00000000 then I need to enable secure zone to access there, but my bootloader and vector table exists in NS ROM space. 0x00000000 - 0x0000FFFF.

Is my understanding correct?

As as a test, I changed my scatter file to load ROM and RAM in the secure RAM memory region and loaded my vector table to the new spot. With configRUN_FREERTOS_SECURE_ONLY enabled, I could not load my code to main. Trying to confirm some details with who built the FPGA drop.

You should use these files - FreeRTOS-Kernel/portable/GCC/ARM_CM33_NTZ/non_secure at main · FreeRTOS/FreeRTOS-Kernel · GitHub.

I think your controller does not disable TZ and still boots as secure. As a result, your entire application runs on the secure side.

This is a good resource - Using FreeRTOS on ARMv8-M Microcontrollers - FreeRTOS.

We want to use CMSIS and it’s drivers so that is why I am using the CMSIS specific FreeRTOS code. The link you sent does not seem to be part of the CMSIS v2 FreeRTOS.

Ah I see, but if TrustZone was enabled, wouldn’t that mean I am running on the non-secure side and then using TrustZone to access the secure side?

Where did you get this code from?

If the TZ is enabled, the following sequence happens:

  1. The MCU boots as secure.
  2. The secure application configures the resources accessible from the non-secure side.
  3. The secure application jumps to the non-secure application.
  4. From this point onwards, the non-secure application can only access the functions exported by the secure application using the valid entry points.

It is different than the CMSIS implementation of FreeRTOS located here https://github.com/ARM-software/CMSIS_6

One question, I am running into a hardfault now when I try to initialize my UART driver, for some reason when I step into the xTimerCreate method, it occurs. I have increase the heap size in the scatter file to 0x1000 and configTOTAL_HEAP_SIZE by a lot to 32768 but this did not help. As soon as I step into this method, xTimerCreate method which is triggered by the CMSIS UART Driver (see example) I receive a JLink -Cortex M Error “Could not stop Cortex-M device! Please check JTAG cable.”

I know the UART peripherals are defined and I have manually tested the UART (via interacting with control and FIFO registers) and it is working properly and defined in the proper address locations for Arm M33. Could this be due to running in secure side and interacting with a peripheral defined in a different memory region (0x88880000 - 0x8888FFFF)

Below is the xTimerCreate method I am referring too:

#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )

        TimerHandle_t xTimerCreate( const char * const pcTimerName,
                                    const TickType_t xTimerPeriodInTicks,
                                    const BaseType_t xAutoReload,
                                    void * const pvTimerID,
                                    TimerCallbackFunction_t pxCallbackFunction )
        {
            Timer_t * pxNewTimer;

            traceENTER_xTimerCreate( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction );

            /* MISRA Ref 11.5.1 [Malloc memory assignment] */
            /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
            /* coverity[misra_c_2012_rule_11_5_violation] */
            pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );

            if( pxNewTimer != NULL )
            {
                /* Status is thus far zero as the timer is not created statically
                 * and has not been started.  The auto-reload bit may get set in
                 * prvInitialiseNewTimer. */
                pxNewTimer->ucStatus = 0x00;
                prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
            }

            traceRETURN_xTimerCreate( pxNewTimer );

            return pxNewTimer;
        }

I tried using the vApplicationMallocFailedHook(); to catch if the heap allocation was causing the problem, but no luck.

It is unlikely because your code is running as secure and secure software usually has access to all the peripherals. Can you use the information in this doc to find out which fault is happening and the faulting instruction?

And just to confirm, if you remove UART initialization, does the application work? You can have just couple of tasks using some FreeRTOS primitives to ensure that it works.