]> git.sur5r.net Git - freertos/commitdiff
Added portASSERT_IF_INTERRUPT_PRIORITY_INVALID() implementation to Cortex-M3 and...
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 4 Jul 2013 11:20:28 +0000 (11:20 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 4 Jul 2013 11:20:28 +0000 (11:20 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1965 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

15 files changed:
FreeRTOS/Source/include/FreeRTOS.h
FreeRTOS/Source/portable/GCC/ARM_CM3/port.c
FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h
FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h
FreeRTOS/Source/portable/IAR/ARM_CM3/port.c
FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h
FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c
FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h
FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c
FreeRTOS/Source/portable/RVDS/ARM_CM3/portmacro.h
FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c
FreeRTOS/Source/portable/RVDS/ARM_CM4F/portmacro.h
FreeRTOS/Source/queue.c
FreeRTOS/Source/tasks.c

index f6f4b2e8a05cec6a6cd5ea3d99eb33a2b76c2fc6..2f3d16ac2b72acddc5f5906d158087eec46e361a 100644 (file)
@@ -229,6 +229,9 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
 \r
 #ifndef configASSERT\r
        #define configASSERT( x )\r
+       #define configASSERT_DEFINED 0\r
+#else\r
+       #define configASSERT_DEFINED 1\r
 #endif\r
 \r
 /* The timers module relies on xTaskGetSchedulerState(). */\r
@@ -592,6 +595,10 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
        #define configINCLUDE_STATS_FORMATTING_FUNCTIONS 0\r
 #endif\r
 \r
+#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID\r
+       #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()\r
+#endif\r
+\r
 /* For backward compatability. */\r
 #define eTaskStateGet eTaskGetState\r
 \r
index e9acf2eaa96dce1fce07f0f396b0d99a5d771c4f..a3d652f12a9913903a00dce8d855cea63728a339 100644 (file)
@@ -107,6 +107,12 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
 #define portNVIC_PENDSV_PRI                                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )\r
 #define portNVIC_SYSTICK_PRI                           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )\r
 \r
+/* Constants required to check the validity of an interrupt prority. */\r
+#define portFIRST_USER_INTERRUPT_NUMBER                ( 16 )\r
+#define portNVIC_IP_REGISTERS_OFFSET_16        ( 0xE000E3F0 )\r
+#define portAIRCR_REG                                          ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )\r
+#define portPRIORITY_GROUP_MASK                                ( 0x07UL << 8UL )\r
+\r
 /* Constants required to set up the initial stack. */\r
 #define portINITIAL_XPSR                                       ( 0x01000000 )\r
 \r
@@ -166,6 +172,16 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
        static unsigned long ulStoppedTimerCompensation = 0;\r
 #endif /* configUSE_TICKLESS_IDLE */\r
 \r
+/*\r
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure \r
+ * FreeRTOS API functions are not called from interrupts that have been assigned\r
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+ */\r
+#if ( configASSERT_DEFINED == 1 )\r
+        static unsigned char ucMaxSysCallPriority = 0;\r
+        static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;\r
+#endif /* configASSERT_DEFINED */\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -231,6 +247,33 @@ portBASE_TYPE xPortStartScheduler( void )
        See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */\r
        configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );\r
 \r
+       #if( configASSERT_DEFINED == 1 )\r
+       {\r
+               volatile unsigned long ulOriginalPriority;\r
+               volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );\r
+\r
+               /* Determine the maximum priority from which ISR safe FreeRTOS API\r
+               functions can be called.  ISR safe functions are those that end in\r
+               "FromISR".  FreeRTOS maintains separate thread and ISR API functions to\r
+               ensure interrupt entry is as fast and simple as possible.\r
+\r
+               Save the interrupt priority value that is about to be clobbered. */\r
+               ulOriginalPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt\r
+               priority register. */\r
+               *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;\r
+\r
+               /* Read back the written priority to obtain its value as seen by the\r
+               hardware, which will only implement a subset of the priority bits. */\r
+               ucMaxSysCallPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Restore the clobbered interrupt priority register to its original\r
+               value. */\r
+               *pcFirstUserPriorityRegister = ulOriginalPriority;\r
+       }\r
+       #endif /* conifgASSERT_DEFINED */\r
+\r
        /* Make PendSV and SysTick the lowest priority interrupts. */\r
        portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
        portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
@@ -523,4 +566,81 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
        portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
+\r
+#if( configASSERT_DEFINED == 1 )\r
+\r
+       void vPortValidateInterruptPriority( void )\r
+       {\r
+       unsigned long ulCurrentInterrupt;\r
+       unsigned char ucCurrentPriority;\r
+\r
+               /* Obtain the number of the currently executing interrupt. */\r
+               __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );\r
+\r
+               /* Is the interrupt number a user defined interrupt? */\r
+               if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )\r
+               {\r
+                       /* Look up the interrupt's priority. */\r
+                       ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];\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
+                       Interrupts that use the FreeRTOS API must not be left at their\r
+                       default priority of     zero as that is the highest possible priority,\r
+                       which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, \r
+                       and     therefore also guaranteed to be invalid.  \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( ucCurrentPriority >= ucMaxSysCallPriority );\r
+               }\r
+\r
+               /* Priority grouping:  The interrupt controller (NVIC) 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
+               If CMSIS libraries are being used then the correct setting can be \r
+               achieved by calling     NVIC_SetPriorityGrouping( 0 ); before starting the \r
+               scheduler. */\r
+               configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );\r
+       }\r
+\r
+#endif /* configASSERT_DEFINED */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
 \r
index 7335aa2644d61c4e9f22e743a6fad35119a0f52e..def764e1c79329e9d88c897af2c43fc49995ed4c 100644 (file)
@@ -180,6 +180,13 @@ not necessary for to use this port.  They are defined so the common demo files
 \r
 /*-----------------------------------------------------------*/\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
 /* portNOP() is not required by this port. */\r
 #define portNOP()\r
 \r
index f3826b1df4a7056473e57f6edf9b2f544149e62c..7cb06899bca5e6f8188739ad97ca111038c93b3c 100644 (file)
 #define portNVIC_PENDSV_PRI                                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )\r
 #define portNVIC_SYSTICK_PRI                           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )\r
 \r
+/* Constants required to check the validity of an interrupt prority. */\r
+#define portFIRST_USER_INTERRUPT_NUMBER                ( 16 )\r
+#define portNVIC_IP_REGISTERS_OFFSET_16        ( 0xE000E3F0 )\r
+#define portAIRCR_REG                                          ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )\r
+#define portPRIORITY_GROUP_MASK                                ( 0x07UL << 8UL )\r
+\r
 /* Constants required to manipulate the VFP. */\r
 #define portFPCCR                                      ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */\r
 #define portASPEN_AND_LSPEN_BITS       ( 0x3UL << 30UL )\r
@@ -173,6 +179,16 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
        static unsigned long ulStoppedTimerCompensation = 0;\r
 #endif /* configUSE_TICKLESS_IDLE */\r
 \r
+/*\r
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure \r
+ * FreeRTOS API functions are not called from interrupts that have been assigned\r
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+ */\r
+#if ( configASSERT_DEFINED == 1 )\r
+        static unsigned char ucMaxSysCallPriority = 0;\r
+        static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;\r
+#endif /* configASSERT_DEFINED */\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -249,6 +265,33 @@ portBASE_TYPE xPortStartScheduler( void )
        See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */\r
        configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );\r
 \r
+       #if( configASSERT_DEFINED == 1 )\r
+       {\r
+               volatile unsigned long ulOriginalPriority;\r
+               volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );\r
+\r
+               /* Determine the maximum priority from which ISR safe FreeRTOS API\r
+               functions can be called.  ISR safe functions are those that end in\r
+               "FromISR".  FreeRTOS maintains separate thread and ISR API functions to\r
+               ensure interrupt entry is as fast and simple as possible.\r
+\r
+               Save the interrupt priority value that is about to be clobbered. */\r
+               ulOriginalPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt\r
+               priority register. */\r
+               *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;\r
+\r
+               /* Read back the written priority to obtain its value as seen by the\r
+               hardware, which will only implement a subset of the priority bits. */\r
+               ucMaxSysCallPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Restore the clobbered interrupt priority register to its original\r
+               value. */\r
+               *pcFirstUserPriorityRegister = ulOriginalPriority;\r
+       }\r
+       #endif /* conifgASSERT_DEFINED */\r
+\r
        /* Make PendSV and SysTick the lowest priority interrupts. */\r
        portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
        portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
@@ -572,4 +615,63 @@ static void vPortEnableVFP( void )
                "       bx r14                                          "\r
        );\r
 }\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configASSERT_DEFINED == 1 )\r
+\r
+       void vPortValidateInterruptPriority( void )\r
+       {\r
+       unsigned long ulCurrentInterrupt;\r
+       unsigned char ucCurrentPriority;\r
+\r
+               /* Obtain the number of the currently executing interrupt. */\r
+               __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );\r
+\r
+               /* Is the interrupt number a user defined interrupt? */\r
+               if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )\r
+               {\r
+                       /* Look up the interrupt's priority. */\r
+                       ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];\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
+                       Interrupts that use the FreeRTOS API must not be left at their\r
+                       default priority of     zero as that is the highest possible priority,\r
+                       which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, \r
+                       and     therefore also guaranteed to be invalid.  \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( ucCurrentPriority >= ucMaxSysCallPriority );\r
+               }\r
+\r
+               /* Priority grouping:  The interrupt controller (NVIC) 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
+               If CMSIS libraries are being used then the correct setting can be \r
+               achieved by calling     NVIC_SetPriorityGrouping( 0 ); before starting the \r
+               scheduler. */\r
+               configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );\r
+       }\r
+\r
+#endif /* configASSERT_DEFINED */\r
+\r
 \r
index 7d58e7b8244712c3090c74ee146ad588cb3664df..a006e45173621a7232ba145ddd1fe69065bda54c 100644 (file)
@@ -181,6 +181,13 @@ not necessary for to use this port.  They are defined so the common demo files
 \r
 /*-----------------------------------------------------------*/\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
 /* portNOP() is not required by this port. */\r
 #define portNOP()\r
 \r
index db8c1f117c763bab8e4847ebb8e2a06005b5e74d..c8fbfde428f076b128d1a47f29c79192cb03fdc6 100644 (file)
 #define portNVIC_PENDSV_PRI                                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )\r
 #define portNVIC_SYSTICK_PRI                           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )\r
 \r
+/* Constants required to check the validity of an interrupt prority. */\r
+#define portFIRST_USER_INTERRUPT_NUMBER                ( 16 )\r
+#define portNVIC_IP_REGISTERS_OFFSET_16        ( 0xE000E3F0 )\r
+#define portAIRCR_REG                                          ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )\r
+#define portPRIORITY_GROUP_MASK                                ( 0x07UL << 8UL )\r
+\r
 /* Constants required to set up the initial stack. */\r
 #define portINITIAL_XPSR                                       ( 0x01000000 )\r
 \r
@@ -171,6 +177,16 @@ extern void vPortStartFirstTask( void );
        static unsigned long ulStoppedTimerCompensation = 0;\r
 #endif /* configUSE_TICKLESS_IDLE */\r
 \r
+/*\r
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure \r
+ * FreeRTOS API functions are not called from interrupts that have been assigned\r
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+ */\r
+#if ( configASSERT_DEFINED == 1 )\r
+        static unsigned char ucMaxSysCallPriority = 0;\r
+        static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;\r
+#endif /* configASSERT_DEFINED */\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -199,6 +215,33 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
  */\r
 portBASE_TYPE xPortStartScheduler( void )\r
 {\r
+       #if( configASSERT_DEFINED == 1 )\r
+       {\r
+               volatile unsigned long ulOriginalPriority;\r
+               volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );\r
+\r
+               /* Determine the maximum priority from which ISR safe FreeRTOS API\r
+               functions can be called.  ISR safe functions are those that end in\r
+               "FromISR".  FreeRTOS maintains separate thread and ISR API functions to\r
+               ensure interrupt entry is as fast and simple as possible.\r
+\r
+               Save the interrupt priority value that is about to be clobbered. */\r
+               ulOriginalPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt\r
+               priority register. */\r
+               *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;\r
+\r
+               /* Read back the written priority to obtain its value as seen by the\r
+               hardware, which will only implement a subset of the priority bits. */\r
+               ucMaxSysCallPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Restore the clobbered interrupt priority register to its original\r
+               value. */\r
+               *pcFirstUserPriorityRegister = ulOriginalPriority;\r
+       }\r
+       #endif /* conifgASSERT_DEFINED */\r
+\r
        /* Make PendSV and SysTick the lowest priority interrupts. */\r
        portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
        portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
@@ -425,4 +468,81 @@ __weak void vPortSetupTimerInterrupt( void )
        portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
+\r
+#if( configASSERT_DEFINED == 1 )\r
+\r
+       void vPortValidateInterruptPriority( void )\r
+       {\r
+       unsigned long ulCurrentInterrupt;\r
+       unsigned char ucCurrentPriority;\r
+\r
+               /* Obtain the number of the currently executing interrupt. */\r
+               __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );\r
+\r
+               /* Is the interrupt number a user defined interrupt? */\r
+               if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )\r
+               {\r
+                       /* Look up the interrupt's priority. */\r
+                       ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];\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
+                       Interrupts that use the FreeRTOS API must not be left at their\r
+                       default priority of     zero as that is the highest possible priority,\r
+                       which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, \r
+                       and     therefore also guaranteed to be invalid.  \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( ucCurrentPriority >= ucMaxSysCallPriority );\r
+               }\r
+\r
+               /* Priority grouping:  The interrupt controller (NVIC) 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
+               If CMSIS libraries are being used then the correct setting can be \r
+               achieved by calling     NVIC_SetPriorityGrouping( 0 ); before starting the \r
+               scheduler. */\r
+               configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );\r
+       }\r
+\r
+#endif /* configASSERT_DEFINED */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
 \r
index ad36320601cbc358860a74ba391c6d518f413a17..396bddacb6bb7dbf272c35fb177003e4a3d77a83 100644 (file)
@@ -171,6 +171,13 @@ not necessary for to use this port.  They are defined so the common demo files
 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
 /*-----------------------------------------------------------*/\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
 /* portNOP() is not required by this port. */\r
 #define portNOP()\r
 \r
index 543cba3cce9e7fe6d7fe53a98c68a92a84f1bf81..e5a3658554183bbd85a65c433b0d70b194618317 100644 (file)
 #define portNVIC_PENDSV_PRI                                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )\r
 #define portNVIC_SYSTICK_PRI                           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )\r
 \r
+/* Constants required to check the validity of an interrupt prority. */\r
+#define portFIRST_USER_INTERRUPT_NUMBER                ( 16 )\r
+#define portNVIC_IP_REGISTERS_OFFSET_16        ( 0xE000E3F0 )\r
+#define portAIRCR_REG                                          ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )\r
+#define portPRIORITY_GROUP_MASK                                ( 0x07UL << 8UL )\r
+\r
 /* Constants required to manipulate the VFP. */\r
 #define portFPCCR                                                      ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */\r
 #define portASPEN_AND_LSPEN_BITS                       ( 0x3UL << 30UL )\r
@@ -179,6 +185,16 @@ extern void vPortEnableVFP( void );
        static unsigned long ulStoppedTimerCompensation = 0;\r
 #endif /* configUSE_TICKLESS_IDLE */\r
 \r
+/*\r
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure \r
+ * FreeRTOS API functions are not called from interrupts that have been assigned\r
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+ */\r
+#if ( configASSERT_DEFINED == 1 )\r
+        static unsigned char ucMaxSysCallPriority = 0;\r
+        static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;\r
+#endif /* configASSERT_DEFINED */\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -219,6 +235,33 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
  */\r
 portBASE_TYPE xPortStartScheduler( void )\r
 {\r
+       #if( configASSERT_DEFINED == 1 )\r
+       {\r
+               volatile unsigned long ulOriginalPriority;\r
+               volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );\r
+\r
+               /* Determine the maximum priority from which ISR safe FreeRTOS API\r
+               functions can be called.  ISR safe functions are those that end in\r
+               "FromISR".  FreeRTOS maintains separate thread and ISR API functions to\r
+               ensure interrupt entry is as fast and simple as possible.\r
+\r
+               Save the interrupt priority value that is about to be clobbered. */\r
+               ulOriginalPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt\r
+               priority register. */\r
+               *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;\r
+\r
+               /* Read back the written priority to obtain its value as seen by the\r
+               hardware, which will only implement a subset of the priority bits. */\r
+               ucMaxSysCallPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Restore the clobbered interrupt priority register to its original\r
+               value. */\r
+               *pcFirstUserPriorityRegister = ulOriginalPriority;\r
+       }\r
+       #endif /* conifgASSERT_DEFINED */\r
+\r
        /* Make PendSV and SysTick the lowest priority interrupts. */\r
        portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
        portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
@@ -451,4 +494,81 @@ __weak void vPortSetupTimerInterrupt( void )
        portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
+\r
+#if( configASSERT_DEFINED == 1 )\r
+\r
+       void vPortValidateInterruptPriority( void )\r
+       {\r
+       unsigned long ulCurrentInterrupt;\r
+       unsigned char ucCurrentPriority;\r
+\r
+               /* Obtain the number of the currently executing interrupt. */\r
+               __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );\r
+\r
+               /* Is the interrupt number a user defined interrupt? */\r
+               if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )\r
+               {\r
+                       /* Look up the interrupt's priority. */\r
+                       ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];\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
+                       Interrupts that use the FreeRTOS API must not be left at their\r
+                       default priority of     zero as that is the highest possible priority,\r
+                       which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, \r
+                       and     therefore also guaranteed to be invalid.  \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( ucCurrentPriority >= ucMaxSysCallPriority );\r
+               }\r
+\r
+               /* Priority grouping:  The interrupt controller (NVIC) 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
+               If CMSIS libraries are being used then the correct setting can be \r
+               achieved by calling     NVIC_SetPriorityGrouping( 0 ); before starting the \r
+               scheduler. */\r
+               configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );\r
+       }\r
+\r
+#endif /* configASSERT_DEFINED */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
 \r
index 8ef0e07245cbcc4bb2df6a8626a2a96ba1b51f7a..3d3be493fb0ca710b9f02bdf13c8a49809ab0550 100644 (file)
@@ -172,6 +172,13 @@ not necessary for to use this port.  They are defined so the common demo files
 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
 /*-----------------------------------------------------------*/\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
 /* portNOP() is not required by this port. */\r
 #define portNOP()\r
 \r
index 9254d62718f8fe4131eb8c11e044b683b4b72e37..8311f94c7f49be6239a6eb79ff8d0eabd88547f4 100644 (file)
@@ -117,6 +117,12 @@ is defined. */
 #define portNVIC_PENDSV_PRI                                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )\r
 #define portNVIC_SYSTICK_PRI                           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )\r
 \r
+/* Constants required to check the validity of an interrupt prority. */\r
+#define portFIRST_USER_INTERRUPT_NUMBER                ( 16 )\r
+#define portNVIC_IP_REGISTERS_OFFSET_16        ( 0xE000E3F0 )\r
+#define portAIRCR_REG                                          ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )\r
+#define portPRIORITY_GROUP_MASK                                ( 0x07UL << 8UL )\r
+\r
 /* Constants required to set up the initial stack. */\r
 #define portINITIAL_XPSR                       ( 0x01000000 )\r
 \r
@@ -179,6 +185,16 @@ static void prvStartFirstTask( void );
        static unsigned long ulStoppedTimerCompensation = 0;\r
 #endif /* configUSE_TICKLESS_IDLE */\r
 \r
+/*\r
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure \r
+ * FreeRTOS API functions are not called from interrupts that have been assigned\r
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+ */\r
+#if ( configASSERT_DEFINED == 1 )\r
+        static unsigned char ucMaxSysCallPriority = 0;\r
+        static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;\r
+#endif /* configASSERT_DEFINED */\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -241,6 +257,33 @@ __asm void prvStartFirstTask( void )
  */\r
 portBASE_TYPE xPortStartScheduler( void )\r
 {\r
+       #if( configASSERT_DEFINED == 1 )\r
+       {\r
+               volatile unsigned long ulOriginalPriority;\r
+               volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );\r
+\r
+               /* Determine the maximum priority from which ISR safe FreeRTOS API\r
+               functions can be called.  ISR safe functions are those that end in\r
+               "FromISR".  FreeRTOS maintains separate thread and ISR API functions to\r
+               ensure interrupt entry is as fast and simple as possible.\r
+\r
+               Save the interrupt priority value that is about to be clobbered. */\r
+               ulOriginalPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt\r
+               priority register. */\r
+               *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;\r
+\r
+               /* Read back the written priority to obtain its value as seen by the\r
+               hardware, which will only implement a subset of the priority bits. */\r
+               ucMaxSysCallPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Restore the clobbered interrupt priority register to its original\r
+               value. */\r
+               *pcFirstUserPriorityRegister = ulOriginalPriority;\r
+       }\r
+       #endif /* conifgASSERT_DEFINED */\r
+\r
        /* Make PendSV and SysTick the lowest priority interrupts. */\r
        portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
        portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
@@ -524,3 +567,72 @@ __asm void vPortClearInterruptMask( unsigned long ulNewMask )
        msr basepri, r0\r
        bx r14\r
 }\r
+/*-----------------------------------------------------------*/\r
+\r
+__asm unsigned long vPortGetIPSR( void )\r
+{\r
+       PRESERVE8\r
+       \r
+       mrs r0, ipsr\r
+       bx r14\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configASSERT_DEFINED == 1 )\r
+\r
+       void vPortValidateInterruptPriority( void )\r
+       {\r
+       unsigned long ulCurrentInterrupt;\r
+       unsigned char ucCurrentPriority;\r
+\r
+               /* Obtain the number of the currently executing interrupt. */\r
+               ulCurrentInterrupt = vPortGetIPSR();\r
+\r
+               /* Is the interrupt number a user defined interrupt? */\r
+               if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )\r
+               {\r
+                       /* Look up the interrupt's priority. */\r
+                       ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];\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
+                       Interrupts that use the FreeRTOS API must not be left at their\r
+                       default priority of     zero as that is the highest possible priority,\r
+                       which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, \r
+                       and     therefore also guaranteed to be invalid.  \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( ucCurrentPriority >= ucMaxSysCallPriority );\r
+               }\r
+\r
+               /* Priority grouping:  The interrupt controller (NVIC) 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
+               If CMSIS libraries are being used then the correct setting can be \r
+               achieved by calling     NVIC_SetPriorityGrouping( 0 ); before starting the \r
+               scheduler. */\r
+               configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );\r
+       }\r
+\r
+#endif /* configASSERT_DEFINED */\r
+\r
+\r
index 80a7b2f3fcd9227d7371eaa56ebc30ebd90846a9..8e35226573f276889deb489f4b0b7992ecd00508 100644 (file)
@@ -170,6 +170,13 @@ not necessary for to use this port.  They are defined so the common demo files
 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
 /*-----------------------------------------------------------*/\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
 /* portNOP() is not required by this port. */\r
 #define portNOP()\r
 \r
index 616a8330ba402ffa330c1f82851c1116e45819db..1877f9a160b604a3b09eca52d7106407f7bd8091 100644 (file)
@@ -117,6 +117,12 @@ is defined. */
 #define portNVIC_PENDSV_PRI                                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )\r
 #define portNVIC_SYSTICK_PRI                           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )\r
 \r
+/* Constants required to check the validity of an interrupt prority. */\r
+#define portFIRST_USER_INTERRUPT_NUMBER                ( 16 )\r
+#define portNVIC_IP_REGISTERS_OFFSET_16        ( 0xE000E3F0 )\r
+#define portAIRCR_REG                                          ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )\r
+#define portPRIORITY_GROUP_MASK                                ( 0x07UL << 8UL )\r
+\r
 /* Constants required to manipulate the VFP. */\r
 #define portFPCCR                                      ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */\r
 #define portASPEN_AND_LSPEN_BITS       ( 0x3UL << 30UL )\r
@@ -188,6 +194,16 @@ static void prvEnableVFP( void );
        static unsigned long ulStoppedTimerCompensation = 0;\r
 #endif /* configUSE_TICKLESS_IDLE */\r
 \r
+/*\r
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure \r
+ * FreeRTOS API functions are not called from interrupts that have been assigned\r
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+ */\r
+#if ( configASSERT_DEFINED == 1 )\r
+        static unsigned char ucMaxSysCallPriority = 0;\r
+        static const volatile unsigned char * const pcInterruptPriorityRegisters = ( unsigned char * ) portNVIC_IP_REGISTERS_OFFSET_16;\r
+#endif /* configASSERT_DEFINED */\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -279,6 +295,33 @@ __asm void prvEnableVFP( void )
  */\r
 portBASE_TYPE xPortStartScheduler( void )\r
 {\r
+       #if( configASSERT_DEFINED == 1 )\r
+       {\r
+               volatile unsigned long ulOriginalPriority;\r
+               volatile char * const pcFirstUserPriorityRegister = ( char * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );\r
+\r
+               /* Determine the maximum priority from which ISR safe FreeRTOS API\r
+               functions can be called.  ISR safe functions are those that end in\r
+               "FromISR".  FreeRTOS maintains separate thread and ISR API functions to\r
+               ensure interrupt entry is as fast and simple as possible.\r
+\r
+               Save the interrupt priority value that is about to be clobbered. */\r
+               ulOriginalPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt\r
+               priority register. */\r
+               *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;\r
+\r
+               /* Read back the written priority to obtain its value as seen by the\r
+               hardware, which will only implement a subset of the priority bits. */\r
+               ucMaxSysCallPriority = *pcFirstUserPriorityRegister;\r
+\r
+               /* Restore the clobbered interrupt priority register to its original\r
+               value. */\r
+               *pcFirstUserPriorityRegister = ulOriginalPriority;\r
+       }\r
+       #endif /* conifgASSERT_DEFINED */\r
+\r
        /* Make PendSV and SysTick the lowest priority interrupts. */\r
        portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
        portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
@@ -587,3 +630,72 @@ __asm void vPortClearInterruptMask( unsigned long ulNewMask )
        msr basepri, r0\r
        bx r14\r
 }\r
+/*-----------------------------------------------------------*/\r
+\r
+__asm unsigned long vPortGetIPSR( void )\r
+{\r
+       PRESERVE8\r
+       \r
+       mrs r0, ipsr\r
+       bx r14\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configASSERT_DEFINED == 1 )\r
+\r
+       void vPortValidateInterruptPriority( void )\r
+       {\r
+       unsigned long ulCurrentInterrupt;\r
+       unsigned char ucCurrentPriority;\r
+\r
+               /* Obtain the number of the currently executing interrupt. */\r
+               ulCurrentInterrupt = vPortGetIPSR();\r
+\r
+               /* Is the interrupt number a user defined interrupt? */\r
+               if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )\r
+               {\r
+                       /* Look up the interrupt's priority. */\r
+                       ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];\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
+                       Interrupts that use the FreeRTOS API must not be left at their\r
+                       default priority of     zero as that is the highest possible priority,\r
+                       which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, \r
+                       and     therefore also guaranteed to be invalid.  \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( ucCurrentPriority >= ucMaxSysCallPriority );\r
+               }\r
+\r
+               /* Priority grouping:  The interrupt controller (NVIC) 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
+               If CMSIS libraries are being used then the correct setting can be \r
+               achieved by calling     NVIC_SetPriorityGrouping( 0 ); before starting the \r
+               scheduler. */\r
+               configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );\r
+       }\r
+       \r
+#endif /* configASSERT_DEFINED */\r
+\r
+\r
index ef8fa625221c97fbe010cfb6042e3d91dddd6bb7..d2ab5a527fb0c7a777df72703dd9fa18b9aab60a 100644 (file)
@@ -171,6 +171,13 @@ not necessary for to use this port.  They are defined so the common demo files
 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
 /*-----------------------------------------------------------*/\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
 /* portNOP() is not required by this port. */\r
 #define portNOP()\r
 \r
index b9024d5354da203f0b1c4920fc1e882846f9f82f..ec665174b5df6cc07657336a091311859a046911 100644 (file)
@@ -940,6 +940,7 @@ xQUEUE *pxQueue;
        configASSERT( pxQueue );\r
        configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
        configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );\r
+       portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
 \r
        /* Similar to xQueueGenericSend, except we don't block if there is no room\r
        in the queue.  Also we don't directly wake a task that was blocked on a\r
@@ -1050,7 +1051,7 @@ xQUEUE *pxQueue;
                        the highest priority task wanting to access the queue. */\r
                        if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )\r
                        {\r
-                               /* Remember the read position in case the queue is only being \r
+                               /* Remember the read position in case the queue is only being\r
                                peeked. */\r
                                pcOriginalReadPosition = pxQueue->u.pcReadFrom;\r
 \r
@@ -1188,6 +1189,7 @@ xQUEUE *pxQueue;
        pxQueue = ( xQUEUE * ) xQueue;\r
        configASSERT( pxQueue );\r
        configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
+       portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
 \r
        uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
        {\r
@@ -1199,9 +1201,9 @@ xQUEUE *pxQueue;
                        prvCopyDataFromQueue( pxQueue, pvBuffer );\r
                        --( pxQueue->uxMessagesWaiting );\r
 \r
-                       /* If the queue is locked the event list will not be modified.  \r
-                       Instead update the lock count so the task that unlocks the queue \r
-                       will know that an ISR has removed data while the queue was \r
+                       /* If the queue is locked the event list will not be modified.\r
+                       Instead update the lock count so the task that unlocks the queue\r
+                       will know that an ISR has removed data while the queue was\r
                        locked. */\r
                        if( pxQueue->xRxLock == queueUNLOCKED )\r
                        {\r
@@ -1249,6 +1251,7 @@ xQUEUE *pxQueue;
        pxQueue = ( xQUEUE * ) xQueue;\r
        configASSERT( pxQueue );\r
        configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );\r
+       portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
 \r
        uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
        {\r
@@ -1388,9 +1391,9 @@ static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, port
                {\r
                        if( pxQueue->uxMessagesWaiting > 0 )\r
                        {\r
-                               /* An item is not being added but overwritten, so subtract \r
-                               one from the recorded number of items in the queue so when \r
-                               one is added again below the number of recorded items remains \r
+                               /* An item is not being added but overwritten, so subtract\r
+                               one from the recorded number of items in the queue so when\r
+                               one is added again below the number of recorded items remains\r
                                correct. */\r
                                --( pxQueue->uxMessagesWaiting );\r
                        }\r
index 83d9f09a36b72f61c56372817557928e48423214..dc4f6010782133ccd1f0e64ac2ceb03c0f46ef91 100644 (file)
@@ -1176,6 +1176,7 @@ tskTCB * pxNewTCB;
        unsigned portBASE_TYPE uxSavedInterruptStatus;\r
 \r
                configASSERT( xTaskToResume );\r
+               portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
 \r
                pxTCB = ( tskTCB * ) xTaskToResume;\r
 \r
@@ -1414,6 +1415,8 @@ portTickType xTaskGetTickCountFromISR( void )
 portTickType xReturn;\r
 unsigned portBASE_TYPE uxSavedInterruptStatus;\r
 \r
+       portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
+       \r
        uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
        xReturn = xTickCount;\r
        portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r