Add configUSE_TASK_FPU_SUPPORT to AARCH64 port (#1048)

* 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:
StefanBalt 2024-05-08 13:37:52 +02:00 committed by GitHub
parent 067d04e44e
commit 55eceb2203
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 63 additions and 22 deletions

View file

@ -133,6 +133,10 @@
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#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--;
*pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */
pxTopOfStack--;
pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSTATE;
pxTopOfStack--;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are
* enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--;
#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 = portNO_FLOATING_POINT_CONTEXT;
/* 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
* enabled. */
pxTopOfStack--;
*pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--;
*pxTopOfStack = pdTRUE;
ullPortTaskHasFPUContext = pdTRUE;
}
#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;
}
@ -440,15 +468,19 @@ void FreeRTOS_Tick_Handler( void )
}
/*-----------------------------------------------------------*/
void vPortTaskUsesFPU( void )
{
/* A task is registering the fact that it needs an FPU context. Set the
* FPU flag (which is saved as part of the task context). */
ullPortTaskHasFPUContext = pdTRUE;
#if ( configUSE_TASK_FPU_SUPPORT != 2 )
/* Consider initialising the FPSR here - but probably not necessary in
* AArch64. */
}
void vPortTaskUsesFPU( void )
{
/* A task is registering the fact that it needs an FPU context. Set the
* FPU flag (which is saved as part of the task context). */
ullPortTaskHasFPUContext = pdTRUE;
/* Consider initialising the FPSR here - but probably not necessary in
* AArch64. */
}
#endif /* configUSE_TASK_FPU_SUPPORT */
/*-----------------------------------------------------------*/
void vPortClearInterruptMask( UBaseType_t uxNewMaskValue )