mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-05-03 11:50:59 -04:00
Update the GCC Cortex-A9 port to introduce a version of the IRQ handler that saves the FPU registers.
This commit is contained in:
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[];
|
extern const XScuGic_Config XScuGic_ConfigTable[];
|
||||||
static const XScuGic_VectorTableEntry *pxVectorTable = XScuGic_ConfigTable[ XPAR_SCUGIC_SINGLE_DEVICE_ID ].HandlerTable;
|
static const XScuGic_VectorTableEntry *pxVectorTable = XScuGic_ConfigTable[ XPAR_SCUGIC_SINGLE_DEVICE_ID ].HandlerTable;
|
||||||
|
@ -155,7 +162,7 @@ uint32_t ulInterruptID;
|
||||||
const XScuGic_VectorTableEntry *pxVectorEntry;
|
const XScuGic_VectorTableEntry *pxVectorEntry;
|
||||||
|
|
||||||
/* Re-enable interrupts. */
|
/* Re-enable interrupts. */
|
||||||
__asm ( "cpsie i" );
|
__asm ( "cpsie i" );
|
||||||
|
|
||||||
/* The ID of the interrupt is obtained by bitwise anding the ICCIAR value
|
/* The ID of the interrupt is obtained by bitwise anding the ICCIAR value
|
||||||
with 0x3FF. */
|
with 0x3FF. */
|
||||||
|
|
|
@ -202,6 +202,27 @@ extern void vPortRestoreTaskContext( void );
|
||||||
*/
|
*/
|
||||||
static void prvTaskExitError( 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
|
/* 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
|
a non-privileged mode or the binary point register was not set to its lowest
|
||||||
possible value. prvTaskExitError() is referenced to prevent a compiler
|
possible value. prvTaskExitError() is referenced to prevent a compiler
|
||||||
warning about it being defined but not referenced in the case that the user
|
warning about it being defined but not referenced in the case that the user
|
||||||
|
@ -555,3 +576,7 @@ uint32_t ulReturn;
|
||||||
#endif /* configASSERT_DEFINED */
|
#endif /* configASSERT_DEFINED */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )
|
||||||
|
{
|
||||||
|
configASSERT( ( volatile void * ) NULL );
|
||||||
|
}
|
||||||
|
|
|
@ -289,6 +289,46 @@ switch_before_exit:
|
||||||
next. */
|
next. */
|
||||||
portRESTORE_CONTEXT
|
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
|
ulICCIARConst: .word ulICCIAR
|
||||||
ulICCEOIRConst: .word ulICCEOIR
|
ulICCEOIRConst: .word ulICCEOIR
|
||||||
ulICCPMRConst: .word ulICCPMR
|
ulICCPMRConst: .word ulICCPMR
|
||||||
|
@ -299,6 +339,7 @@ ulMaxAPIPriorityMaskConst: .word ulMaxAPIPriorityMask
|
||||||
vTaskSwitchContextConst: .word vTaskSwitchContext
|
vTaskSwitchContextConst: .word vTaskSwitchContext
|
||||||
vApplicationIRQHandlerConst: .word vApplicationIRQHandler
|
vApplicationIRQHandlerConst: .word vApplicationIRQHandler
|
||||||
ulPortInterruptNestingConst: .word ulPortInterruptNesting
|
ulPortInterruptNestingConst: .word ulPortInterruptNesting
|
||||||
|
vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
|
||||||
|
|
||||||
.end
|
.end
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
|
||||||
/*
|
/*
|
||||||
* Function to enable the VFP.
|
* 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.
|
* 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
|
a non-privileged mode or the binary point register was not set to its lowest
|
||||||
possible value. */
|
possible value. */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue