]> git.sur5r.net Git - freertos/commitdiff
Enhance heap_4.c to prevent blocks accidentally being freed twice, or blocks that...
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Tue, 9 Jul 2013 12:49:49 +0000 (12:49 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Tue, 9 Jul 2013 12:49:49 +0000 (12:49 +0000)
Update the Cortex-A9 port to include asserts if an ISR safe FreeRTOS function is called from an interrupt that has a higher logical priority than configMAX_SYSCALL_INTERRUPT_PRIORITY (or whatever the CA9 equivalent is called), and also assert if the binary point is not set correctly.

git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1967 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

FreeRTOS/Source/portable/IAR/ARM_CA9/port.c
FreeRTOS/Source/portable/IAR/ARM_CA9/portmacro.h
FreeRTOS/Source/portable/MemMang/heap_4.c
FreeRTOS/Source/portable/RVDS/ARM_CA9/port.c
FreeRTOS/Source/portable/RVDS/ARM_CA9/portmacro.h

index 1e731a21e254e49206f4fa1395eaf04541cca049..bca0137d15eb961f8256773fe0d852a32c624230 100644 (file)
@@ -143,6 +143,10 @@ context. */
 #define portINTERRUPT_ENABLE_BIT               ( 0x80UL )\r
 #define portTHUMB_MODE_ADDRESS                 ( 0x01UL )\r
 \r
+/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary\r
+point is zero. */\r
+#define portBINARY_POINT_BITS                  ( ( unsigned char ) 0x03 )\r
+\r
 /* Masks all bits in the APSR other than the mode bits. */\r
 #define portAPSR_MODE_BITS_MASK                        ( 0x1F )\r
 \r
@@ -177,11 +181,6 @@ 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. */\r
 volatile unsigned long ulCriticalNesting = 9999UL;\r
 \r
-/* The value to be written to the interrupt controllers priority mask register\r
-to mask interrupts that can use the FreeRTOS API without masking higher priority\r
-interrupts. */\r
-const unsigned long ulPortAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
-\r
 /* Saved as part of the task context.  If ulPortTaskHasFPUContext is non-zero then\r
 a floating point context must be saved and restored for the task. */\r
 unsigned long ulPortTaskHasFPUContext = pdFALSE;\r
@@ -193,6 +192,7 @@ unsigned long ulPortYieldRequired = pdFALSE;
 if the nesting depth is 0. */\r
 unsigned long ulPortInterruptNesting = 0UL;\r
 \r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -282,15 +282,24 @@ unsigned long ulAPSR;
 \r
        if( ulAPSR != portAPSR_USER_MODE )\r
        {\r
-               /* Start the timer that generates the tick ISR. */\r
-               configSETUP_TICK_INTERRUPT();\r
+               /* Only continue if the binary point value is set to its lowest possible\r
+               setting.  See the comments in vPortValidateInterruptPriority() below for\r
+               more information. */\r
+               configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );\r
 \r
-               __enable_irq();\r
-               vPortRestoreTaskContext();\r
+               if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )\r
+               {\r
+                       /* Start the timer that generates the tick ISR. */\r
+                       configSETUP_TICK_INTERRUPT();\r
+\r
+                       __enable_irq();\r
+                       vPortRestoreTaskContext();\r
+               }\r
        }\r
 \r
        /* Will only get here if xTaskStartScheduler() was called with the CPU in\r
-       a non-privileged mode. */\r
+       a non-privileged mode or the binary point register was not set to its lowest\r
+       possible value. */\r
        return 0;\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -340,7 +349,7 @@ void FreeRTOS_Tick_Handler( void )
        handler runs at the lowest priority, so interrupts cannot already be masked,\r
        so there is no need to save and restore the current mask value. */\r
        __disable_irq();\r
-       portICCPMR_PRIORITY_MASK_REGISTER = ulPortAPIPriorityMask;\r
+       portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
        __asm(  "DSB            \n"\r
                        "ISB            \n" );\r
        __enable_irq();\r
@@ -383,7 +392,7 @@ unsigned long ulPortSetInterruptMask( void )
 unsigned long ulReturn;\r
 \r
        __disable_irq();\r
-       if( portICCPMR_PRIORITY_MASK_REGISTER == ulPortAPIPriorityMask )\r
+       if( portICCPMR_PRIORITY_MASK_REGISTER == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )\r
        {\r
                /* Interrupts were already masked. */\r
                ulReturn = pdTRUE;\r
@@ -391,7 +400,7 @@ unsigned long ulReturn;
        else\r
        {\r
                ulReturn = pdFALSE;\r
-               portICCPMR_PRIORITY_MASK_REGISTER = ulPortAPIPriorityMask;\r
+               portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
                __asm(  "DSB            \n"\r
                                "ISB            \n" );\r
        }\r
@@ -399,5 +408,45 @@ unsigned long ulReturn;
 \r
        return ulReturn;\r
 }\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configASSERT_DEFINED == 1 )\r
+\r
+       void vPortValidateInterruptPriority( void )\r
+       {\r
+               /* The following assertion will fail if a service routine (ISR) for\r
+               an interrupt that has been assigned a priority above\r
+               configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API\r
+               function.  ISR safe FreeRTOS API functions must *only* be called\r
+               from interrupts that have been assigned a priority at or below\r
+               configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+\r
+               Numerically low interrupt priority numbers represent logically high\r
+               interrupt priorities, therefore the priority of the interrupt must\r
+               be set to a value equal to or numerically *higher* than\r
+               configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+\r
+               FreeRTOS maintains separate thread and ISR API functions to ensure\r
+               interrupt entry is as fast and simple as possible.\r
+\r
+               The following links provide detailed information:\r
+               http://www.freertos.org/RTOS-Cortex-M3-M4.html\r
+               http://www.freertos.org/FAQHelp.html */\r
+               configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );\r
+\r
+               /* Priority grouping:  The interrupt controller (GIC) allows the bits\r
+               that define each interrupt's priority to be split between bits that\r
+               define the interrupt's pre-emption priority bits and bits that define\r
+               the interrupt's sub-priority.  For simplicity all bits must be defined\r
+               to be pre-emption priority bits.  The following assertion will fail if\r
+               this is not the case (if some bits represent a sub-priority).\r
+\r
+               The priority grouping is configured by the GIC's binary point register\r
+               (ICCBPR).  Writting 0 to ICCBPR will ensure it is set to its lowest\r
+               possible value (which may be above 0). */\r
+               configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );\r
+       }\r
+\r
+#endif /* configASSERT_DEFINED */\r
 \r
 \r
index 5ce489c02427ebd56aee71c1e56634f0d4868b91..2f1f13d550ac8e99d35762f4a6939c08fe7971c0 100644 (file)
 \r
 /* IAR includes. */\r
 #ifdef __ICCARM__\r
+\r
        #include <intrinsics.h>\r
 \r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
+       #ifdef __cplusplus\r
+       extern "C" {\r
+       #endif\r
+\r
+       /*-----------------------------------------------------------\r
+        * Port specific definitions.\r
+        *\r
+        * The settings in this file configure FreeRTOS correctly for the given hardware\r
+        * and compiler.\r
+        *\r
+        * These settings should not be altered.\r
+        *-----------------------------------------------------------\r
+        */\r
+\r
+       /* Type definitions. */\r
+       #define portCHAR                char\r
+       #define portFLOAT               float\r
+       #define portDOUBLE              double\r
+       #define portLONG                long\r
+       #define portSHORT               short\r
+       #define portSTACK_TYPE  unsigned long\r
+       #define portBASE_TYPE   portLONG\r
+       typedef unsigned long portTickType;\r
+       #define portMAX_DELAY ( portTickType ) 0xffffffff\r
+\r
+       /*-----------------------------------------------------------*/\r
+\r
+       /* Hardware specifics. */\r
+       #define portSTACK_GROWTH                        ( -1 )\r
+       #define portTICK_RATE_MS                        ( ( portTickType ) 1000 / configTICK_RATE_HZ )\r
+       #define portBYTE_ALIGNMENT                      8\r
 \r
-/*-----------------------------------------------------------\r
- * Port specific definitions.\r
- *\r
- * The settings in this file configure FreeRTOS correctly for the given hardware\r
- * and compiler.\r
- *\r
- * These settings should not be altered.\r
- *-----------------------------------------------------------\r
- */\r
-\r
-/* Type definitions. */\r
-#define portCHAR               char\r
-#define portFLOAT              float\r
-#define portDOUBLE             double\r
-#define portLONG               long\r
-#define portSHORT              short\r
-#define portSTACK_TYPE unsigned long\r
-#define portBASE_TYPE  portLONG\r
-typedef unsigned long portTickType;\r
-#define portMAX_DELAY ( portTickType ) 0xffffffff\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/* Hardware specifics. */\r
-#define portSTACK_GROWTH                       ( -1 )\r
-#define portTICK_RATE_MS                       ( ( portTickType ) 1000 / configTICK_RATE_HZ )\r
-#define portBYTE_ALIGNMENT                     8\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/* Task utilities. */\r
-\r
-/* Called at the end of an ISR that can cause a context switch. */\r
-#define portEND_SWITCHING_ISR( xSwitchRequired )\\r
-{                                                                                              \\r
-extern unsigned long ulPortYieldRequired;              \\r
-                                                                                               \\r
-       if( xSwitchRequired != pdFALSE )                        \\r
-       {                                                                                       \\r
-               ulPortYieldRequired = pdTRUE;                   \\r
-       }                                                                                       \\r
-}\r
-\r
-#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )\r
-#define portYIELD() __asm( "SWI 0" );\r
-\r
-\r
-/*-----------------------------------------------------------\r
- * Critical section control\r
- *----------------------------------------------------------*/\r
-\r
-extern void vPortEnterCritical( void );\r
-extern void vPortExitCritical( void );\r
-extern unsigned long ulPortSetInterruptMask( void );\r
-extern void vPortClearInterruptMask( unsigned long ulNewMaskValue );\r
-\r
-/* These macros do not globally disable/enable interrupts.  They do mask off\r
-interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */\r
-#define portENTER_CRITICAL()           vPortEnterCritical();\r
-#define portEXIT_CRITICAL()                    vPortExitCritical();\r
-#define portDISABLE_INTERRUPTS()       ulPortSetInterruptMask()\r
-#define portENABLE_INTERRUPTS()                vPortClearInterruptMask( 0 )\r
-#define portSET_INTERRUPT_MASK_FROM_ISR()              ulPortSetInterruptMask()\r
-#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   vPortClearInterruptMask(x)\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/* Task function macros as described on the FreeRTOS.org WEB site.  These are\r
-not required for this port but included in case common demo code that uses these\r
-macros is used. */\r
-#define portTASK_FUNCTION_PROTO( vFunction, pvParameters )     void vFunction( void *pvParameters )\r
-#define portTASK_FUNCTION( vFunction, pvParameters )   void vFunction( void *pvParameters )\r
-\r
-/* Prototype of the FreeRTOS tick handler.  This must be installed as the\r
-handler for whichever peripheral is used to generate the RTOS tick. */\r
-void FreeRTOS_Tick_Handler( void );\r
-\r
-/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()\r
-before any floating point instructions are executed. */\r
-void vPortTaskUsesFPU( void );\r
-#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()\r
-\r
-#define portLOWEST_INTERRUPT_PRIORITY ( ( ( unsigned long ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )\r
-#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )\r
-\r
-/* Architecture specific optimisations. */\r
-#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1\r
-\r
-       /* Store/clear the ready priorities in a bit map. */\r
-       #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )\r
-       #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )\r
+       /*-----------------------------------------------------------*/\r
+\r
+       /* Task utilities. */\r
+\r
+       /* Called at the end of an ISR that can cause a context switch. */\r
+       #define portEND_SWITCHING_ISR( xSwitchRequired )\\r
+       {                                                                                               \\r
+       extern unsigned long ulPortYieldRequired;               \\r
+                                                                                                       \\r
+               if( xSwitchRequired != pdFALSE )                        \\r
+               {                                                                                       \\r
+                       ulPortYieldRequired = pdTRUE;                   \\r
+               }                                                                                       \\r
+       }\r
+\r
+       #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )\r
+       #define portYIELD() __asm( "SWI 0" );\r
+\r
+\r
+       /*-----------------------------------------------------------\r
+        * Critical section control\r
+        *----------------------------------------------------------*/\r
+\r
+       extern void vPortEnterCritical( void );\r
+       extern void vPortExitCritical( void );\r
+       extern unsigned long ulPortSetInterruptMask( void );\r
+       extern void vPortClearInterruptMask( unsigned long ulNewMaskValue );\r
+\r
+       /* These macros do not globally disable/enable interrupts.  They do mask off\r
+       interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */\r
+       #define portENTER_CRITICAL()            vPortEnterCritical();\r
+       #define portEXIT_CRITICAL()                     vPortExitCritical();\r
+       #define portDISABLE_INTERRUPTS()        ulPortSetInterruptMask()\r
+       #define portENABLE_INTERRUPTS()         vPortClearInterruptMask( 0 )\r
+       #define portSET_INTERRUPT_MASK_FROM_ISR()               ulPortSetInterruptMask()\r
+       #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)    vPortClearInterruptMask(x)\r
 \r
        /*-----------------------------------------------------------*/\r
 \r
-       #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( uxReadyPriorities ) )\r
+       /* Task function macros as described on the FreeRTOS.org WEB site.  These are\r
+       not required for this port but included in case common demo code that uses these\r
+       macros is used. */\r
+       #define portTASK_FUNCTION_PROTO( vFunction, pvParameters )      void vFunction( void *pvParameters )\r
+       #define portTASK_FUNCTION( vFunction, pvParameters )    void vFunction( void *pvParameters )\r
 \r
-#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
+       /* Prototype of the FreeRTOS tick handler.  This must be installed as the\r
+       handler for whichever peripheral is used to generate the RTOS tick. */\r
+       void FreeRTOS_Tick_Handler( void );\r
 \r
-#ifdef __cplusplus\r
-}\r
-#endif\r
+       /* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()\r
+       before any floating point instructions are executed. */\r
+       void vPortTaskUsesFPU( void );\r
+       #define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()\r
 \r
-#endif /* __ICCARM__ */\r
+       #define portLOWEST_INTERRUPT_PRIORITY ( ( ( unsigned long ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )\r
+       #define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )\r
+\r
+       /* Architecture specific optimisations. */\r
+       #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1\r
 \r
-#define portNOP() __asm volatile( "NOP" )\r
+               /* Store/clear the ready priorities in a bit map. */\r
+               #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )\r
+               #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )\r
+\r
+               /*-----------------------------------------------------------*/\r
+\r
+               #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( uxReadyPriorities ) )\r
+\r
+       #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
+\r
+       #ifdef configASSERT\r
+               void vPortValidateInterruptPriority( void );\r
+               #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()      vPortValidateInterruptPriority()\r
+       #else\r
+               #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()\r
+       #endif\r
+\r
+       #define portNOP() __asm volatile( "NOP" )\r
+\r
+\r
+       #ifdef __cplusplus\r
+       }\r
+       #endif\r
+\r
+#endif /* __ICCARM__ */\r
 \r
 \r
 /* The number of bits to shift for an interrupt priority is dependent on the\r
 number of bits implemented by the interrupt controller. */\r
 #if configUNIQUE_INTERRUPT_PRIORITIES == 16\r
        #define portPRIORITY_SHIFT 4\r
+       #define portMAX_BINARY_POINT_VALUE      3\r
 #elif configUNIQUE_INTERRUPT_PRIORITIES == 32\r
        #define portPRIORITY_SHIFT 3\r
+       #define portMAX_BINARY_POINT_VALUE      2\r
 #elif configUNIQUE_INTERRUPT_PRIORITIES == 64\r
        #define portPRIORITY_SHIFT 2\r
+       #define portMAX_BINARY_POINT_VALUE      1\r
 #elif configUNIQUE_INTERRUPT_PRIORITIES == 128\r
        #define portPRIORITY_SHIFT 1\r
+       #define portMAX_BINARY_POINT_VALUE      0\r
 #elif configUNIQUE_INTERRUPT_PRIORITIES == 256\r
        #define portPRIORITY_SHIFT 0\r
+       #define portMAX_BINARY_POINT_VALUE      0\r
 #else\r
        #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting.  configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware\r
 #endif\r
 \r
 /* Interrupt controller access addresses. */\r
-#define portICCPMR_PRIORITY_MASK_OFFSET  ( 0x04 )\r
-#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )\r
-#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )\r
-#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )\r
-#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile unsigned long * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )\r
-#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )\r
-#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )\r
-#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )\r
-\r
+#define portICCPMR_PRIORITY_MASK_OFFSET                                                ( 0x04 )\r
+#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET                                ( 0x0C )\r
+#define portICCEOIR_END_OF_INTERRUPT_OFFSET                                    ( 0x10 )\r
+#define portICCBPR_BINARY_POINT_OFFSET                                                 ( 0x08 )\r
+#define portICCRPR_RUNNING_PRIORITY_OFFSET                                             ( 0x14 )\r
+\r
+#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS                 ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )\r
+#define portICCPMR_PRIORITY_MASK_REGISTER                                      ( *( ( volatile unsigned char * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )\r
+#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS      ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )\r
+#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS          ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )\r
+#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS                      ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )\r
+#define portICCBPR_BINARY_POINT_REGISTER                                       ( *( ( const volatile unsigned long * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )\r
+#define portICCRPR_RUNNING_PRIORITY_REGISTER                           ( *( ( const volatile unsigned char * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )\r
 \r
 #endif /* PORTMACRO_H */\r
 \r
index b40229fb19f738c2ebcd13c2d198a053b2dbc1bd..d0d35a1a49d8ffdd198b4b05f4461d88d731e1df 100644 (file)
@@ -95,8 +95,11 @@ task.h is included from an application file. */
 /* Block sizes must not get too small. */\r
 #define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )\r
 \r
+/* Assumes 8bit bytes! */\r
+#define heapBITS_PER_BYTE              ( ( size_t ) 8 )\r
+\r
 /* A few bytes might be lost to byte aligning the heap start address. */\r
-#define configADJUSTED_HEAP_SIZE       ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )\r
+#define heapADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )\r
 \r
 /* Allocate the memory for the heap. */\r
 static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];\r
@@ -132,16 +135,20 @@ block must by correctly byte aligned. */
 static const unsigned short heapSTRUCT_SIZE    = ( ( sizeof ( xBlockLink ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK );\r
 \r
 /* Ensure the pxEnd pointer will end up on the correct byte alignment. */\r
-static const size_t xTotalHeapSize = ( ( size_t ) configADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );\r
+static const size_t xTotalHeapSize = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );\r
 \r
 /* Create a couple of list links to mark the start and end of the list. */\r
 static xBlockLink xStart, *pxEnd = NULL;\r
 \r
 /* Keeps track of the number of free bytes remaining, but says nothing about\r
 fragmentation. */\r
-static size_t xFreeBytesRemaining = ( ( size_t ) configADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );\r
+static size_t xFreeBytesRemaining = ( ( size_t ) heapADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK );\r
 \r
-/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */\r
+/* Gets set to the top bit of an size_t type.  When this bit in the xBlockSize \r
+member of an xBlockLink structure is set then the block belongs to the \r
+application.  When the bit is free the block is still part of the free heap\r
+space. */\r
+static size_t xBlockAllocatedBit = 0;\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -159,63 +166,77 @@ void *pvReturn = NULL;
                        prvHeapInit();\r
                }\r
 \r
-               /* The wanted size is increased so it can contain a xBlockLink\r
-               structure in addition to the requested amount of bytes. */\r
-               if( xWantedSize > 0 )\r
+               /* Check the requested block size is not so large that the top bit is\r
+               set.  The top bit of the block size member of the xBlockLink structure \r
+               is used to determine who owns the block - the application or the\r
+               kernel, so it must be free. */\r
+               if( ( xWantedSize & xBlockAllocatedBit ) == 0 )\r
                {\r
-                       xWantedSize += heapSTRUCT_SIZE;\r
-\r
-                       /* Ensure that blocks are always aligned to the required number of \r
-                       bytes. */\r
-                       if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )\r
+                       /* The wanted size is increased so it can contain a xBlockLink\r
+                       structure in addition to the requested amount of bytes. */\r
+                       if( xWantedSize > 0 )\r
                        {\r
-                               /* Byte alignment required. */\r
-                               xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );\r
-                       }\r
-               }\r
+                               xWantedSize += heapSTRUCT_SIZE;\r
 \r
-               if( ( xWantedSize > 0 ) && ( xWantedSize < xTotalHeapSize ) )\r
-               {\r
-                       /* Traverse the list from the start     (lowest address) block until one\r
-                       of adequate size is found. */\r
-                       pxPreviousBlock = &xStart;\r
-                       pxBlock = xStart.pxNextFreeBlock;\r
-                       while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )\r
-                       {\r
-                               pxPreviousBlock = pxBlock;\r
-                               pxBlock = pxBlock->pxNextFreeBlock;\r
+                               /* Ensure that blocks are always aligned to the required number \r
+                               of bytes. */\r
+                               if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )\r
+                               {\r
+                                       /* Byte alignment required. */\r
+                                       xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );\r
+                               }\r
                        }\r
 \r
-                       /* If the end marker was reached then a block of adequate size was\r
-                       not found. */\r
-                       if( pxBlock != pxEnd )\r
+                       if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )\r
                        {\r
-                               /* Return the memory space - jumping over the xBlockLink structure\r
-                               at its start. */\r
-                               pvReturn = ( void * ) ( ( ( unsigned char * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );\r
-\r
-                               /* This block is being returned for use so must be taken out of\r
-                               the     list of free blocks. */\r
-                               pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;\r
-\r
-                               /* If the block is larger than required it can be split into two. */\r
-                               if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )\r
+                               /* Traverse the list from the start     (lowest address) block until \r
+                               one     of adequate size is found. */\r
+                               pxPreviousBlock = &xStart;\r
+                               pxBlock = xStart.pxNextFreeBlock;\r
+                               while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )\r
                                {\r
-                                       /* This block is to be split into two.  Create a new block\r
-                                       following the number of bytes requested. The void cast is\r
-                                       used to prevent byte alignment warnings from the compiler. */\r
-                                       pxNewBlockLink = ( void * ) ( ( ( unsigned char * ) pxBlock ) + xWantedSize );\r
-\r
-                                       /* Calculate the sizes of two blocks split from the single\r
-                                       block. */\r
-                                       pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;\r
-                                       pxBlock->xBlockSize = xWantedSize;\r
-\r
-                                       /* Insert the new block into the list of free blocks. */\r
-                                       prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );\r
+                                       pxPreviousBlock = pxBlock;\r
+                                       pxBlock = pxBlock->pxNextFreeBlock;\r
                                }\r
 \r
-                               xFreeBytesRemaining -= pxBlock->xBlockSize;\r
+                               /* If the end marker was reached then a block of adequate size \r
+                               was     not found. */\r
+                               if( pxBlock != pxEnd )\r
+                               {\r
+                                       /* Return the memory space pointed to - jumping over the \r
+                                       xBlockLink structure at its start. */\r
+                                       pvReturn = ( void * ) ( ( ( unsigned char * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );\r
+\r
+                                       /* This block is being returned for use so must be taken out \r
+                                       of the list of free blocks. */\r
+                                       pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;\r
+\r
+                                       /* If the block is larger than required it can be split into \r
+                                       two. */\r
+                                       if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )\r
+                                       {\r
+                                               /* This block is to be split into two.  Create a new \r
+                                               block following the number of bytes requested. The void \r
+                                               cast is used to prevent byte alignment warnings from the \r
+                                               compiler. */\r
+                                               pxNewBlockLink = ( void * ) ( ( ( unsigned char * ) pxBlock ) + xWantedSize );\r
+\r
+                                               /* Calculate the sizes of two blocks split from the \r
+                                               single block. */\r
+                                               pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;\r
+                                               pxBlock->xBlockSize = xWantedSize;\r
+\r
+                                               /* Insert the new block into the list of free blocks. */\r
+                                               prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );\r
+                                       }\r
+\r
+                                       xFreeBytesRemaining -= pxBlock->xBlockSize;\r
+\r
+                                       /* The block is being returned - it is allocated and owned\r
+                                       by the application and has no "next" block. */\r
+                                       pxBlock->xBlockSize |= xBlockAllocatedBit;\r
+                                       pxBlock->pxNextFreeBlock = NULL;\r
+                               }\r
                        }\r
                }\r
        }\r
@@ -249,13 +270,27 @@ xBlockLink *pxLink;
                /* This casting is to keep the compiler from issuing warnings. */\r
                pxLink = ( void * ) puc;\r
 \r
-               vTaskSuspendAll();\r
+               /* Check the block is actually allocated. */\r
+               configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );\r
+               configASSERT( pxLink->pxNextFreeBlock == NULL );\r
+               \r
+               if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )\r
                {\r
-                       /* Add this block to the list of free blocks. */\r
-                       xFreeBytesRemaining += pxLink->xBlockSize;\r
-                       prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) );                      \r
+                       if( pxLink->pxNextFreeBlock == NULL )\r
+                       {\r
+                               /* The block is being returned to the heap - it is no longer\r
+                               allocated. */\r
+                               pxLink->xBlockSize &= ~xBlockAllocatedBit;\r
+\r
+                               vTaskSuspendAll();\r
+                               {\r
+                                       /* Add this block to the list of free blocks. */\r
+                                       xFreeBytesRemaining += pxLink->xBlockSize;\r
+                                       prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) );\r
+                               }\r
+                               xTaskResumeAll();\r
+                       }\r
                }\r
-               xTaskResumeAll();\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -302,6 +337,9 @@ unsigned char *pucHeapEnd, *pucAlignedHeap;
 \r
        /* The heap now contains pxEnd. */\r
        xFreeBytesRemaining -= heapSTRUCT_SIZE;\r
+\r
+       /* Work out the position of the top bit in a size_t variable. */\r
+       xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
index fbcb527598b55b89818ed2e6ded6876d3f9ef687..4737f62fff9cf7d9889d072973359b0031e7be06 100644 (file)
 number of bits implemented by the interrupt controller. */\r
 #if configUNIQUE_INTERRUPT_PRIORITIES == 16\r
        #define portPRIORITY_SHIFT 4\r
+       #define portMAX_BINARY_POINT_VALUE      3\r
 #elif configUNIQUE_INTERRUPT_PRIORITIES == 32\r
        #define portPRIORITY_SHIFT 3\r
+       #define portMAX_BINARY_POINT_VALUE      2\r
 #elif configUNIQUE_INTERRUPT_PRIORITIES == 64\r
        #define portPRIORITY_SHIFT 2\r
+       #define portMAX_BINARY_POINT_VALUE      1\r
 #elif configUNIQUE_INTERRUPT_PRIORITIES == 128\r
        #define portPRIORITY_SHIFT 1\r
+       #define portMAX_BINARY_POINT_VALUE      0\r
 #elif configUNIQUE_INTERRUPT_PRIORITIES == 256\r
        #define portPRIORITY_SHIFT 0\r
+       #define portMAX_BINARY_POINT_VALUE      0\r
 #else\r
        #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting.  configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware\r
 #endif\r
@@ -151,14 +156,22 @@ context. */
 #define portNO_FLOATING_POINT_CONTEXT  ( ( portSTACK_TYPE ) 0 )\r
 \r
 /* Interrupt controller access addresses. */\r
-#define portICCPMR_PRIORITY_MASK_OFFSET  ( 0x04 )\r
+#define portICCPMR_PRIORITY_MASK_OFFSET                ( 0x04 )\r
 #define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )\r
-#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )\r
-#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )\r
-#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile unsigned long * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )\r
-#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )\r
-#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )\r
-#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )\r
+#define portICCEOIR_END_OF_INTERRUPT_OFFSET    ( 0x10 )\r
+#define portICCBPR_BINARY_POINT_OFFSET                 ( 0x08 )\r
+#define portICCRPR_RUNNING_PRIORITY_OFFSET             ( 0x14 )\r
+#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS                 ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )\r
+#define portICCPMR_PRIORITY_MASK_REGISTER                                      ( *( ( volatile unsigned long * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )\r
+#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS      ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )\r
+#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS          ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )\r
+#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS                      ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )\r
+#define portICCBPR_BINARY_POINT_REGISTER                                       ( *( ( const volatile unsigned long * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )\r
+#define portICCRPR_RUNNING_PRIORITY_REGISTER                           ( *( ( const volatile unsigned char * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )\r
+\r
+/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary\r
+point is zero. */\r
+#define portBINARY_POINT_BITS                  ( ( unsigned char ) 0x03 )\r
 \r
 /* Constants required to setup the initial task context. */\r
 #define portINITIAL_SPSR                               ( ( portSTACK_TYPE ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */\r
@@ -200,11 +213,6 @@ 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. */\r
 volatile unsigned long ulCriticalNesting = 9999UL;\r
 \r
-/* The value to be written to the interrupt controllers priority mask register\r
-to mask interrupts that can use the FreeRTOS API without masking higher priority\r
-interrupts. */\r
-const unsigned long ulPortAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
-\r
 /* Used to pass constants into the ASM code.  The address at which variables are\r
 placed is the constant value so indirect loads in the asm code are not\r
 required. */\r
@@ -313,15 +321,24 @@ unsigned long ulAPSR;
 \r
        if( ulAPSR != portAPSR_USER_MODE )\r
        {\r
-               /* Start the timer that generates the tick ISR. */\r
-               configSETUP_TICK_INTERRUPT();\r
-\r
-               __enable_irq();\r
-               vPortRestoreTaskContext();\r
+               /* Only continue if the binary point value is set to its lowest possible\r
+               setting.  See the comments in vPortValidateInterruptPriority() below for\r
+               more information. */\r
+               configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );\r
+               \r
+               if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )\r
+               {       \r
+                       /* Start the timer that generates the tick ISR. */\r
+                       configSETUP_TICK_INTERRUPT();\r
+\r
+                       __enable_irq();\r
+                       vPortRestoreTaskContext();\r
+               }\r
        }\r
 \r
        /* Will only get here if xTaskStartScheduler() was called with the CPU in\r
-       a non-privileged mode. */\r
+       a non-privileged mode or the binary point register was not set to its lowest\r
+       possible value. */\r
        return 0;\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -371,7 +388,7 @@ void FreeRTOS_Tick_Handler( void )
        handler runs at the lowest priority, so interrupts cannot already be masked,\r
        so there is no need to save and restore the current mask value. */\r
        __disable_irq();\r
-       portICCPMR_PRIORITY_MASK_REGISTER = ulPortAPIPriorityMask;\r
+       portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
        __asm(  "DSB            \n"\r
                        "ISB            \n" );\r
        __enable_irq();\r
@@ -414,7 +431,7 @@ unsigned long ulPortSetInterruptMask( void )
 unsigned long ulReturn;\r
 \r
        __disable_irq();\r
-       if( portICCPMR_PRIORITY_MASK_REGISTER == ulPortAPIPriorityMask )\r
+       if( portICCPMR_PRIORITY_MASK_REGISTER == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )\r
        {\r
                /* Interrupts were already masked. */\r
                ulReturn = pdTRUE;\r
@@ -422,7 +439,7 @@ unsigned long ulReturn;
        else\r
        {\r
                ulReturn = pdFALSE;\r
-               portICCPMR_PRIORITY_MASK_REGISTER = ulPortAPIPriorityMask;\r
+               portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
                __asm(  "DSB            \n"\r
                                "ISB            \n" );\r
        }\r
@@ -430,5 +447,47 @@ unsigned long ulReturn;
 \r
        return ulReturn;\r
 }\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configASSERT_DEFINED == 1 )\r
+\r
+       void vPortValidateInterruptPriority( void )\r
+       {\r
+               /* The following assertion will fail if a service routine (ISR) for\r
+               an interrupt that has been assigned a priority above\r
+               configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API\r
+               function.  ISR safe FreeRTOS API functions must *only* be called\r
+               from interrupts that have been assigned a priority at or below\r
+               configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+\r
+               Numerically low interrupt priority numbers represent logically high\r
+               interrupt priorities, therefore the priority of the interrupt must\r
+               be set to a value equal to or numerically *higher* than\r
+               configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+\r
+               FreeRTOS maintains separate thread and ISR API functions to ensure\r
+               interrupt entry is as fast and simple as possible.\r
+\r
+               The following links provide detailed information:\r
+               http://www.freertos.org/RTOS-Cortex-M3-M4.html\r
+               http://www.freertos.org/FAQHelp.html */\r
+               configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );\r
+\r
+               /* Priority grouping:  The interrupt controller (GIC) allows the bits\r
+               that define each interrupt's priority to be split between bits that\r
+               define the interrupt's pre-emption priority bits and bits that define\r
+               the interrupt's sub-priority.  For simplicity all bits must be defined\r
+               to be pre-emption priority bits.  The following assertion will fail if\r
+               this is not the case (if some bits represent a sub-priority).\r
+\r
+               The priority grouping is configured by the GIC's binary point register\r
+               (ICCBPR).  Writting 0 to ICCBPR will ensure it is set to its lowest\r
+               possible value (which may be above 0). */\r
+               configASSERT( portICCBPR_BINARY_POINT_REGISTER <= portMAX_BINARY_POINT_VALUE );\r
+       }\r
+\r
+#endif /* configASSERT_DEFINED */\r
+\r
+\r
 \r
 \r
index 8c177cd0723587f034d2af53aa0f9bb35401bb18..39bd25fdf64764a6543cea5d3a8f2a107bc70862 100644 (file)
@@ -182,6 +182,13 @@ void vPortTaskUsesFPU( void );
 \r
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
 \r
+#ifdef configASSERT\r
+       void vPortValidateInterruptPriority( void );\r
+       #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()      vPortValidateInterruptPriority()\r
+#else\r
+       #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()\r
+#endif\r
+\r
 #define portNOP() __nop()\r
 \r
 #ifdef __cplusplus\r