28
28
29
29
/* Standard includes. */
30
30
#include <stdlib.h>
31
+ #include <string.h>
31
32
32
33
/* Scheduler includes. */
33
34
#include "FreeRTOS.h"
148
149
#define portTASK_RETURN_ADDRESS prvTaskExitError
149
150
#endif
150
151
152
+ /*
153
+ * The space on the stack required to hold the FPU registers.
154
+ *
155
+ * The ARM Cortex R5 processor implements the VFPv3-D16 FPU
156
+ * architecture. This includes only 16 double-precision registers,
157
+ * instead of 32 as is in VFPv3. The register bank can be viewed
158
+ * either as sixteen 64-bit double-word registers (D0-D15) or
159
+ * thirty-two 32-bit single-word registers (S0-S31), in both cases
160
+ * the size of the bank remains the same. The FPU has also a 32-bit
161
+ * status register.
162
+ */
163
+ #define portFPU_REGISTER_WORDS ( ( 16 * 2 ) + 1 )
164
+
151
165
/*-----------------------------------------------------------*/
152
166
153
167
/*
@@ -161,6 +175,27 @@ extern void vPortRestoreTaskContext( void );
161
175
*/
162
176
static void prvTaskExitError ( void );
163
177
178
+ /*
179
+ * If the application provides an implementation of vApplicationIRQHandler(),
180
+ * then it will get called directly without saving the FPU registers on
181
+ * interrupt entry, and this weak implementation of
182
+ * vApplicationFPUSafeIRQHandler() is just provided to remove linkage errors -
183
+ * it should never actually get called so its implementation contains a
184
+ * call to configASSERT() that will always fail.
185
+ *
186
+ * If the application provides its own implementation of
187
+ * vApplicationFPUSafeIRQHandler() then the implementation of
188
+ * vApplicationIRQHandler() provided in portASM.S will save the FPU registers
189
+ * before calling it.
190
+ *
191
+ * Therefore, if the application writer wants FPU registers to be saved on
192
+ * interrupt entry their IRQ handler must be called
193
+ * vApplicationFPUSafeIRQHandler(), and if the application writer does not want
194
+ * FPU registers to be saved on interrupt entry their IRQ handler must be
195
+ * called vApplicationIRQHandler().
196
+ */
197
+ void vApplicationFPUSafeIRQHandler ( uint32_t ulICCIAR ) __attribute__((weak ) );
198
+
164
199
/*-----------------------------------------------------------*/
165
200
166
201
/* A variable is used to keep track of the critical section nesting. This
@@ -255,12 +290,31 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
255
290
/* The task will start with a critical nesting count of 0 as interrupts are
256
291
* enabled. */
257
292
* pxTopOfStack = portNO_CRITICAL_NESTING ;
258
- pxTopOfStack -- ;
259
293
260
- /* The task will start without a floating point context. A task that uses
261
- * the floating point hardware must call vPortTaskUsesFPU() before executing
262
- * any floating point instructions. */
263
- * pxTopOfStack = portNO_FLOATING_POINT_CONTEXT ;
294
+ #if ( configUSE_TASK_FPU_SUPPORT == 1 )
295
+ {
296
+ /* The task will start without a floating point context. A task that
297
+ uses the floating point hardware must call vPortTaskUsesFPU() before
298
+ executing any floating point instructions. */
299
+ pxTopOfStack -- ;
300
+ * pxTopOfStack = portNO_FLOATING_POINT_CONTEXT ;
301
+ }
302
+ #elif ( configUSE_TASK_FPU_SUPPORT == 2 )
303
+ {
304
+ /* The task will start with a floating point context. Leave enough
305
+ space for the registers - and ensure they are initialized to 0. */
306
+ pxTopOfStack -= portFPU_REGISTER_WORDS ;
307
+ memset ( pxTopOfStack , 0x00 , portFPU_REGISTER_WORDS * sizeof ( StackType_t ) );
308
+
309
+ pxTopOfStack -- ;
310
+ * pxTopOfStack = pdTRUE ;
311
+ ulPortTaskHasFPUContext = pdTRUE ;
312
+ }
313
+ #else
314
+ {
315
+ #error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined.
316
+ }
317
+ #endif /* configUSE_TASK_FPU_SUPPORT */
264
318
265
319
return pxTopOfStack ;
266
320
}
@@ -283,6 +337,13 @@ static void prvTaskExitError( void )
283
337
}
284
338
/*-----------------------------------------------------------*/
285
339
340
+ void vApplicationFPUSafeIRQHandler ( uint32_t ulICCIAR )
341
+ {
342
+ ( void ) ulICCIAR ;
343
+ configASSERT ( ( volatile void * ) NULL );
344
+ }
345
+ /*-----------------------------------------------------------*/
346
+
286
347
BaseType_t xPortStartScheduler ( void )
287
348
{
288
349
uint32_t ulAPSR , ulCycles = 8 ; /* 8 bits per byte. */
@@ -444,17 +505,21 @@ void FreeRTOS_Tick_Handler( void )
444
505
}
445
506
/*-----------------------------------------------------------*/
446
507
447
- void vPortTaskUsesFPU ( void )
448
- {
449
- uint32_t ulInitialFPSCR = 0 ;
508
+ #if ( configUSE_TASK_FPU_SUPPORT != 2 )
450
509
451
- /* A task is registering the fact that it needs an FPU context. Set the
452
- * FPU flag (which is saved as part of the task context). */
453
- ulPortTaskHasFPUContext = pdTRUE ;
510
+ void vPortTaskUsesFPU ( void )
511
+ {
512
+ uint32_t ulInitialFPSCR = 0 ;
454
513
455
- /* Initialise the floating point status register. */
456
- __asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" );
457
- }
514
+ /* A task is registering the fact that it needs an FPU context. Set the
515
+ * FPU flag (which is saved as part of the task context). */
516
+ ulPortTaskHasFPUContext = pdTRUE ;
517
+
518
+ /* Initialise the floating point status register. */
519
+ __asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" );
520
+ }
521
+
522
+ #endif /* configUSE_TASK_FPU_SUPPORT */
458
523
/*-----------------------------------------------------------*/
459
524
460
525
void vPortClearInterruptMask ( uint32_t ulNewMaskValue )
0 commit comments