Add configUSE_TASK_FPU_SUPPORT to AARCH64 port

NEON SIMD is required by standard AARCH64 and its registers are
frequently utilized by standard functions such as memcpy().
This means that even simple tasks that do not use any floating point
arithmetics may still alter the contents of the FPU registers.

For this reason it makes sense to add support for
configUSE_TASK_FPU_SUPPORT to be able to enforce FPU register saving and
restoring globally.

The implementation was largely adopted from the ARM_CA9 port. However,
the FPU registers must be placed on the stack before the critical
nesting count to match the AARCH64 portASM.S.
This commit is contained in:
Stefan Baltruweit 2024-05-02 18:09:29 +02:00
parent 30afc1a2c0
commit d57cbc07d0

View file

@ -133,6 +133,10 @@
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portBIT_0_SET ( ( uint8_t ) 0x01 ) #define portBIT_0_SET ( ( uint8_t ) 0x01 )
/* The space on the stack required to hold the FPU registers.
* There are 32 128-bit registers.*/
#define portFPU_REGISTER_WORDS ( 32 * 2 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -244,23 +248,47 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */ *pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */ *pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */
pxTopOfStack--;
pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSTATE; *pxTopOfStack = portINITIAL_PSTATE;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
#if ( configUSE_TASK_FPU_SUPPORT == 1 )
{
/* The task will start with a critical nesting count of 0 as interrupts are
* enabled. */
pxTopOfStack--;
*pxTopOfStack = portNO_CRITICAL_NESTING;
/* The task will start without a floating point context. A task that
* uses the floating point hardware must call vPortTaskUsesFPU() before
* executing any floating point instructions. */
pxTopOfStack--;
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
}
#elif ( configUSE_TASK_FPU_SUPPORT == 2 )
{
/* The task will start with a floating point context. Leave enough
* space for the registers - and ensure they are initialised to 0. */
pxTopOfStack -= portFPU_REGISTER_WORDS;
memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );
/* The task will start with a critical nesting count of 0 as interrupts are /* The task will start with a critical nesting count of 0 as interrupts are
* enabled. */ * enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portNO_CRITICAL_NESTING;
/* The task will start without a floating point context. A task that uses pxTopOfStack--;
* the floating point hardware must call vPortTaskUsesFPU() before executing *pxTopOfStack = pdTRUE;
* any floating point instructions. */ ullPortTaskHasFPUContext = pdTRUE;
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; }
#else /* if ( configUSE_TASK_FPU_SUPPORT == 1 ) */
{
#error "Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined."
}
#endif /* if ( configUSE_TASK_FPU_SUPPORT == 1 ) */
return pxTopOfStack; return pxTopOfStack;
} }