damien_d wrote on Monday, October 15, 2018:
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 StackType_t need to be aligned on 8-bytes?
// This: #define ALIGN_8_BYTES
// or this? #define ALIGN_8_BYTES __attribute__ ((aligned (8)))
#define STACK_DEPTH_FLASH_LED 256
static TaskHandle_t xTaskHandle_FlashLED;
static StaticTask_t ALIGN_8_BYTES m_xTaskBuffer_FlashLED;
static StackType_t ALIGN_8_BYTES m_xStack_FlashLED[STACK_DEPTH_FLASH_LED];
#define NO_THREAD_PARAMETERS NULL
xTaskHandle_FlashLED = xTaskCreateStatic(
vTask_FlashLED,
"flash_led",
STACK_DEPTH_FLASH_LED,
NO_THREAD_PARAMETERS,
TASK_PRIORITY_FLASH_LED,
m_xStack_FlashLED,
&m_xTaskBuffer_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 uint32_t, then GCC will allocate this to a 4-byte boundary, not an 8-byte boundary, e.g.
.bss.m_xTaskBuffer_FlashLED
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_xTaskBuffer_FlashLED
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 DEBUG_UART_QUEUE_SIZE 32
#define DEBUG_UART_QUEUE_ITEM_SIZE sizeof(SUARTDatagram)
static QueueHandle_t m_queue_DebugUART;
static ALIGN_8_BYTES uint8_t m_queue_DebugUART_storageArea[
DEBUG_UART_QUEUE_SIZE * DEBUG_UART_QUEUE_ITEM_SIZE];
static ALIGN_8_BYTES StaticQueue_t m_queue_DebugUART_StaticQueue;
m_queue_DebugUART = xQueueCreateStatic(
DEBUG_UART_QUEUE_SIZE,
DEBUG_UART_QUEUE_ITEM_SIZE,
m_queue_DebugUART_storageArea,
&m_queue_DebugUART_StaticQueue);
Kind regards,
Damien.