mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2026-07-10 13:29:45 -04:00
Fix SH2A_FPU FPU context cleanup
Keep the per-task FPU context allocation reachable, avoid replacing an existing task tag buffer, and free the allocation from portCLEAN_UP_TCB using the saved buffer end pointer. Signed-off-by: Old-Ding <ai.neo.ae86@gmail.com>
This commit is contained in:
parent
d72263b404
commit
389e7bce8e
2 changed files with 46 additions and 22 deletions
|
|
@ -43,13 +43,6 @@
|
|||
* value is for all interrupts to be enabled. */
|
||||
#define portINITIAL_SR ( 0UL )
|
||||
|
||||
/* Dimensions the array into which the floating point context is saved.
|
||||
* Allocate enough space for FPR0 to FPR15, FPUL and FPSCR, each of which is 4
|
||||
* bytes big. If this number is changed then the 72 in portasm.src also needs
|
||||
* changing. */
|
||||
#define portFLOP_REGISTERS_TO_STORE ( 18 )
|
||||
#define portFLOP_STORAGE_SIZE ( portFLOP_REGISTERS_TO_STORE * 4 )
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
|
||||
#error configSUPPORT_DYNAMIC_ALLOCATION must be 1 to use this port.
|
||||
#endif
|
||||
|
|
@ -245,26 +238,35 @@ BaseType_t xPortUsesFloatingPoint( TaskHandle_t xTask )
|
|||
xTask = ( TaskHandle_t ) pxCurrentTCB;
|
||||
}
|
||||
|
||||
/* Allocate a buffer large enough to hold all the flop registers. */
|
||||
pulFlopBuffer = ( uint32_t * ) pvPortMalloc( portFLOP_STORAGE_SIZE );
|
||||
|
||||
if( pulFlopBuffer != NULL )
|
||||
/* The task tag already owns the FPU buffer for this port. Do not replace
|
||||
* it, or the original allocation would become unreachable. */
|
||||
if( xTaskGetApplicationTaskTag( xTask ) != NULL )
|
||||
{
|
||||
/* Start with the registers in a benign state. */
|
||||
memset( ( void * ) pulFlopBuffer, 0x00, portFLOP_STORAGE_SIZE );
|
||||
|
||||
/* The first thing to get saved in the buffer is the FPSCR value -
|
||||
* initialise this to the current FPSCR value. */
|
||||
*pulFlopBuffer = get_fpscr();
|
||||
|
||||
/* Use the task tag to point to the flop buffer. Pass pointer to just
|
||||
* above the buffer because the flop save routine uses a pre-decrement. */
|
||||
vTaskSetApplicationTaskTag( xTask, ( void * ) ( pulFlopBuffer + portFLOP_REGISTERS_TO_STORE ) );
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFAIL;
|
||||
/* Allocate a buffer large enough to hold all the flop registers. */
|
||||
pulFlopBuffer = ( uint32_t * ) pvPortMalloc( portFLOP_STORAGE_SIZE );
|
||||
|
||||
if( pulFlopBuffer != NULL )
|
||||
{
|
||||
/* Start with the registers in a benign state. */
|
||||
memset( ( void * ) pulFlopBuffer, 0x00, portFLOP_STORAGE_SIZE );
|
||||
|
||||
/* The first thing to get saved in the buffer is the FPSCR value -
|
||||
* initialise this to the current FPSCR value. */
|
||||
*pulFlopBuffer = get_fpscr();
|
||||
|
||||
/* Use the task tag to point to the flop buffer. Pass pointer to just
|
||||
* above the buffer because the flop save routine uses a pre-decrement. */
|
||||
vTaskSetApplicationTaskTag( xTask, ( void * ) ( pulFlopBuffer + portFLOP_REGISTERS_TO_STORE ) );
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
|
|
|
|||
|
|
@ -84,6 +84,13 @@ typedef unsigned long UBaseType_t;
|
|||
#define portYIELD_TRAP_NO ( 33 )
|
||||
#define portKERNEL_INTERRUPT_PRIORITY ( 1 )
|
||||
|
||||
/* Dimensions the array into which the floating point context is saved.
|
||||
* Allocate enough space for FPR0 to FPR15, FPUL and FPSCR, each of which is 4
|
||||
* bytes big. If this number is changed then the 72 in portasm.src also needs
|
||||
* changing. */
|
||||
#define portFLOP_REGISTERS_TO_STORE ( 18 )
|
||||
#define portFLOP_STORAGE_SIZE ( portFLOP_REGISTERS_TO_STORE * 4 )
|
||||
|
||||
void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
|
||||
|
|
@ -112,6 +119,21 @@ void vPortRestoreFlopRegisters( void * pulBuffer );
|
|||
#define traceTASK_SWITCHED_OUT() do { if( pxCurrentTCB->pxTaskTag != NULL ) vPortSaveFlopRegisters( pxCurrentTCB->pxTaskTag ); } while( 0 )
|
||||
#define traceTASK_SWITCHED_IN() do { if( pxCurrentTCB->pxTaskTag != NULL ) vPortRestoreFlopRegisters( pxCurrentTCB->pxTaskTag ); } while( 0 )
|
||||
|
||||
/* pxTaskTag points just above the FPU context buffer because the save routine
|
||||
* uses a pre-decrement. Recover the allocation base before freeing it. */
|
||||
#define portCLEAN_UP_TCB( pxTCB ) \
|
||||
do \
|
||||
{ \
|
||||
if( ( pxTCB )->pxTaskTag != NULL ) \
|
||||
{ \
|
||||
uint32_t * pulFlopBufferEnd = \
|
||||
( uint32_t * ) ( pxTCB )->pxTaskTag; \
|
||||
vPortFree( ( void * ) ( pulFlopBufferEnd - \
|
||||
portFLOP_REGISTERS_TO_STORE ) ); \
|
||||
( pxTCB )->pxTaskTag = NULL; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
/*
|
||||
* These macros should be called directly, but through the taskENTER_CRITICAL()
|
||||
* and taskEXIT_CRITICAL() macros.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue