}\r
/*-----------------------------------------------------------*/\r
\r
-void vApplicationIRQHandler( uint32_t ulICCIAR )\r
+/* This is the callback function which is called by the FreeRTOS Cortex-A port\r
+layer in response to an interrupt. If the function is called\r
+vApplicationFPUSafeIRQHandler() then it is called after the floating point\r
+registers have been saved. If the function is called vApplicationIRQHandler()\r
+then it will be called without first having saved the FPU registers. See\r
+http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html for\r
+more information */\r
+void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )\r
{\r
extern const XScuGic_Config XScuGic_ConfigTable[];\r
static const XScuGic_VectorTableEntry *pxVectorTable = XScuGic_ConfigTable[ XPAR_SCUGIC_SINGLE_DEVICE_ID ].HandlerTable;\r
const XScuGic_VectorTableEntry *pxVectorEntry;\r
\r
/* Re-enable interrupts. */\r
- __asm ( "cpsie i" );\r
+ __asm ( "cpsie i" );\r
\r
/* The ID of the interrupt is obtained by bitwise anding the ICCIAR value\r
with 0x3FF. */\r
*/\r
static void prvTaskExitError( void );\r
\r
+/*\r
+ * If the application provides an implementation of vApplicationIRQHandler(),\r
+ * then it will get called directly without saving the FPU registers on\r
+ * interrupt entry, and this weak implementation of \r
+ * vApplicationFPUSafeIRQHandler() is just provided to remove linkage errors -\r
+ * it should never actually get called so its implementation contains a\r
+ * call to configASSERT() that will always fail.\r
+ *\r
+ * If the application provides its own implementation of \r
+ * vApplicationFPUSafeIRQHandler() then the implementation of \r
+ * vApplicationIRQHandler() provided in portASM.S will save the FPU registers\r
+ * before calling it.\r
+ *\r
+ * Therefore, if the application writer wants FPU registers to be saved on\r
+ * interrupt entry their IRQ handler must be called \r
+ * vApplicationFPUSafeIRQHandler(), and if the application writer does not want\r
+ * FPU registers to be saved on interrupt entry their IRQ handler must be\r
+ * called vApplicationIRQHandler().\r
+ */\r
+void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__((weak) );\r
+\r
/*-----------------------------------------------------------*/\r
\r
/* A variable is used to keep track of the critical section nesting. This\r
}\r
}\r
\r
- /* Will only get here if xTaskStartScheduler() was called with the CPU in\r
+ /* Will only get here if vTaskStartScheduler() was called with the CPU in\r
a non-privileged mode or the binary point register was not set to its lowest\r
possible value. prvTaskExitError() is referenced to prevent a compiler\r
warning about it being defined but not referenced in the case that the user\r
#endif /* configASSERT_DEFINED */\r
/*-----------------------------------------------------------*/\r
\r
+void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )\r
+{\r
+ configASSERT( ( volatile void * ) NULL );\r
+}\r
next. */\r
portRESTORE_CONTEXT\r
\r
+\r
+/******************************************************************************\r
+ * If the application provides an implementation of vApplicationIRQHandler(),\r
+ * then it will get called directly without saving the FPU registers on\r
+ * interrupt entry, and this weak implementation of\r
+ * vApplicationIRQHandler() will not get called.\r
+ *\r
+ * If the application provides its own implementation of\r
+ * vApplicationFPUSafeIRQHandler() then this implementation of\r
+ * vApplicationIRQHandler() will be called, save the FPU registers, and then\r
+ * call vApplicationFPUSafeIRQHandler().\r
+ *\r
+ * Therefore, if the application writer wants FPU registers to be saved on\r
+ * interrupt entry their IRQ handler must be called\r
+ * vApplicationFPUSafeIRQHandler(), and if the application writer does not want\r
+ * FPU registers to be saved on interrupt entry their IRQ handler must be\r
+ * called vApplicationIRQHandler().\r
+ *****************************************************************************/\r
+\r
+.align 4\r
+.weak vApplicationIRQHandler\r
+.type vApplicationIRQHandler, %function\r
+vApplicationIRQHandler:\r
+ PUSH {LR}\r
+ FMRX R1, FPSCR\r
+ VPUSH {D0-D15}\r
+ VPUSH {D16-D31}\r
+ PUSH {R1}\r
+\r
+ LDR r1, vApplicationFPUSafeIRQHandlerConst\r
+ BLX r1\r
+\r
+ POP {R0}\r
+ VPOP {D16-D31}\r
+ VPOP {D0-D15}\r
+ VMSR FPSCR, R0\r
+\r
+ POP {PC}\r
+\r
+\r
ulICCIARConst: .word ulICCIAR\r
ulICCEOIRConst: .word ulICCEOIR\r
ulICCPMRConst: .word ulICCPMR\r
vTaskSwitchContextConst: .word vTaskSwitchContext\r
vApplicationIRQHandlerConst: .word vApplicationIRQHandler\r
ulPortInterruptNestingConst: .word ulPortInterruptNesting\r
+vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler\r
\r
.end\r
\r
/*\r
* Function to enable the VFP.\r
*/\r
- static void vPortEnableVFP( void ) __attribute__ (( naked ));\r
+static void vPortEnableVFP( void ) __attribute__ (( naked ));\r
\r
/*\r
* Used to catch tasks that attempt to return from their implementing function.\r
}\r
}\r
\r
- /* Will only get here if xTaskStartScheduler() was called with the CPU in\r
+ /* Will only get here if vTaskStartScheduler() was called with the CPU in\r
a non-privileged mode or the binary point register was not set to its lowest\r
possible value. */\r
return 0;\r