Add flop support.

This commit is contained in:
Richard Barry 2010-01-17 13:12:54 +00:00
parent 65b947b50f
commit 094945625d
3 changed files with 137 additions and 22 deletions

View file

@ -59,8 +59,16 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.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(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
trapa( 32 ); trapa( portSTART_SCHEDULER_TRAP_NO );
/* Should not get here. */ /* Should not get here. */
return pdFAIL; 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;
}
/*-----------------------------------------------------------*/

View file

@ -57,9 +57,11 @@
.export _vPortStartFirstTask .export _vPortStartFirstTask
.export _ulPortGetGBR .export _ulPortGetGBR
.export _vPortYield .export _vPortYieldHandler
.export _vPortPreemptiveTick .export _vPortPreemptiveTick
.export _vPortCooperativeTick .export _vPortCooperativeTick
.export _vPortSaveFlopRegisters
.export _vPortRestoreFlopRegisters
.section P .section P
@ -118,19 +120,7 @@ _vPortStartFirstTask:
;----------------------------------------------------------- ;-----------------------------------------------------------
_vPortYield: _vPortYieldHandler:
; 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
portSAVE_CONTEXT portSAVE_CONTEXT
@ -176,5 +166,58 @@ _ulPortGetGBR:
rts rts
nop 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 .end

View file

@ -90,15 +90,27 @@ extern "C" {
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 4 #define portBYTE_ALIGNMENT 4
#define portSTACK_GROWTH -1 #define portSTACK_GROWTH -1
#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) #define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ )
#define portYIELD() trapa( 33 ) #define portNOP() nop()
#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 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. */ /* Critical section handling. */
#define portCRITICAL_NESTING_IN_TCB ( 1 ) #define portCRITICAL_NESTING_IN_TCB ( 1 )