From 21f15ec1680b120dcb8b0d64f6775fa29dc178aa Mon Sep 17 00:00:00 2001 From: richardbarry Date: Sun, 17 Jan 2010 13:12:54 +0000 Subject: [PATCH] Add flop support. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@961 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Source/portable/Renesas/SH2A_FPU/port.c | 64 +++++++++++++++++- Source/portable/Renesas/SH2A_FPU/portasm.src | 71 ++++++++++++++++---- Source/portable/Renesas/SH2A_FPU/portmacro.h | 24 +++++-- 3 files changed, 137 insertions(+), 22 deletions(-) diff --git a/Source/portable/Renesas/SH2A_FPU/port.c b/Source/portable/Renesas/SH2A_FPU/port.c index b6832f9c2..c52485c81 100644 --- a/Source/portable/Renesas/SH2A_FPU/port.c +++ b/Source/portable/Renesas/SH2A_FPU/port.c @@ -59,8 +59,16 @@ #include "FreeRTOS.h" #include "task.h" -#define portINITIAL_SR 0UL /* No interrupts masked. */ +/* Library includes. */ +#include "string.h" +#define portINITIAL_SR 0UL /* No interrupts masked. */ + +/* 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 ) /*-----------------------------------------------------------*/ @@ -196,7 +204,7 @@ portBASE_TYPE xPortStartScheduler( void ) prvSetupTimerInterrupt(); /* Start the first task. */ - trapa( 32 ); + trapa( portSTART_SCHEDULER_TRAP_NO ); /* Should not get here. */ return pdFAIL; @@ -229,6 +237,58 @@ extern void vApplicationSetupTimerInterrupt( void ); } /*-----------------------------------------------------------*/ +void vPortYield( void ) +{ +long lInterruptMask; + + lInterruptMask = get_imask(); + + /* taskYIELD() can only be called from a task, not an interrupt, so the + current interrupt mask can only be 0 or portKERNEL_INTERRUPT_PRIORITY and + the mask can be set without risk of accidentally lowering the mask value. */ + set_imask( portKERNEL_INTERRUPT_PRIORITY ); + + trapa( portYIELD_TRAP_NO ); + + set_imask( ( int ) lInterruptMask ); +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xPortUsesFloatingPoint( xTaskHandle xTask ) +{ +unsigned long *pulFlopBuffer; +portBASE_TYPE xReturn; +extern void * volatile pxCurrentTCB; + + if( xTask == NULL ) + { + xTask = pxCurrentTCB; + } + + /* Allocate a buffer large enough to hold all the flop registers. */ + pulFlopBuffer = ( unsigned long * ) pvPortMalloc( portFLOP_STORAGE_SIZE ); + + if( pulFlopBuffer != NULL ) + { + memset( ( void * ) pulFlopBuffer, 0x00, portFLOP_STORAGE_SIZE ); + + *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/Source/portable/Renesas/SH2A_FPU/portasm.src b/Source/portable/Renesas/SH2A_FPU/portasm.src index 1d832a90d..948b57dd7 100644 --- a/Source/portable/Renesas/SH2A_FPU/portasm.src +++ b/Source/portable/Renesas/SH2A_FPU/portasm.src @@ -57,9 +57,11 @@ .export _vPortStartFirstTask .export _ulPortGetGBR - .export _vPortYield + .export _vPortYieldHandler .export _vPortPreemptiveTick .export _vPortCooperativeTick + .export _vPortSaveFlopRegisters + .export _vPortRestoreFlopRegisters .section P @@ -118,19 +120,7 @@ _vPortStartFirstTask: ;----------------------------------------------------------- -_vPortYield: - - ; Push r0 so it can be used. - mov.l r0, @-r15 - - ; Set the interrupt mask in the status register. - stc sr, r0 - or #H'70, r0 - ldc r0, sr - - ; Restore r0 so its original value can be saved by the movml.l instruction - ; below, without ending up with two copies on the stack. - mov.l @r15+, r0 +_vPortYieldHandler: portSAVE_CONTEXT @@ -176,5 +166,58 @@ _ulPortGetGBR: rts nop +;----------------------------------------------------------- + +_vPortSaveFlopRegisters: + + fmov.s fr0, @-r4 + fmov.s fr1, @-r4 + fmov.s fr2, @-r4 + fmov.s fr3, @-r4 + fmov.s fr4, @-r4 + fmov.s fr5, @-r4 + fmov.s fr6, @-r4 + fmov.s fr7, @-r4 + fmov.s fr8, @-r4 + fmov.s fr9, @-r4 + fmov.s fr10, @-r4 + fmov.s fr11, @-r4 + fmov.s fr12, @-r4 + fmov.s fr13, @-r4 + fmov.s fr14, @-r4 + fmov.s fr15, @-r4 + sts.l fpul, @-r4 + sts.l fpscr, @-r4 + + rts + nop + +;----------------------------------------------------------- + +_vPortRestoreFlopRegisters: + + add.l #-72, r4 + lds.l @r4+, fpscr + lds.l @r4+, fpul + fmov.s @r4+, fr15 + fmov.s @r4+, fr14 + fmov.s @r4+, fr13 + fmov.s @r4+, fr12 + fmov.s @r4+, fr11 + fmov.s @r4+, fr10 + fmov.s @r4+, fr9 + fmov.s @r4+, fr8 + fmov.s @r4+, fr7 + fmov.s @r4+, fr6 + fmov.s @r4+, fr5 + fmov.s @r4+, fr4 + fmov.s @r4+, fr3 + fmov.s @r4+, fr2 + fmov.s @r4+, fr1 + fmov.s @r4+, fr0 + + rts + nop + .end diff --git a/Source/portable/Renesas/SH2A_FPU/portmacro.h b/Source/portable/Renesas/SH2A_FPU/portmacro.h index b1c88de7d..ca59d72db 100644 --- a/Source/portable/Renesas/SH2A_FPU/portmacro.h +++ b/Source/portable/Renesas/SH2A_FPU/portmacro.h @@ -90,15 +90,27 @@ extern "C" { /*-----------------------------------------------------------*/ /* Hardware specifics. */ -#define portBYTE_ALIGNMENT 4 -#define portSTACK_GROWTH -1 -#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) -#define portYIELD() trapa( 33 ) -#define portNOP() nop() +#define portBYTE_ALIGNMENT 4 +#define portSTACK_GROWTH -1 +#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) +#define portNOP() nop() +#define portSTART_SCHEDULER_TRAP_NO ( 32 ) +#define portYIELD_TRAP_NO ( 33 ) +#define portKERNEL_INTERRUPT_PRIORITY ( 1 ) + +void vPortYield( void ); +#define portYIELD() vPortYield() + +portBASE_TYPE xPortUsesFloatingPoint( void* xTask ); +void vPortSaveFlopRegisters( void *pulBuffer ); +void vPortRestoreFlopRegisters( void *pulBuffer ); +#define traceTASK_SWITCHED_OUT() if( pxCurrentTCB->pxTaskTag != NULL ) vPortSaveFlopRegisters( pxCurrentTCB->pxTaskTag ) +#define traceTASK_SWITCHED_IN() if( pxCurrentTCB->pxTaskTag != NULL ) vPortRestoreFlopRegisters( pxCurrentTCB->pxTaskTag ) + /*-----------------------------------------------------------*/ #define portENABLE_INTERRUPTS() set_imask( 0x00 ) -#define portDISABLE_INTERRUPTS() set_imask( configMAX_SYSCALL_INTERRUPT_PRIORITY ) +#define portDISABLE_INTERRUPTS() set_imask( portKERNEL_INTERRUPT_PRIORITY ) /* Critical section handling. */ #define portCRITICAL_NESTING_IN_TCB ( 1 ) -- 2.39.5