FreeRTOS wasted stack space

Hi, I’m currently deep-diving into FreeRTOS and I noticed with a kernel-aware debugger, that FreeRTOS “wastes” space on the stack and I see no reason for it. My statically-allocated stack is 8-byte aligned and 512 bytes big.

For example: One stack is [0x24000350, 0x24000550).

FreeRTOS now does this to set the initial stack pointer in prvInitialiseNewTask:

pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );
pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );

This essentially gets the address 0x2400054C in the first line and truncates it to 0x24000548 in the second. This loses 8 bytes at the very bottom of the stack, which never gets written to. And if the stack is aligned to 4 bytes then, it might only loose 4 bytes sometimes (C>8>8 instead of 0>C>8), but I find this really strange.

Is there any explanation for this behaviour?

Hi there SkryptX,

first of all we need to know what your target platform is and which port you use.

Cortex-M4F port with a STM32H743 (Cortex-M7). The portPOINTER_SIZE_TYPE is uint32_t. The portBYTE_ALIGNMENT_MASK is 0x0007, because 8-byte alignment seems to be the correct choice for Cortex-M4/7 if you want to be compatible in every scenario. I did not edit the port, apart from very careful trace macros for Segger SystemView.

Please elaborate. Which scenarios do you refer to here?

This is just what I read online during a cursory search on the ARM forum. I wanted to know, if this value is wrong, but it seems to be plausible to be the correct value. But I’m not an expert in ARM microarchitecture :smiley:. And as mentioned: I did not edit these values. They are taken as provided with the default M4F port and I rather believe, that these ports are more correct than any google search :yum:

Yes, the ARM ABI requires 8 byte stack alignment because a few instructions need it.

1 Like

But back to my original question: Why does FreeRTOS waste 8 bytes of perfectly fine stack while initializing its pxTopOfStack? :sweat_smile:

I think it is because that frame writes to the location that is the multiple of 8, but the computed TOS is the location just past the allocation, so not writeable.

I mean yes. With the assumption that a stack-push decrements topOfStack once and then writes to that decremented address, it does waste 8 bytes. But what if you would just set topOfStack to 0x24000550, which itself is the first byte after the stack, but since on every stack write the pointer gets decremented first, it is no problem and writes inside the valid stack. The only counter-argument to that method I can make out is that a debugger would incorrectly dereference the pointer to another variable, if the stack is completely empty, but I would not mind at all.

Have you checked here:

ARM Initialized stack alignment assert fail - Kernel - FreeRTOS Community Forums

? I think Richard’s response may help answer your question…

Thanks!

I believe that is not true for all the architectures FreeRTOS supports - that is the reason for keeping the SP point to a valid stack memory.

The fact that the rounding code is in the generic code means it has to be a bit more conservative, and possibly wasteful. If the rounding was moved into the port layer, then perhaps it could save the bytes for some cases.

Are there plans to do this or not? Would probably be a lot of work for all the different ports…

I can’t speak for the developers, but as you say, it would require changes to ALL the ports, and would probably need to be a ‘major rev’ release because it would not be backwards compatible to custom ports.

1 Like