|
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"
|
|
80 | 81 | #define portTASK_RETURN_ADDRESS prvTaskExitError
|
81 | 82 | #endif
|
82 | 83 |
|
| 84 | +/* The space on the stack required to hold the FPU registers. */ |
| 85 | +#if ( configFPU_D32 == 1 ) |
| 86 | + #define portFPU_REGISTER_WORDS ( ( 32 * 2 ) + 1 ) /* D0-D31 and FPSCR. */ |
| 87 | +#else |
| 88 | + #define portFPU_REGISTER_WORDS ( ( 16 * 2 ) + 1 ) /* D0-D15 and FPSCR. */ |
| 89 | +#endif /* configFPU_D32 */ |
| 90 | + |
83 | 91 | /*-----------------------------------------------------------*/
|
84 | 92 |
|
85 | 93 | /*
|
86 |
| - * Starts the first task executing. This function is necessarily written in |
87 |
| - * assembly code so is implemented in portASM.s. |
| 94 | + * These functions are necessarily written in assembly code, so are implemented |
| 95 | + * in portASM.S. |
88 | 96 | */
|
89 | 97 | extern void vPortRestoreTaskContext( void );
|
| 98 | +extern void vPortInitialiseFPSCR( void ); |
| 99 | +extern uint32_t ulReadAPSR( void ); |
90 | 100 |
|
91 | 101 | /*
|
92 | 102 | * Used to catch tasks that attempt to return from their implementing function.
|
@@ -184,12 +194,33 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
184 | 194 | /* The task will start with a critical nesting count of 0 as interrupts are
|
185 | 195 | * enabled. */
|
186 | 196 | *pxTopOfStack = portNO_CRITICAL_NESTING;
|
187 |
| - pxTopOfStack--; |
188 | 197 |
|
189 |
| - /* The task will start without a floating point context. A task that uses |
190 |
| - * the floating point hardware must call vPortTaskUsesFPU() before executing |
191 |
| - * any floating point instructions. */ |
192 |
| - *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; |
| 198 | + #if ( configUSE_TASK_FPU_SUPPORT == 1 ) |
| 199 | + { |
| 200 | + /* The task will start without a floating point context. A task that uses |
| 201 | + * the floating point hardware must call vPortTaskUsesFPU() before executing |
| 202 | + * any floating point instructions. */ |
| 203 | + pxTopOfStack--; |
| 204 | + *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; |
| 205 | + } |
| 206 | + #elif ( configUSE_TASK_FPU_SUPPORT == 2 ) |
| 207 | + { |
| 208 | + /* The task will start with a floating point context. Leave enough |
| 209 | + * space for the registers - and ensure they are initialised to 0. */ |
| 210 | + pxTopOfStack -= portFPU_REGISTER_WORDS; |
| 211 | + memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) ); |
| 212 | + |
| 213 | + /* Initialise the slot containing ulPortTaskHasFPUContext to true as |
| 214 | + * the task starts with a floating point context. */ |
| 215 | + pxTopOfStack--; |
| 216 | + *pxTopOfStack = pdTRUE; |
| 217 | + ulPortTaskHasFPUContext = pdTRUE; |
| 218 | + } |
| 219 | + #else |
| 220 | + { |
| 221 | + #error "Invalid configUSE_TASK_FPU_SUPPORT value - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined." |
| 222 | + } |
| 223 | + #endif /* if ( configUSE_TASK_FPU_SUPPORT == 1 ) */ |
193 | 224 |
|
194 | 225 | return pxTopOfStack;
|
195 | 226 | }
|
@@ -218,7 +249,7 @@ BaseType_t xPortStartScheduler( void )
|
218 | 249 |
|
219 | 250 | /* Only continue if the CPU is not in User mode. The CPU must be in a
|
220 | 251 | * Privileged mode for the scheduler to start. */
|
221 |
| - __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR )::"memory" ); |
| 252 | + ulAPSR = ulReadAPSR(); |
222 | 253 |
|
223 | 254 | ulAPSR &= portAPSR_MODE_BITS_MASK;
|
224 | 255 | configASSERT( ulAPSR != portAPSR_USER_MODE );
|
@@ -310,15 +341,17 @@ void FreeRTOS_Tick_Handler( void )
|
310 | 341 | }
|
311 | 342 | /*-----------------------------------------------------------*/
|
312 | 343 |
|
313 |
| -void vPortTaskUsesFPU( void ) |
314 |
| -{ |
315 |
| - uint32_t ulInitialFPSCR = 0; |
| 344 | +#if ( configUSE_TASK_FPU_SUPPORT != 2 ) |
316 | 345 |
|
317 |
| - /* A task is registering the fact that it needs an FPU context. Set the |
318 |
| - * FPU flag (which is saved as part of the task context). */ |
319 |
| - ulPortTaskHasFPUContext = pdTRUE; |
| 346 | + void vPortTaskUsesFPU( void ) |
| 347 | + { |
| 348 | + /* A task is registering the fact that it needs an FPU context. Set the |
| 349 | + * FPU flag (which is saved as part of the task context). */ |
| 350 | + ulPortTaskHasFPUContext = pdTRUE; |
320 | 351 |
|
321 |
| - /* Initialise the floating point status register. */ |
322 |
| - __asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" ); |
323 |
| -} |
| 352 | + /* Initialise the floating point status register. */ |
| 353 | + vPortInitialiseFPSCR(); |
| 354 | + } |
| 355 | + |
| 356 | +#endif /* configUSE_TASK_FPU_SUPPORT */ |
324 | 357 | /*-----------------------------------------------------------*/
|
0 commit comments