Skip to content

Commit 55eceb2

Browse files
authored
Add configUSE_TASK_FPU_SUPPORT to AARCH64 port (FreeRTOS#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.
1 parent 067d04e commit 55eceb2

File tree

2 files changed

+64
-23
lines changed

2 files changed

+64
-23
lines changed

portable/GCC/ARM_AARCH64/port.c

+52-20
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@
133133
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
134134
#define portBIT_0_SET ( ( uint8_t ) 0x01 )
135135

136+
/* The space on the stack required to hold the FPU registers.
137+
* There are 32 128-bit registers.*/
138+
#define portFPU_REGISTER_WORDS ( 32 * 2 )
139+
136140
/*-----------------------------------------------------------*/
137141

138142
/*
@@ -244,23 +248,47 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
244248
*pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */
245249
pxTopOfStack--;
246250
*pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */
247-
pxTopOfStack--;
248-
249-
*pxTopOfStack = portINITIAL_PSTATE;
250-
pxTopOfStack--;
251251

252-
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
253252
pxTopOfStack--;
253+
*pxTopOfStack = portINITIAL_PSTATE;
254254

255-
/* The task will start with a critical nesting count of 0 as interrupts are
256-
* enabled. */
257-
*pxTopOfStack = portNO_CRITICAL_NESTING;
258255
pxTopOfStack--;
256+
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
259257

260-
/* The task will start without a floating point context. A task that uses
261-
* the floating point hardware must call vPortTaskUsesFPU() before executing
262-
* any floating point instructions. */
263-
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
258+
#if ( configUSE_TASK_FPU_SUPPORT == 1 )
259+
{
260+
/* The task will start with a critical nesting count of 0 as interrupts are
261+
* enabled. */
262+
pxTopOfStack--;
263+
*pxTopOfStack = portNO_CRITICAL_NESTING;
264+
265+
/* The task will start without a floating point context. A task that
266+
* uses the floating point hardware must call vPortTaskUsesFPU() before
267+
* executing any floating point instructions. */
268+
pxTopOfStack--;
269+
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
270+
}
271+
#elif ( configUSE_TASK_FPU_SUPPORT == 2 )
272+
{
273+
/* The task will start with a floating point context. Leave enough
274+
* space for the registers - and ensure they are initialised to 0. */
275+
pxTopOfStack -= portFPU_REGISTER_WORDS;
276+
memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );
277+
278+
/* The task will start with a critical nesting count of 0 as interrupts are
279+
* enabled. */
280+
pxTopOfStack--;
281+
*pxTopOfStack = portNO_CRITICAL_NESTING;
282+
283+
pxTopOfStack--;
284+
*pxTopOfStack = pdTRUE;
285+
ullPortTaskHasFPUContext = pdTRUE;
286+
}
287+
#else /* if ( configUSE_TASK_FPU_SUPPORT == 1 ) */
288+
{
289+
#error "Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined."
290+
}
291+
#endif /* if ( configUSE_TASK_FPU_SUPPORT == 1 ) */
264292

265293
return pxTopOfStack;
266294
}
@@ -440,15 +468,19 @@ void FreeRTOS_Tick_Handler( void )
440468
}
441469
/*-----------------------------------------------------------*/
442470

443-
void vPortTaskUsesFPU( void )
444-
{
445-
/* A task is registering the fact that it needs an FPU context. Set the
446-
* FPU flag (which is saved as part of the task context). */
447-
ullPortTaskHasFPUContext = pdTRUE;
471+
#if ( configUSE_TASK_FPU_SUPPORT != 2 )
448472

449-
/* Consider initialising the FPSR here - but probably not necessary in
450-
* AArch64. */
451-
}
473+
void vPortTaskUsesFPU( void )
474+
{
475+
/* A task is registering the fact that it needs an FPU context. Set the
476+
* FPU flag (which is saved as part of the task context). */
477+
ullPortTaskHasFPUContext = pdTRUE;
478+
479+
/* Consider initialising the FPSR here - but probably not necessary in
480+
* AArch64. */
481+
}
482+
483+
#endif /* configUSE_TASK_FPU_SUPPORT */
452484
/*-----------------------------------------------------------*/
453485

454486
void vPortClearInterruptMask( UBaseType_t uxNewMaskValue )

portable/GCC/ARM_AARCH64/portmacro.h

+12-3
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,18 @@ extern void vPortInstallFreeRTOSVectorTable( void );
135135
* handler for whichever peripheral is used to generate the RTOS tick. */
136136
void FreeRTOS_Tick_Handler( void );
137137

138-
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
139-
* before any floating point instructions are executed. */
140-
void vPortTaskUsesFPU( void );
138+
/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or left undefined) then tasks are
139+
* created without an FPU context and must call vPortTaskUsesFPU() to give
140+
* themselves an FPU context before using any FPU instructions. If
141+
* configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context
142+
* by default. */
143+
#if ( configUSE_TASK_FPU_SUPPORT != 2 )
144+
void vPortTaskUsesFPU( void );
145+
#else
146+
/* Each task has an FPU context already, so define this function away to
147+
* nothing to prevent it from being called accidentally. */
148+
#define vPortTaskUsesFPU()
149+
#endif
141150
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
142151

143152
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )

0 commit comments

Comments
 (0)