Enable building the GCC Cortex-R5 port without an FPU (#586)

* Ensure configUSE_TASK_FPU_SUPPORT option is set correctly

If one does enable the FPU of the Cortex-R5 processor, then the GCC
compiler will define the macro __ARM_FP. This can be used to ensure,
that the configUSE_TASK_FPU_SUPPORT is set accordingly.

* Enable the implementation of vPortTaskUsesFPU only if configUSE_TASK_FPU_SUPPORT is set to 1

* Remove error case in pxPortInitialiseStack

The case of configUSE_TASK_FPU_SUPPORT is 0 is now handled

* Enable access to FPU registers only if FPU is enabled

* Make minor formating changes

* Format ARM Cortex-R5 port

* Address review comments from @ChristosZosi

* Minor code review suggestions

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>

---------

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com>
Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com>
Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com>
diff --git a/portable/GCC/ARM_CR5/port.c b/portable/GCC/ARM_CR5/port.c
index 8a9839c..0300782 100644
--- a/portable/GCC/ARM_CR5/port.c
+++ b/portable/GCC/ARM_CR5/port.c
@@ -74,25 +74,52 @@
     #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
 #endif
 
-/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
- * portmacro.h. */
+/*
+ * __ARM_FP is defined by the c preprocessor when FPU support is enabled,
+ * usually with the -mfpu= argument and -mfloat-abi=.
+ *
+ * Note: Some implementations of the c standard library may use FPU registers
+ *       for generic memory operations (memcpy, etc).
+ *       When setting configUSE_TASK_FPU_SUPPORT == 1, care must be taken to
+ *       ensure that the FPU registers are not used without an FPU context.
+ */
+#if ( configUSE_TASK_FPU_SUPPORT == 0 )
+    #ifdef __ARM_FP
+        #error __ARM_FP is defined, so configUSE_TASK_FPU_SUPPORT must be set to either to 1 or 2.
+    #endif /* __ARM_FP */
+#elif ( configUSE_TASK_FPU_SUPPORT == 1 ) || ( configUSE_TASK_FPU_SUPPORT == 2 )
+    #ifndef __ARM_FP
+        #error __ARM_FP is not defined, so configUSE_TASK_FPU_SUPPORT must be set to 0.
+    #endif /* __ARM_FP */
+#endif /* configUSE_TASK_FPU_SUPPORT */
+
+/*
+ * Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
+ * portmacro.h.
+ */
 #ifndef configCLEAR_TICK_INTERRUPT
     #define configCLEAR_TICK_INTERRUPT()
 #endif
 
-/* A critical section is exited when the critical section nesting count reaches
- * this value. */
+/*
+ * A critical section is exited when the critical section nesting count reaches
+ * this value.
+ */
 #define portNO_CRITICAL_NESTING          ( ( uint32_t ) 0 )
 
-/* In all GICs 255 can be written to the priority mask register to unmask all
- * (but the lowest) interrupt priority. */
+/*
+ * In all GICs 255 can be written to the priority mask register to unmask all
+ * (but the lowest) interrupt priority.
+ */
 #define portUNMASK_VALUE                 ( 0xFFUL )
 
-/* Tasks are not created with a floating point context, but can be given a
+/*
+ * Tasks are not created with a floating point context, but can be given a
  * floating point context after they have been created.  A variable is stored as
  * part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
  * does not have an FPU context, or any other value if the task does have an FPU
- * context. */
+ * context.
+ */
 #define portNO_FLOATING_POINT_CONTEXT    ( ( StackType_t ) 0 )
 
 /* Constants required to setup the initial task context. */
@@ -101,8 +128,10 @@
 #define portINTERRUPT_ENABLE_BIT         ( 0x80UL )
 #define portTHUMB_MODE_ADDRESS           ( 0x01UL )
 
-/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
- * point is zero. */
+/*
+ * Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
+ * point is zero.
+ */
 #define portBINARY_POINT_BITS            ( ( uint8_t ) 0x03 )
 
 /* Masks all bits in the APSR other than the mode bits. */
@@ -140,15 +169,19 @@
 #define portMAX_8_BIT_VALUE                       ( ( uint8_t ) 0xff )
 #define portBIT_0_SET                             ( ( uint8_t ) 0x01 )
 
-/* Let the user override the pre-loading of the initial LR with the address of
+/*
+ * Let the user override the pre-loading of the initial LR with the address of
  * prvTaskExitError() in case is messes up unwinding of the stack in the
- * debugger. */
+ * debugger.
+ */
 #ifdef configTASK_RETURN_ADDRESS
     #define portTASK_RETURN_ADDRESS    configTASK_RETURN_ADDRESS
 #else
     #define portTASK_RETURN_ADDRESS    prvTaskExitError
 #endif
 
+#if ( configUSE_TASK_FPU_SUPPORT != 0 )
+
 /*
  * The space on the stack required to hold the FPU registers.
  *
@@ -160,7 +193,8 @@
  * the size of the bank remains the same. The FPU has also a 32-bit
  * status register.
  */
-#define portFPU_REGISTER_WORDS    ( ( 16 * 2 ) + 1 )
+    #define portFPU_REGISTER_WORDS    ( ( 16 * 2 ) + 1 )
+#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
 
 /*-----------------------------------------------------------*/
 
@@ -175,6 +209,8 @@
  */
 static void prvTaskExitError( void );
 
+#if ( configUSE_TASK_FPU_SUPPORT != 0 )
+
 /*
  * If the application provides an implementation of vApplicationIRQHandler(),
  * then it will get called directly without saving the FPU registers on
@@ -194,26 +230,36 @@
  * FPU registers to be saved on interrupt entry their IRQ handler must be
  * called vApplicationIRQHandler().
  */
-void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__((weak) );
+    void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__( ( weak ) );
+#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
 
 /*-----------------------------------------------------------*/
 
-/* 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
  * variable has to be stored as part of the task context and must be initialised to
  * a non zero value to ensure interrupts don't inadvertently become unmasked before
  * the scheduler starts.  As it is stored as part of the task context it will
- * automatically be set to 0 when the first task is started. */
+ * automatically be set to 0 when the first task is started.
+ */
 volatile uint32_t ulCriticalNesting = 9999UL;
 
-/* Saved as part of the task context.  If ulPortTaskHasFPUContext is non-zero then
- * a floating point context must be saved and restored for the task. */
-uint32_t ulPortTaskHasFPUContext = pdFALSE;
+#if ( configUSE_TASK_FPU_SUPPORT != 0 )
+
+/*
+ * Saved as part of the task context.  If ulPortTaskHasFPUContext is non-zero then
+ * a floating point context must be saved and restored for the task.
+ */
+    uint32_t ulPortTaskHasFPUContext = pdFALSE;
+#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
 
 /* Set to 1 to pend a context switch from an ISR. */
 uint32_t ulPortYieldRequired = pdFALSE;
 
-/* Counts the interrupt nesting depth.  A context switch is only performed if
- * if the nesting depth is 0. */
+/*
+ * Counts the interrupt nesting depth.  A context switch is only performed if
+ * if the nesting depth is 0.
+ */
 uint32_t ulPortInterruptNesting = 0UL;
 
 /* Used in asm code. */
@@ -231,12 +277,14 @@
                                      TaskFunction_t pxCode,
                                      void * pvParameters )
 {
-    /* Setup the initial stack of the task.  The stack is set exactly as
+    /*
+     * Setup the initial stack of the task.  The stack is set exactly as
      * expected by the portRESTORE_CONTEXT() macro.
      *
      * The fist real value on the stack is the status register, which is set for
      * system mode, with interrupts enabled.  A few NULLs are added first to ensure
-     * GDB does not try decoding a non-existent return address. */
+     * GDB does not try decoding a non-existent return address.
+     */
     *pxTopOfStack = ( StackType_t ) NULL;
     pxTopOfStack--;
     *pxTopOfStack = ( StackType_t ) NULL;
@@ -285,24 +333,31 @@
     *pxTopOfStack = ( StackType_t ) 0x01010101;              /* R1 */
     pxTopOfStack--;
     *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0 */
-    pxTopOfStack--;
 
-    /* The task will start with a critical nesting count of 0 as interrupts are
-     * enabled. */
+    /*
+     * The task will start with a critical nesting count of 0 as interrupts are
+     * enabled.
+     */
+    pxTopOfStack--;
     *pxTopOfStack = portNO_CRITICAL_NESTING;
 
-    #if( configUSE_TASK_FPU_SUPPORT == 1 )
+    #if ( configUSE_TASK_FPU_SUPPORT == 1 )
     {
-        /* The task will start without a floating point context.  A task that
-        uses the floating point hardware must call vPortTaskUsesFPU() before
-        executing any floating point instructions. */
+        /*
+         * The task will start without a floating point context.
+         * A task that uses the floating point hardware must call
+         * vPortTaskUsesFPU() before executing any floating point
+         * instructions.
+         */
         pxTopOfStack--;
         *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
     }
-    #elif( configUSE_TASK_FPU_SUPPORT == 2 )
+    #elif ( configUSE_TASK_FPU_SUPPORT == 2 )
     {
-        /* The task will start with a floating point context.  Leave enough
-        space for the registers - and ensure they are initialized to 0. */
+        /*
+         * The task will start with a floating point context. Leave enough
+         * space for the registers and ensure they are initialized to 0.
+         */
         pxTopOfStack -= portFPU_REGISTER_WORDS;
         memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );
 
@@ -310,9 +365,9 @@
         *pxTopOfStack = pdTRUE;
         ulPortTaskHasFPUContext = pdTRUE;
     }
-    #else
+    #elif ( configUSE_TASK_FPU_SUPPORT != 0 )
     {
-        #error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined.
+        #error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 0, 1, or 2.
     }
     #endif /* configUSE_TASK_FPU_SUPPORT */
 
@@ -322,12 +377,14 @@
 
 static void prvTaskExitError( void )
 {
-    /* A function that implements a task must not exit or attempt to return to
+    /*
+     * A function that implements a task must not exit or attempt to return to
      * its caller as there is nothing to return to.  If a task wants to exit it
      * should instead call vTaskDelete( NULL ).
      *
      * Artificially force an assert() to be triggered if configASSERT() is
-     * defined, then stop here so application writers can catch the error. */
+     * defined, then stop here so application writers can catch the error.
+     */
     configASSERT( ulPortInterruptNesting == ~0UL );
     portDISABLE_INTERRUPTS();
 
@@ -337,11 +394,15 @@
 }
 /*-----------------------------------------------------------*/
 
-void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )
-{
-    ( void ) ulICCIAR;
-    configASSERT( ( volatile void * ) NULL );
-}
+#if ( configUSE_TASK_FPU_SUPPORT != 0 )
+
+    void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) /* __attribute__( ( weak ) ) */
+    {
+        ( void ) ulICCIAR;
+        configASSERT( ( volatile void * ) NULL );
+    }
+
+#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
 /*-----------------------------------------------------------*/
 
 BaseType_t xPortStartScheduler( void )
@@ -349,67 +410,82 @@
     uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */
 
     #if ( configASSERT_DEFINED == 1 )
+    {
+        volatile uint32_t ulOriginalPriority;
+        volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
+        volatile uint8_t ucMaxPriorityValue;
+
+        /*
+         * Determine how many priority bits are implemented in the GIC.
+         * Save the interrupt priority value that is about to be clobbered.
+         */
+        ulOriginalPriority = *pucFirstUserPriorityRegister;
+
+        /*
+         * Determine the number of priority bits available.  First write to
+         * all possible bits.
+         */
+        *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
+
+        /* Read the value back to see how many bits stuck. */
+        ucMaxPriorityValue = *pucFirstUserPriorityRegister;
+
+        /* Shift to the least significant bits. */
+        while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
         {
-            volatile uint32_t ulOriginalPriority;
-            volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
-            volatile uint8_t ucMaxPriorityValue;
+            ucMaxPriorityValue >>= ( uint8_t ) 0x01;
 
-            /* Determine how many priority bits are implemented in the GIC.
-             *
-             * Save the interrupt priority value that is about to be clobbered. */
-            ulOriginalPriority = *pucFirstUserPriorityRegister;
+            /*
+             * If ulCycles reaches 0 then ucMaxPriorityValue must have been
+             * read as 0, indicating a misconfiguration.
+             */
+            ulCycles--;
 
-            /* Determine the number of priority bits available.  First write to
-             * all possible bits. */
-            *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
-
-            /* Read the value back to see how many bits stuck. */
-            ucMaxPriorityValue = *pucFirstUserPriorityRegister;
-
-            /* Shift to the least significant bits. */
-            while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
+            if( ulCycles == 0 )
             {
-                ucMaxPriorityValue >>= ( uint8_t ) 0x01;
-
-                /* If ulCycles reaches 0 then ucMaxPriorityValue must have been
-                 * read as 0, indicating a misconfiguration. */
-                ulCycles--;
-
-                if( ulCycles == 0 )
-                {
-                    break;
-                }
+                break;
             }
-
-            /* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
-             * value. */
-            configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
-
-            /* Restore the clobbered interrupt priority register to its original
-             * value. */
-            *pucFirstUserPriorityRegister = ulOriginalPriority;
         }
+
+        /*
+         * Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
+         * value.
+         */
+        configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
+
+        /*
+         * Restore the clobbered interrupt priority register to its original
+         * value.
+         */
+        *pucFirstUserPriorityRegister = ulOriginalPriority;
+    }
     #endif /* configASSERT_DEFINED */
 
-    /* Only continue if the CPU is not in User mode.  The CPU must be in a
-     * Privileged mode for the scheduler to start. */
+    /*
+     * Only continue if the CPU is not in User mode.  The CPU must be in a
+     * Privileged mode for the scheduler to start.
+     */
     __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR )::"memory" );
     ulAPSR &= portAPSR_MODE_BITS_MASK;
     configASSERT( ulAPSR != portAPSR_USER_MODE );
 
     if( ulAPSR != portAPSR_USER_MODE )
     {
-        /* Only continue if the binary point value is set to its lowest possible
+        /*
+         * Only continue if the binary point value is set to its lowest possible
          * setting.  See the comments in vPortValidateInterruptPriority() below for
-         * more information. */
+         * more information.
+         */
         configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
 
         if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
         {
-            /* Interrupts are turned off in the CPU itself to ensure tick does
+            /*
+             * Interrupts are turned off in the CPU itself to ensure tick does
              * not execute  while the scheduler is being started.  Interrupts are
              * automatically turned back on in the CPU when the first task starts
-             * executing. */
+             * executing.
+             */
             portCPU_IRQ_DISABLE();
 
             /* Start the timer that generates the tick ISR. */
@@ -420,20 +496,25 @@
         }
     }
 
-    /* Will only get here if vTaskStartScheduler() 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
-     * defines their own exit address. */
+     * defines their own exit address.
+     */
     ( void ) prvTaskExitError;
+
     return 0;
 }
 /*-----------------------------------------------------------*/
 
 void vPortEndScheduler( void )
 {
-    /* Not implemented in ports where there is nothing to return to.
-     * Artificially force an assert. */
+    /*
+     * Not implemented in ports where there is nothing to return to.
+     * Artificially force an assert.
+     */
     configASSERT( ulCriticalNesting == 1000UL );
 }
 /*-----------------------------------------------------------*/
@@ -443,16 +524,20 @@
     /* Mask interrupts up to the max syscall interrupt priority. */
     ulPortSetInterruptMask();
 
-    /* Now interrupts are disabled ulCriticalNesting can be accessed
+    /*
+     * Now interrupts are disabled ulCriticalNesting can be accessed
      * directly.  Increment ulCriticalNesting to keep a count of how many times
-     * portENTER_CRITICAL() has been called. */
+     * portENTER_CRITICAL() has been called.
+     */
     ulCriticalNesting++;
 
-    /* This is not the interrupt safe version of the enter critical function so
+    /*
+     * This is not the interrupt safe version of the enter critical function so
      * assert() if it is being called from an interrupt context.  Only API
      * functions that end in "FromISR" can be used in an interrupt.  Only assert if
      * the critical nesting count is 1 to protect against recursive calls if the
-     * assert function also uses a critical section. */
+     * assert function also uses a critical section.
+     */
     if( ulCriticalNesting == 1 )
     {
         configASSERT( ulPortInterruptNesting == 0 );
@@ -464,16 +549,19 @@
 {
     if( ulCriticalNesting > portNO_CRITICAL_NESTING )
     {
-        /* Decrement the nesting count as the critical section is being
-         * exited. */
+        /* Decrement the nesting count as the critical section is being exited. */
         ulCriticalNesting--;
 
-        /* If the nesting level has reached zero then all interrupt
-         * priorities must be re-enabled. */
+        /*
+         * If the nesting level has reached zero then all interrupt
+         * priorities must be re-enabled.
+         */
         if( ulCriticalNesting == portNO_CRITICAL_NESTING )
         {
-            /* Critical nesting has reached zero so all interrupt priorities
-             * should be unmasked. */
+            /*
+             * Critical nesting has reached zero so all interrupt priorities
+             * should be unmasked.
+             */
             portCLEAR_INTERRUPT_MASK();
         }
     }
@@ -482,11 +570,13 @@
 
 void FreeRTOS_Tick_Handler( void )
 {
-    /* Set interrupt mask before altering scheduler structures.   The tick
+    /*
+     * Set interrupt mask before altering scheduler structures.   The tick
      * handler runs at the lowest priority, so interrupts cannot already be masked,
      * so there is no need to save and restore the current mask value.  It is
      * necessary to turn off interrupts in the CPU itself while the ICCPMR is being
-     * updated. */
+     * updated.
+     */
     portCPU_IRQ_DISABLE();
     portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
     __asm volatile ( "dsb       \n"
@@ -505,21 +595,23 @@
 }
 /*-----------------------------------------------------------*/
 
-#if( configUSE_TASK_FPU_SUPPORT != 2 )
+#if ( configUSE_TASK_FPU_SUPPORT == 1 )
 
     void vPortTaskUsesFPU( void )
     {
         uint32_t ulInitialFPSCR = 0;
 
-        /* A task is registering the fact that it needs an FPU context.  Set the
-         * FPU flag (which is saved as part of the task context). */
+        /*
+         * A task is registering the fact that it needs an FPU context. Set the
+         * FPU flag (which is saved as part of the task context).
+         */
         ulPortTaskHasFPUContext = pdTRUE;
 
         /* Initialise the floating point status register. */
         __asm volatile ( "FMXR  FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" );
     }
 
-#endif /* configUSE_TASK_FPU_SUPPORT */
+#endif /* configUSE_TASK_FPU_SUPPORT == 1 */
 /*-----------------------------------------------------------*/
 
 void vPortClearInterruptMask( uint32_t ulNewMaskValue )
@@ -535,8 +627,7 @@
 {
     uint32_t ulReturn;
 
-    /* Interrupt in the CPU must be turned off while the ICCPMR is being
-     * updated. */
+    /* Interrupts must be masked while ICCPMR is updated. */
     portCPU_IRQ_DISABLE();
 
     if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
@@ -562,7 +653,8 @@
 
     void vPortValidateInterruptPriority( void )
     {
-        /* The following assertion will fail if a service routine (ISR) for
+        /*
+         * The following assertion will fail if a service routine (ISR) for
          * an interrupt that has been assigned a priority above
          * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
          * function.  ISR safe FreeRTOS API functions must *only* be called
@@ -575,11 +667,13 @@
          * configMAX_SYSCALL_INTERRUPT_PRIORITY.
          *
          * FreeRTOS maintains separate thread and ISR API functions to ensure
-         * interrupt entry is as fast and simple as possible. */
+         * interrupt entry is as fast and simple as possible.
+         */
 
         configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
 
-        /* Priority grouping:  The interrupt controller (GIC) allows the bits
+        /*
+         * Priority grouping:  The interrupt controller (GIC) allows the bits
          * that define each interrupt's priority to be split between bits that
          * define the interrupt's pre-emption priority bits and bits that define
          * the interrupt's sub-priority.  For simplicity all bits must be defined
@@ -588,7 +682,8 @@
          *
          * The priority grouping is configured by the GIC's binary point register
          * (ICCBPR).  Writing 0 to ICCBPR will ensure it is set to its lowest
-         * possible value (which may be above 0). */
+         * possible value (which may be above 0).
+         */
         configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
     }
 
diff --git a/portable/GCC/ARM_CR5/portASM.S b/portable/GCC/ARM_CR5/portASM.S
index c44ea6b..c331057 100644
--- a/portable/GCC/ARM_CR5/portASM.S
+++ b/portable/GCC/ARM_CR5/portASM.S
@@ -45,7 +45,10 @@
     .extern vTaskSwitchContext
     .extern vApplicationIRQHandler
     .extern ulPortInterruptNesting
+
+#if defined( __ARM_FP )
     .extern ulPortTaskHasFPUContext
+#endif /* __ARM_FP */
 
     .global FreeRTOS_IRQ_Handler
     .global FreeRTOS_SWI_Handler
@@ -64,20 +67,21 @@
     LDR     R1, [R2]
     PUSH    {R1}
 
-    /* Does the task have a floating point context that needs saving?  If
-    ulPortTaskHasFPUContext is 0 then no. */
-    LDR     R2, ulPortTaskHasFPUContextConst
-    LDR     R3, [R2]
-    CMP     R3, #0
+    #if defined( __ARM_FP )
+        /* Does the task have a floating point context that needs saving?  If
+        ulPortTaskHasFPUContext is 0 then no. */
+        LDR     R2, ulPortTaskHasFPUContextConst
+        LDR     R3, [R2]
+        CMP     R3, #0
 
-    /* Save the floating point context, if any. */
-    FMRXNE  R1,  FPSCR
-    VPUSHNE {D0-D15}
-    /*VPUSHNE   {D16-D31}*/
-    PUSHNE  {R1}
+        /* Save the floating point context, if any. */
+        FMRXNE  R1,  FPSCR
+        VPUSHNE {D0-D15}
+        PUSHNE  {R1}
 
-    /* Save ulPortTaskHasFPUContext itself. */
-    PUSH    {R3}
+        /* Save ulPortTaskHasFPUContext itself. */
+        PUSH    {R3}
+    #endif /* __ARM_FP */
 
     /* Save the stack pointer in the TCB. */
     LDR     R0, pxCurrentTCBConst
@@ -95,18 +99,21 @@
     LDR     R1, [R0]
     LDR     SP, [R1]
 
-    /* Is there a floating point context to restore?  If the restored
-    ulPortTaskHasFPUContext is zero then no. */
-    LDR     R0, ulPortTaskHasFPUContextConst
-    POP     {R1}
-    STR     R1, [R0]
-    CMP     R1, #0
+    #if defined( __ARM_FP )
+        /*
+         * Is there a floating point context to restore?  If the restored
+         * ulPortTaskHasFPUContext is zero then no.
+         */
+        LDR     R0, ulPortTaskHasFPUContextConst
+        POP     {R1}
+        STR     R1, [R0]
+        CMP     R1, #0
 
-    /* Restore the floating point context, if any. */
-    POPNE   {R0}
-    /*VPOPNE    {D16-D31}*/
-    VPOPNE  {D0-D15}
-    VMSRNE  FPSCR, R0
+        /* Restore the floating point context, if any. */
+        POPNE   {R0}
+        VPOPNE  {D0-D15}
+        VMSRNE  FPSCR, R0
+    #endif /* __ARM_FP */
 
     /* Restore the critical section nesting depth. */
     LDR     R0, ulCriticalNestingConst
@@ -132,8 +139,6 @@
     .endm
 
 
-
-
 /******************************************************************************
  * SVC handler is used to start the scheduler.
  *****************************************************************************/
@@ -279,22 +284,25 @@
  * 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}
-    PUSH    {R1}
 
-    LDR     r1, vApplicationFPUSafeIRQHandlerConst
-    BLX     r1
+    #if defined( __ARM_FP )
+        FMRX    R1,  FPSCR
+        VPUSH   {D0-D15}
+        PUSH    {R1}
 
-    POP     {R0}
-    VPOP    {D0-D15}
-    VMSR    FPSCR, R0
+        LDR     r1, vApplicationFPUSafeIRQHandlerConst
+        BLX     r1
+
+        POP     {R0}
+        VPOP    {D0-D15}
+        VMSR    FPSCR, R0
+    #endif /* __ARM_FP */
 
     POP {PC}
 
@@ -303,11 +311,15 @@
 ulICCPMRConst: .word ulICCPMR
 pxCurrentTCBConst: .word pxCurrentTCB
 ulCriticalNestingConst: .word ulCriticalNesting
-ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext
+
+#if defined( __ARM_FP )
+    ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext
+    vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
+#endif /* __ARM_FP */
+
 ulMaxAPIPriorityMaskConst: .word ulMaxAPIPriorityMask
 vTaskSwitchContextConst: .word vTaskSwitchContext
 vApplicationIRQHandlerConst: .word vApplicationIRQHandler
 ulPortInterruptNestingConst: .word ulPortInterruptNesting
-vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
 
 .end
diff --git a/portable/GCC/ARM_CR5/portmacro.h b/portable/GCC/ARM_CR5/portmacro.h
index 4bd25bb..ff7337d 100644
--- a/portable/GCC/ARM_CR5/portmacro.h
+++ b/portable/GCC/ARM_CR5/portmacro.h
@@ -27,11 +27,13 @@
  */
 
 #ifndef PORTMACRO_H
-    #define PORTMACRO_H
+#define PORTMACRO_H
 
-    #ifdef __cplusplus
-        extern "C" {
-    #endif
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+    extern "C" {
+#endif
+/* *INDENT-ON* */
 
 /*-----------------------------------------------------------
  * Port specific definitions.
@@ -44,161 +46,175 @@
  */
 
 /* Type definitions. */
-    #define portCHAR          char
-    #define portFLOAT         float
-    #define portDOUBLE        double
-    #define portLONG          long
-    #define portSHORT         short
-    #define portSTACK_TYPE    uint32_t
-    #define portBASE_TYPE     long
+#define portCHAR          char
+#define portFLOAT         float
+#define portDOUBLE        double
+#define portLONG          long
+#define portSHORT         short
+#define portSTACK_TYPE    uint32_t
+#define portBASE_TYPE     long
 
-    typedef portSTACK_TYPE   StackType_t;
-    typedef long             BaseType_t;
-    typedef unsigned long    UBaseType_t;
+typedef portSTACK_TYPE   StackType_t;
+typedef long             BaseType_t;
+typedef unsigned long    UBaseType_t;
 
-    typedef uint32_t         TickType_t;
-    #define portMAX_DELAY    ( TickType_t ) 0xffffffffUL
+typedef uint32_t         TickType_t;
+#define portMAX_DELAY    ( TickType_t ) 0xffffffffUL
 
 /*-----------------------------------------------------------*/
 
 /* Hardware specifics. */
-    #define portSTACK_GROWTH      ( -1 )
-    #define portTICK_PERIOD_MS    ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
-    #define portBYTE_ALIGNMENT    8
+#define portSTACK_GROWTH      ( -1 )
+#define portTICK_PERIOD_MS    ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
+#define portBYTE_ALIGNMENT    8
 
 /*-----------------------------------------------------------*/
 
 /* Task utilities. */
 
 /* Called at the end of an ISR that can cause a context switch. */
-    #define portEND_SWITCHING_ISR( xSwitchRequired ) \
-    {                                                \
-        extern uint32_t ulPortYieldRequired;         \
-                                                     \
-        if( xSwitchRequired != pdFALSE )             \
-        {                                            \
-            ulPortYieldRequired = pdTRUE;            \
-        }                                            \
+#define portEND_SWITCHING_ISR( xSwitchRequired ) \
+    {                                            \
+        extern uint32_t ulPortYieldRequired;     \
+                                                 \
+        if( xSwitchRequired != pdFALSE )         \
+        {                                        \
+            ulPortYieldRequired = pdTRUE;        \
+        }                                        \
     }
 
-    #define portYIELD_FROM_ISR( x )    portEND_SWITCHING_ISR( x )
-    #define portYIELD()                __asm volatile ( "SWI 0" ::: "memory" );
+#define portYIELD_FROM_ISR( x )    portEND_SWITCHING_ISR( x )
+#define portYIELD()                __asm volatile ( "SWI 0" ::: "memory" );
 
 
 /*-----------------------------------------------------------
 * Critical section control
 *----------------------------------------------------------*/
 
-    extern void vPortEnterCritical( void );
-    extern void vPortExitCritical( void );
-    extern uint32_t ulPortSetInterruptMask( void );
-    extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
-    extern void vPortInstallFreeRTOSVectorTable( void );
+extern void vPortEnterCritical( void );
+extern void vPortExitCritical( void );
+extern uint32_t ulPortSetInterruptMask( void );
+extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
+extern void vPortInstallFreeRTOSVectorTable( void );
 
-/* These macros do not globally disable/enable interrupts.  They do mask off
- * interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
-    #define portENTER_CRITICAL()                      vPortEnterCritical();
-    #define portEXIT_CRITICAL()                       vPortExitCritical();
-    #define portDISABLE_INTERRUPTS()                  ulPortSetInterruptMask()
-    #define portENABLE_INTERRUPTS()                   vPortClearInterruptMask( 0 )
-    #define portSET_INTERRUPT_MASK_FROM_ISR()         ulPortSetInterruptMask()
-    #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vPortClearInterruptMask( x )
+/*
+ * These macros do not globally disable/enable interrupts. They do mask off
+ * interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY.
+ */
+#define portENTER_CRITICAL()                      vPortEnterCritical();
+#define portEXIT_CRITICAL()                       vPortExitCritical();
+#define portDISABLE_INTERRUPTS()                  ulPortSetInterruptMask()
+#define portENABLE_INTERRUPTS()                   vPortClearInterruptMask( 0 )
+#define portSET_INTERRUPT_MASK_FROM_ISR()         ulPortSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vPortClearInterruptMask( x )
 
 /*-----------------------------------------------------------*/
 
-/* Task function macros as described on the FreeRTOS.org WEB site.  These are
+/*
+ * Task function macros as described on the FreeRTOS.org WEB site.  These are
  * not required for this port but included in case common demo code that uses these
- * macros is used. */
-    #define portTASK_FUNCTION_PROTO( vFunction, pvParameters )    void vFunction( void * pvParameters )
-    #define portTASK_FUNCTION( vFunction, pvParameters )          void vFunction( void * pvParameters )
+ * macros is used.
+ */
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters )    void vFunction( void * pvParameters )
+#define portTASK_FUNCTION( vFunction, pvParameters )          void vFunction( void * pvParameters )
 
-/* Prototype of the FreeRTOS tick handler.  This must be installed as the
- * handler for whichever peripheral is used to generate the RTOS tick. */
-    void FreeRTOS_Tick_Handler( void );
+/*
+ * Prototype of the FreeRTOS tick handler.  This must be installed as the
+ * handler for whichever peripheral is used to generate the RTOS tick.
+ */
+void FreeRTOS_Tick_Handler( void );
 
-/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or left undefined) then tasks are
-created without an FPU context and must call vPortTaskUsesFPU() to give
-themselves an FPU context before using any FPU instructions. If
-configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context
-by default. */
-#if( configUSE_TASK_FPU_SUPPORT != 2 )
+/*
+ * If configUSE_TASK_FPU_SUPPORT is set to 1, then tasks are created without an
+ * FPU context and must call vPortTaskUsesFPU() to allocate an FPU context
+ * prior to any FPU instructions. If configUSE_TASK_FPU_SUPPORT is set to 2,
+ * then all tasks have an FPU context allocated by default.
+ */
+#if ( configUSE_TASK_FPU_SUPPORT == 1 )
     void vPortTaskUsesFPU( void );
-#else
-    /* Each task has an FPU context already, so define this function away to
-    nothing to prevent it being called accidentally. */
-    #define vPortTaskUsesFPU()
-#endif /* configUSE_TASK_FPU_SUPPORT */
     #define portTASK_USES_FLOATING_POINT()    vPortTaskUsesFPU()
+#elif ( configUSE_TASK_FPU_SUPPORT == 2 )
 
-    #define portLOWEST_INTERRUPT_PRIORITY           ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
-    #define portLOWEST_USABLE_INTERRUPT_PRIORITY    ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
+/*
+ * Each task has an FPU context already, so define this function away to
+ * prevent it being called accidentally.
+ */
+    #define vPortTaskUsesFPU()
+    #define portTASK_USES_FLOATING_POINT()
+#endif /* configUSE_TASK_FPU_SUPPORT */
+
+#define portLOWEST_INTERRUPT_PRIORITY           ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
+#define portLOWEST_USABLE_INTERRUPT_PRIORITY    ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
 
 /* Architecture specific optimisations. */
-    #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
-        #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
-    #endif
+#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
+    #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
+#endif
 
-    #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
+#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
 
 /* Store/clear the ready priorities in a bit map. */
-        #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities )    ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
-        #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities )     ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
+    #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities )    ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
+    #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities )     ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
 
 /*-----------------------------------------------------------*/
 
-        #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities )    uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
+    #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities )    uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
 
-    #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 
-    #ifdef configASSERT
-        void vPortValidateInterruptPriority( void );
-        #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()    vPortValidateInterruptPriority()
-    #endif /* configASSERT */
+#ifdef configASSERT
+    void vPortValidateInterruptPriority( void );
+    #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()    vPortValidateInterruptPriority()
+#endif /* configASSERT */
 
-    #define portNOP()                                         __asm volatile ( "NOP" )
+#define portNOP()                                         __asm volatile ( "NOP" )
 
 
-    #ifdef __cplusplus
-        } /* extern C */
-    #endif
-
-
-/* The number of bits to shift for an interrupt priority is dependent on the
- * number of bits implemented by the interrupt controller. */
-    #if configUNIQUE_INTERRUPT_PRIORITIES == 16
-        #define portPRIORITY_SHIFT            4
-        #define portMAX_BINARY_POINT_VALUE    3
-    #elif configUNIQUE_INTERRUPT_PRIORITIES == 32
-        #define portPRIORITY_SHIFT            3
-        #define portMAX_BINARY_POINT_VALUE    2
-    #elif configUNIQUE_INTERRUPT_PRIORITIES == 64
-        #define portPRIORITY_SHIFT            2
-        #define portMAX_BINARY_POINT_VALUE    1
-    #elif configUNIQUE_INTERRUPT_PRIORITIES == 128
-        #define portPRIORITY_SHIFT            1
-        #define portMAX_BINARY_POINT_VALUE    0
-    #elif configUNIQUE_INTERRUPT_PRIORITIES == 256
-        #define portPRIORITY_SHIFT            0
-        #define portMAX_BINARY_POINT_VALUE    0
-    #else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
-        #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting.  configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
-    #endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
+/*
+ * The number of bits to shift for an interrupt priority is dependent on the
+ * number of bits implemented by the interrupt controller.
+ */
+#if configUNIQUE_INTERRUPT_PRIORITIES == 16
+    #define portPRIORITY_SHIFT            4
+    #define portMAX_BINARY_POINT_VALUE    3
+#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
+    #define portPRIORITY_SHIFT            3
+    #define portMAX_BINARY_POINT_VALUE    2
+#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
+    #define portPRIORITY_SHIFT            2
+    #define portMAX_BINARY_POINT_VALUE    1
+#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
+    #define portPRIORITY_SHIFT            1
+    #define portMAX_BINARY_POINT_VALUE    0
+#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
+    #define portPRIORITY_SHIFT            0
+    #define portMAX_BINARY_POINT_VALUE    0
+#else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
+    #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting.  configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
+#endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
 
 /* Interrupt controller access addresses. */
-    #define portICCPMR_PRIORITY_MASK_OFFSET                      ( 0x04 )
-    #define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET              ( 0x0C )
-    #define portICCEOIR_END_OF_INTERRUPT_OFFSET                  ( 0x10 )
-    #define portICCBPR_BINARY_POINT_OFFSET                       ( 0x08 )
-    #define portICCRPR_RUNNING_PRIORITY_OFFSET                   ( 0x14 )
+#define portICCPMR_PRIORITY_MASK_OFFSET                      ( 0x04 )
+#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET              ( 0x0C )
+#define portICCEOIR_END_OF_INTERRUPT_OFFSET                  ( 0x10 )
+#define portICCBPR_BINARY_POINT_OFFSET                       ( 0x08 )
+#define portICCRPR_RUNNING_PRIORITY_OFFSET                   ( 0x14 )
 
-    #define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS       ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
-    #define portICCPMR_PRIORITY_MASK_REGISTER                    ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
-    #define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS    ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
-    #define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS        ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
-    #define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS            ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
-    #define portICCBPR_BINARY_POINT_REGISTER                     ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
-    #define portICCRPR_RUNNING_PRIORITY_REGISTER                 ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
+#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS       ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
+#define portICCPMR_PRIORITY_MASK_REGISTER                    ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
+#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS    ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
+#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS        ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
+#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS            ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
+#define portICCBPR_BINARY_POINT_REGISTER                     ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
+#define portICCRPR_RUNNING_PRIORITY_REGISTER                 ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
 
-    #define portMEMORY_BARRIER()    __asm volatile ( "" ::: "memory" )
+#define portMEMORY_BARRIER()    __asm volatile ( "" ::: "memory" )
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+    } /* extern C */
+#endif
+/* *INDENT-ON* */
 
 #endif /* PORTMACRO_H */