Update the GCC Cortex-A9 port to introduce a version of the IRQ handler that saves the FPU registers.

pull/4/head
Richard Barry 9 years ago
parent ac67c39be9
commit 345819d550

@ -147,7 +147,14 @@ void vClearTickInterrupt( void )
}
/*-----------------------------------------------------------*/
void vApplicationIRQHandler( uint32_t ulICCIAR )
/* This is the callback function which is called by the FreeRTOS Cortex-A port
layer in response to an interrupt. If the function is called
vApplicationFPUSafeIRQHandler() then it is called after the floating point
registers have been saved. If the function is called vApplicationIRQHandler()
then it will be called without first having saved the FPU registers. See
http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html for
more information */
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )
{
extern const XScuGic_Config XScuGic_ConfigTable[];
static const XScuGic_VectorTableEntry *pxVectorTable = XScuGic_ConfigTable[ XPAR_SCUGIC_SINGLE_DEVICE_ID ].HandlerTable;
@ -155,7 +162,7 @@ uint32_t ulInterruptID;
const XScuGic_VectorTableEntry *pxVectorEntry;
/* Re-enable interrupts. */
__asm ( "cpsie i" );
__asm ( "cpsie i" );
/* The ID of the interrupt is obtained by bitwise anding the ICCIAR value
with 0x3FF. */

@ -202,6 +202,27 @@ extern void vPortRestoreTaskContext( void );
*/
static void prvTaskExitError( void );
/*
* If the application provides an implementation of vApplicationIRQHandler(),
* then it will get called directly without saving the FPU registers on
* interrupt entry, and this weak implementation of
* vApplicationFPUSafeIRQHandler() is just provided to remove linkage errors -
* it should never actually get called so its implementation contains a
* call to configASSERT() that will always fail.
*
* If the application provides its own implementation of
* vApplicationFPUSafeIRQHandler() then the implementation of
* vApplicationIRQHandler() provided in portASM.S will save the FPU registers
* before calling it.
*
* Therefore, if the application writer wants FPU registers to be saved on
* interrupt entry their IRQ handler must be called
* vApplicationFPUSafeIRQHandler(), and if the application writer does not want
* FPU registers to be saved on interrupt entry their IRQ handler must be
* called vApplicationIRQHandler().
*/
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__((weak) );
/*-----------------------------------------------------------*/
/* A variable is used to keep track of the critical section nesting. This
@ -387,7 +408,7 @@ uint32_t ulAPSR;
}
}
/* Will only get here if xTaskStartScheduler() was called with the CPU in
/* Will only get here if vTaskStartScheduler() was called with the CPU in
a non-privileged mode or the binary point register was not set to its lowest
possible value. prvTaskExitError() is referenced to prevent a compiler
warning about it being defined but not referenced in the case that the user
@ -555,3 +576,7 @@ uint32_t ulReturn;
#endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )
{
configASSERT( ( volatile void * ) NULL );
}

@ -289,6 +289,46 @@ switch_before_exit:
next. */
portRESTORE_CONTEXT
/******************************************************************************
* If the application provides an implementation of vApplicationIRQHandler(),
* then it will get called directly without saving the FPU registers on
* interrupt entry, and this weak implementation of
* vApplicationIRQHandler() will not get called.
*
* If the application provides its own implementation of
* vApplicationFPUSafeIRQHandler() then this implementation of
* vApplicationIRQHandler() will be called, save the FPU registers, and then
* call vApplicationFPUSafeIRQHandler().
*
* Therefore, if the application writer wants FPU registers to be saved on
* interrupt entry their IRQ handler must be called
* vApplicationFPUSafeIRQHandler(), and if the application writer does not want
* FPU registers to be saved on interrupt entry their IRQ handler must be
* called vApplicationIRQHandler().
*****************************************************************************/
.align 4
.weak vApplicationIRQHandler
.type vApplicationIRQHandler, %function
vApplicationIRQHandler:
PUSH {LR}
FMRX R1, FPSCR
VPUSH {D0-D15}
VPUSH {D16-D31}
PUSH {R1}
LDR r1, vApplicationFPUSafeIRQHandlerConst
BLX r1
POP {R0}
VPOP {D16-D31}
VPOP {D0-D15}
VMSR FPSCR, R0
POP {PC}
ulICCIARConst: .word ulICCIAR
ulICCEOIRConst: .word ulICCEOIR
ulICCPMRConst: .word ulICCPMR
@ -299,6 +339,7 @@ ulMaxAPIPriorityMaskConst: .word ulMaxAPIPriorityMask
vTaskSwitchContextConst: .word vTaskSwitchContext
vApplicationIRQHandlerConst: .word vApplicationIRQHandler
ulPortInterruptNestingConst: .word ulPortInterruptNesting
vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
.end

@ -178,7 +178,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
/*
* Function to enable the VFP.
*/
static void vPortEnableVFP( void ) __attribute__ (( naked ));
static void vPortEnableVFP( void ) __attribute__ (( naked ));
/*
* Used to catch tasks that attempt to return from their implementing function.

@ -353,7 +353,7 @@ uint32_t ulAPSR;
}
}
/* Will only get here if xTaskStartScheduler() was called with the CPU in
/* Will only get here if vTaskStartScheduler() was called with the CPU in
a non-privileged mode or the binary point register was not set to its lowest
possible value. */
return 0;

Loading…
Cancel
Save