From fe68ff121910bf15097abae2360a9d6baffabc3e Mon Sep 17 00:00:00 2001 From: aineoae86-sys Date: Sat, 4 Jul 2026 15:45:37 +0800 Subject: [PATCH] Fix SH2A_FPU FPU context cleanup --- portable/Renesas/SH2A_FPU/port.c | 46 ++++++++++++++------------- portable/Renesas/SH2A_FPU/portmacro.h | 22 +++++++++++++ 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/portable/Renesas/SH2A_FPU/port.c b/portable/Renesas/SH2A_FPU/port.c index c14a0a851c3..1c66691ecee 100644 --- a/portable/Renesas/SH2A_FPU/port.c +++ b/portable/Renesas/SH2A_FPU/port.c @@ -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; diff --git a/portable/Renesas/SH2A_FPU/portmacro.h b/portable/Renesas/SH2A_FPU/portmacro.h index 2229fd3f66b..b9d751b4b70 100644 --- a/portable/Renesas/SH2A_FPU/portmacro.h +++ b/portable/Renesas/SH2A_FPU/portmacro.h @@ -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.