Dear All,
I am looking to clarify if alignment is required when using statically allocated tasks and, by extension, statically allocated stacks for Idle and Timers.
I am currently using
GCC with an
NXP S32K144 EVK (ARM Cortex M4F).
For example, I am currently allocating my tasks using the following pattern, following the examplies in the
documentation:
~~~
// Does either StaticTask
t or StackTypet need to be aligned on 8-bytes?
// This: #define ALIGN
8BYTES
// or this? #define ALIGN
8BYTES
attribute ((aligned (8)))
define STACKDEPTHFLASH_LED 256
static TaskHandle
t xTaskHandleFlashLED;
static StaticTask
t ALIGN8
BYTES mxTaskBuffer
FlashLED;
static StackTypet ALIGN
8BYTES m
xStackFlashLED[STACK
DEPTHFLASH_LED];
define NOTHREADPARAMETERS NULL
xTaskHandle
FlashLED = xTaskCreateStatic(
vTaskFlashLED,
“flash
led”,
STACKDEPTH
FLASHLED,
NO
THREADPARAMETERS,
TASK
PRIORITYFLASH
LED,
mxStack
FlashLED,
&mxTaskBuffer_FlashLED);
~~~
When looking at tasks.c for the dynamic case, the allocated memory will be aligned to (in the case of the CM4F) 8-byte boundaries, as guarunteed by pvPortAlloc:
~~~
{
StackType_t *pxStack;
/* Allocate space for the stack used by the task being created. */
pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
if( pxStack != NULL )
{
/* Allocate space for the TCB. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
if( pxNewTCB != NULL )
{
/* Store the stack location in the TCB. */
pxNewTCB->pxStack = pxStack;
}
else
{
/* The stack cannot be used as the TCB was not created. Free
it again. */
vPortFree( pxStack );
}
}
else
{
pxNewTCB = NULL;
}
}
~~~
As I understand it, The CM4F requires that the stack is 8-byte aligned. However, since StackType
t is a uint32t, then GCC will allocate this to a 4-byte boundary, not an 8-byte boundary, e.g.
~~~
.bss.m
xTaskBufferFlashLED
0x000000002000435c 0x4c /tmp/ccRQFTy2.ltrans0.ltrans.o
~~~
So, should the statically allocated stack also be 8-byte aligned using gcc’s
attribute ((aligned (8))) to ensure alignment? What is the likely consequence if this is not the case. Certainly, this does indeed force aligment:
~~~
fill 0x00000000200043c4 0x4
.bss.m
xTaskBufferFlashLED
0x00000000200043c8 0x4c /tmp/ccPCqzB6.ltrans0.ltrans.o
~~~
And, would this be consequential for other statically alloctaed buffer, especially queues since the storage area is declared as a uint8_t:
For example:
~~~
define DEBUGUARTQUEUE_SIZE 32
define DEBUGUARTQUEUEITEMSIZE sizeof(SUARTDatagram)
static QueueHandle
t mqueue_DebugUART;
static ALIGN
8BYTES uint8
t mqueue
DebugUARTstorageArea[
DEBUG
UARTQUEUE
SIZE * DEBUGUART
QUEUEITEM_SIZE];
static ALIGN
8BYTES StaticQueue
t mqueue
DebugUARTStaticQueue;
m
queueDebugUART = xQueueCreateStatic(
DEBUG
UARTQUEUE
SIZE,
DEBUGUART
QUEUEITEM
SIZE,
mqueue
DebugUARTstorageArea,
&m
queueDebugUART_StaticQueue);
~~~
Kind regards,
Damien.