summaryrefslogtreecommitdiff
path: root/FreeRTOS/Source/portable
diff options
context:
space:
mode:
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2013-07-04 11:20:28 +0000
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2013-07-04 11:20:28 +0000
commit03ddb80a20e723631c54fa1c01a70f8d2806f541 (patch)
tree26a52035eed459783742083160d6135d30af66b1 /FreeRTOS/Source/portable
parentcf20d8ab394f87e350c90c3c9f6a3dd990772734 (diff)
downloadfreertos-03ddb80a20e723631c54fa1c01a70f8d2806f541.tar.gz
Added portASSERT_IF_INTERRUPT_PRIORITY_INVALID() implementation to Cortex-M3 and Cortex-M4F ports.
git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@1965 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
Diffstat (limited to 'FreeRTOS/Source/portable')
-rw-r--r--FreeRTOS/Source/portable/GCC/ARM_CM3/port.c120
-rw-r--r--FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h7
-rw-r--r--FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c102
-rw-r--r--FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h7
-rw-r--r--FreeRTOS/Source/portable/IAR/ARM_CM3/port.c120
-rw-r--r--FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h7
-rw-r--r--FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c120
-rw-r--r--FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h7
-rw-r--r--FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c112
-rw-r--r--FreeRTOS/Source/portable/RVDS/ARM_CM3/portmacro.h7
-rw-r--r--FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c112
-rw-r--r--FreeRTOS/Source/portable/RVDS/ARM_CM4F/portmacro.h7
12 files changed, 728 insertions, 0 deletions
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c
index e9acf2eaa..a3d652f12 100644
--- a/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c
+++ b/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c
@@ -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 )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
+/* Constants required to check the validity of an interrupt prority. */
+#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
+#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
+#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
+#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
+
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 )
@@ -166,6 +172,16 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
static unsigned long ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
+/*
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
+ * FreeRTOS API functions are not called from interrupts that have been assigned
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
+ */
+#if ( configASSERT_DEFINED == 1 )
+ static unsigned char ucMaxSysCallPriority = 0;
+ static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
+#endif /* configASSERT_DEFINED */
+
/*-----------------------------------------------------------*/
/*
@@ -231,6 +247,33 @@ portBASE_TYPE xPortStartScheduler( void )
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
+ #if( configASSERT_DEFINED == 1 )
+ {
+ volatile unsigned long ulOriginalPriority;
+ volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
+
+ /* Determine the maximum priority from which ISR safe FreeRTOS API
+ functions can be called. ISR safe functions are those that end in
+ "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+ ensure interrupt entry is as fast and simple as possible.
+
+ Save the interrupt priority value that is about to be clobbered. */
+ ulOriginalPriority = *pcFirstUserPriorityRegister;
+
+ /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
+ priority register. */
+ *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
+
+ /* Read back the written priority to obtain its value as seen by the
+ hardware, which will only implement a subset of the priority bits. */
+ ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
+
+ /* Restore the clobbered interrupt priority register to its original
+ value. */
+ *pcFirstUserPriorityRegister = ulOriginalPriority;
+ }
+ #endif /* conifgASSERT_DEFINED */
+
/* Make PendSV and SysTick the lowest priority interrupts. */
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
@@ -524,3 +567,80 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
}
/*-----------------------------------------------------------*/
+#if( configASSERT_DEFINED == 1 )
+
+ void vPortValidateInterruptPriority( void )
+ {
+ unsigned long ulCurrentInterrupt;
+ unsigned char ucCurrentPriority;
+
+ /* Obtain the number of the currently executing interrupt. */
+ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
+
+ /* Is the interrupt number a user defined interrupt? */
+ if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
+ {
+ /* Look up the interrupt's priority. */
+ ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
+
+ /* The following assertion will fail if a service routine (ISR) for
+ an interrupt that has been assigned a priority above
+ configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
+ function. ISR safe FreeRTOS API functions must *only* be called
+ from interrupts that have been assigned a priority at or below
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Numerically low interrupt priority numbers represent logically high
+ interrupt priorities, therefore the priority of the interrupt must
+ be set to a value equal to or numerically *higher* than
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Interrupts that use the FreeRTOS API must not be left at their
+ default priority of zero as that is the highest possible priority,
+ which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
+ and therefore also guaranteed to be invalid.
+
+ FreeRTOS maintains separate thread and ISR API functions to ensure
+ interrupt entry is as fast and simple as possible.
+
+ The following links provide detailed information:
+ http://www.freertos.org/RTOS-Cortex-M3-M4.html
+ http://www.freertos.org/FAQHelp.html */
+ configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
+ }
+
+ /* Priority grouping: The interrupt controller (NVIC) allows the bits
+ that define each interrupt's priority to be split between bits that
+ define the interrupt's pre-emption priority bits and bits that define
+ the interrupt's sub-priority. For simplicity all bits must be defined
+ to be pre-emption priority bits. The following assertion will fail if
+ this is not the case (if some bits represent a sub-priority).
+
+ If CMSIS libraries are being used then the correct setting can be
+ achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
+ scheduler. */
+ configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
+ }
+
+#endif /* configASSERT_DEFINED */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h b/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h
index 7335aa264..def764e1c 100644
--- a/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h
+++ b/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h
@@ -180,6 +180,13 @@ not necessary for to use this port. They are defined so the common demo files
/*-----------------------------------------------------------*/
+#ifdef configASSERT
+ void vPortValidateInterruptPriority( void );
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
+#else
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
+#endif
+
/* portNOP() is not required by this port. */
#define portNOP()
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
index f3826b1df..7cb06899b 100644
--- a/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
+++ b/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
@@ -104,6 +104,12 @@
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
+/* Constants required to check the validity of an interrupt prority. */
+#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
+#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
+#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
+#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
+
/* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
@@ -173,6 +179,16 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
static unsigned long ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
+/*
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
+ * FreeRTOS API functions are not called from interrupts that have been assigned
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
+ */
+#if ( configASSERT_DEFINED == 1 )
+ static unsigned char ucMaxSysCallPriority = 0;
+ static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
+#endif /* configASSERT_DEFINED */
+
/*-----------------------------------------------------------*/
/*
@@ -249,6 +265,33 @@ portBASE_TYPE xPortStartScheduler( void )
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
+ #if( configASSERT_DEFINED == 1 )
+ {
+ volatile unsigned long ulOriginalPriority;
+ volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
+
+ /* Determine the maximum priority from which ISR safe FreeRTOS API
+ functions can be called. ISR safe functions are those that end in
+ "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+ ensure interrupt entry is as fast and simple as possible.
+
+ Save the interrupt priority value that is about to be clobbered. */
+ ulOriginalPriority = *pcFirstUserPriorityRegister;
+
+ /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
+ priority register. */
+ *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
+
+ /* Read back the written priority to obtain its value as seen by the
+ hardware, which will only implement a subset of the priority bits. */
+ ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
+
+ /* Restore the clobbered interrupt priority register to its original
+ value. */
+ *pcFirstUserPriorityRegister = ulOriginalPriority;
+ }
+ #endif /* conifgASSERT_DEFINED */
+
/* Make PendSV and SysTick the lowest priority interrupts. */
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
@@ -572,4 +615,63 @@ static void vPortEnableVFP( void )
" bx r14 "
);
}
+/*-----------------------------------------------------------*/
+
+#if( configASSERT_DEFINED == 1 )
+
+ void vPortValidateInterruptPriority( void )
+ {
+ unsigned long ulCurrentInterrupt;
+ unsigned char ucCurrentPriority;
+
+ /* Obtain the number of the currently executing interrupt. */
+ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
+
+ /* Is the interrupt number a user defined interrupt? */
+ if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
+ {
+ /* Look up the interrupt's priority. */
+ ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
+
+ /* The following assertion will fail if a service routine (ISR) for
+ an interrupt that has been assigned a priority above
+ configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
+ function. ISR safe FreeRTOS API functions must *only* be called
+ from interrupts that have been assigned a priority at or below
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Numerically low interrupt priority numbers represent logically high
+ interrupt priorities, therefore the priority of the interrupt must
+ be set to a value equal to or numerically *higher* than
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Interrupts that use the FreeRTOS API must not be left at their
+ default priority of zero as that is the highest possible priority,
+ which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
+ and therefore also guaranteed to be invalid.
+
+ FreeRTOS maintains separate thread and ISR API functions to ensure
+ interrupt entry is as fast and simple as possible.
+
+ The following links provide detailed information:
+ http://www.freertos.org/RTOS-Cortex-M3-M4.html
+ http://www.freertos.org/FAQHelp.html */
+ configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
+ }
+
+ /* Priority grouping: The interrupt controller (NVIC) allows the bits
+ that define each interrupt's priority to be split between bits that
+ define the interrupt's pre-emption priority bits and bits that define
+ the interrupt's sub-priority. For simplicity all bits must be defined
+ to be pre-emption priority bits. The following assertion will fail if
+ this is not the case (if some bits represent a sub-priority).
+
+ If CMSIS libraries are being used then the correct setting can be
+ achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
+ scheduler. */
+ configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
+ }
+
+#endif /* configASSERT_DEFINED */
+
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h b/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h
index 7d58e7b82..a006e4517 100644
--- a/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h
+++ b/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h
@@ -181,6 +181,13 @@ not necessary for to use this port. They are defined so the common demo files
/*-----------------------------------------------------------*/
+#ifdef configASSERT
+ void vPortValidateInterruptPriority( void );
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
+#else
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
+#endif
+
/* portNOP() is not required by this port. */
#define portNOP()
diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c
index db8c1f117..c8fbfde42 100644
--- a/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c
+++ b/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c
@@ -107,6 +107,12 @@
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
+/* Constants required to check the validity of an interrupt prority. */
+#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
+#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
+#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
+#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
+
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 )
@@ -171,6 +177,16 @@ extern void vPortStartFirstTask( void );
static unsigned long ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
+/*
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
+ * FreeRTOS API functions are not called from interrupts that have been assigned
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
+ */
+#if ( configASSERT_DEFINED == 1 )
+ static unsigned char ucMaxSysCallPriority = 0;
+ static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
+#endif /* configASSERT_DEFINED */
+
/*-----------------------------------------------------------*/
/*
@@ -199,6 +215,33 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
*/
portBASE_TYPE xPortStartScheduler( void )
{
+ #if( configASSERT_DEFINED == 1 )
+ {
+ volatile unsigned long ulOriginalPriority;
+ volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
+
+ /* Determine the maximum priority from which ISR safe FreeRTOS API
+ functions can be called. ISR safe functions are those that end in
+ "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+ ensure interrupt entry is as fast and simple as possible.
+
+ Save the interrupt priority value that is about to be clobbered. */
+ ulOriginalPriority = *pcFirstUserPriorityRegister;
+
+ /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
+ priority register. */
+ *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
+
+ /* Read back the written priority to obtain its value as seen by the
+ hardware, which will only implement a subset of the priority bits. */
+ ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
+
+ /* Restore the clobbered interrupt priority register to its original
+ value. */
+ *pcFirstUserPriorityRegister = ulOriginalPriority;
+ }
+ #endif /* conifgASSERT_DEFINED */
+
/* Make PendSV and SysTick the lowest priority interrupts. */
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
@@ -426,3 +469,80 @@ __weak void vPortSetupTimerInterrupt( void )
}
/*-----------------------------------------------------------*/
+#if( configASSERT_DEFINED == 1 )
+
+ void vPortValidateInterruptPriority( void )
+ {
+ unsigned long ulCurrentInterrupt;
+ unsigned char ucCurrentPriority;
+
+ /* Obtain the number of the currently executing interrupt. */
+ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
+
+ /* Is the interrupt number a user defined interrupt? */
+ if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
+ {
+ /* Look up the interrupt's priority. */
+ ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
+
+ /* The following assertion will fail if a service routine (ISR) for
+ an interrupt that has been assigned a priority above
+ configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
+ function. ISR safe FreeRTOS API functions must *only* be called
+ from interrupts that have been assigned a priority at or below
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Numerically low interrupt priority numbers represent logically high
+ interrupt priorities, therefore the priority of the interrupt must
+ be set to a value equal to or numerically *higher* than
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Interrupts that use the FreeRTOS API must not be left at their
+ default priority of zero as that is the highest possible priority,
+ which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
+ and therefore also guaranteed to be invalid.
+
+ FreeRTOS maintains separate thread and ISR API functions to ensure
+ interrupt entry is as fast and simple as possible.
+
+ The following links provide detailed information:
+ http://www.freertos.org/RTOS-Cortex-M3-M4.html
+ http://www.freertos.org/FAQHelp.html */
+ configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
+ }
+
+ /* Priority grouping: The interrupt controller (NVIC) allows the bits
+ that define each interrupt's priority to be split between bits that
+ define the interrupt's pre-emption priority bits and bits that define
+ the interrupt's sub-priority. For simplicity all bits must be defined
+ to be pre-emption priority bits. The following assertion will fail if
+ this is not the case (if some bits represent a sub-priority).
+
+ If CMSIS libraries are being used then the correct setting can be
+ achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
+ scheduler. */
+ configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
+ }
+
+#endif /* configASSERT_DEFINED */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h b/FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h
index ad3632060..396bddacb 100644
--- a/FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h
+++ b/FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h
@@ -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 )
/*-----------------------------------------------------------*/
+#ifdef configASSERT
+ void vPortValidateInterruptPriority( void );
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
+#else
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
+#endif
+
/* portNOP() is not required by this port. */
#define portNOP()
diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c
index 543cba3cc..e5a365855 100644
--- a/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c
+++ b/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c
@@ -111,6 +111,12 @@
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
+/* Constants required to check the validity of an interrupt prority. */
+#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
+#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
+#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
+#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
+
/* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
@@ -179,6 +185,16 @@ extern void vPortEnableVFP( void );
static unsigned long ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
+/*
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
+ * FreeRTOS API functions are not called from interrupts that have been assigned
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
+ */
+#if ( configASSERT_DEFINED == 1 )
+ static unsigned char ucMaxSysCallPriority = 0;
+ static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
+#endif /* configASSERT_DEFINED */
+
/*-----------------------------------------------------------*/
/*
@@ -219,6 +235,33 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
*/
portBASE_TYPE xPortStartScheduler( void )
{
+ #if( configASSERT_DEFINED == 1 )
+ {
+ volatile unsigned long ulOriginalPriority;
+ volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
+
+ /* Determine the maximum priority from which ISR safe FreeRTOS API
+ functions can be called. ISR safe functions are those that end in
+ "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+ ensure interrupt entry is as fast and simple as possible.
+
+ Save the interrupt priority value that is about to be clobbered. */
+ ulOriginalPriority = *pcFirstUserPriorityRegister;
+
+ /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
+ priority register. */
+ *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
+
+ /* Read back the written priority to obtain its value as seen by the
+ hardware, which will only implement a subset of the priority bits. */
+ ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
+
+ /* Restore the clobbered interrupt priority register to its original
+ value. */
+ *pcFirstUserPriorityRegister = ulOriginalPriority;
+ }
+ #endif /* conifgASSERT_DEFINED */
+
/* Make PendSV and SysTick the lowest priority interrupts. */
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
@@ -452,3 +495,80 @@ __weak void vPortSetupTimerInterrupt( void )
}
/*-----------------------------------------------------------*/
+#if( configASSERT_DEFINED == 1 )
+
+ void vPortValidateInterruptPriority( void )
+ {
+ unsigned long ulCurrentInterrupt;
+ unsigned char ucCurrentPriority;
+
+ /* Obtain the number of the currently executing interrupt. */
+ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
+
+ /* Is the interrupt number a user defined interrupt? */
+ if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
+ {
+ /* Look up the interrupt's priority. */
+ ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
+
+ /* The following assertion will fail if a service routine (ISR) for
+ an interrupt that has been assigned a priority above
+ configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
+ function. ISR safe FreeRTOS API functions must *only* be called
+ from interrupts that have been assigned a priority at or below
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Numerically low interrupt priority numbers represent logically high
+ interrupt priorities, therefore the priority of the interrupt must
+ be set to a value equal to or numerically *higher* than
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Interrupts that use the FreeRTOS API must not be left at their
+ default priority of zero as that is the highest possible priority,
+ which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
+ and therefore also guaranteed to be invalid.
+
+ FreeRTOS maintains separate thread and ISR API functions to ensure
+ interrupt entry is as fast and simple as possible.
+
+ The following links provide detailed information:
+ http://www.freertos.org/RTOS-Cortex-M3-M4.html
+ http://www.freertos.org/FAQHelp.html */
+ configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
+ }
+
+ /* Priority grouping: The interrupt controller (NVIC) allows the bits
+ that define each interrupt's priority to be split between bits that
+ define the interrupt's pre-emption priority bits and bits that define
+ the interrupt's sub-priority. For simplicity all bits must be defined
+ to be pre-emption priority bits. The following assertion will fail if
+ this is not the case (if some bits represent a sub-priority).
+
+ If CMSIS libraries are being used then the correct setting can be
+ achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
+ scheduler. */
+ configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
+ }
+
+#endif /* configASSERT_DEFINED */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h b/FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h
index 8ef0e0724..3d3be493f 100644
--- a/FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h
+++ b/FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h
@@ -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 )
/*-----------------------------------------------------------*/
+#ifdef configASSERT
+ void vPortValidateInterruptPriority( void );
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
+#else
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
+#endif
+
/* portNOP() is not required by this port. */
#define portNOP()
diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c
index 9254d6271..8311f94c7 100644
--- a/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c
+++ b/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c
@@ -117,6 +117,12 @@ is defined. */
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
+/* Constants required to check the validity of an interrupt prority. */
+#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
+#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
+#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
+#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
+
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 )
@@ -179,6 +185,16 @@ static void prvStartFirstTask( void );
static unsigned long ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
+/*
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
+ * FreeRTOS API functions are not called from interrupts that have been assigned
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
+ */
+#if ( configASSERT_DEFINED == 1 )
+ static unsigned char ucMaxSysCallPriority = 0;
+ static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
+#endif /* configASSERT_DEFINED */
+
/*-----------------------------------------------------------*/
/*
@@ -241,6 +257,33 @@ __asm void prvStartFirstTask( void )
*/
portBASE_TYPE xPortStartScheduler( void )
{
+ #if( configASSERT_DEFINED == 1 )
+ {
+ volatile unsigned long ulOriginalPriority;
+ volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
+
+ /* Determine the maximum priority from which ISR safe FreeRTOS API
+ functions can be called. ISR safe functions are those that end in
+ "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+ ensure interrupt entry is as fast and simple as possible.
+
+ Save the interrupt priority value that is about to be clobbered. */
+ ulOriginalPriority = *pcFirstUserPriorityRegister;
+
+ /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
+ priority register. */
+ *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
+
+ /* Read back the written priority to obtain its value as seen by the
+ hardware, which will only implement a subset of the priority bits. */
+ ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
+
+ /* Restore the clobbered interrupt priority register to its original
+ value. */
+ *pcFirstUserPriorityRegister = ulOriginalPriority;
+ }
+ #endif /* conifgASSERT_DEFINED */
+
/* Make PendSV and SysTick the lowest priority interrupts. */
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
@@ -524,3 +567,72 @@ __asm void vPortClearInterruptMask( unsigned long ulNewMask )
msr basepri, r0
bx r14
}
+/*-----------------------------------------------------------*/
+
+__asm unsigned long vPortGetIPSR( void )
+{
+ PRESERVE8
+
+ mrs r0, ipsr
+ bx r14
+}
+/*-----------------------------------------------------------*/
+
+#if( configASSERT_DEFINED == 1 )
+
+ void vPortValidateInterruptPriority( void )
+ {
+ unsigned long ulCurrentInterrupt;
+ unsigned char ucCurrentPriority;
+
+ /* Obtain the number of the currently executing interrupt. */
+ ulCurrentInterrupt = vPortGetIPSR();
+
+ /* Is the interrupt number a user defined interrupt? */
+ if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
+ {
+ /* Look up the interrupt's priority. */
+ ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
+
+ /* The following assertion will fail if a service routine (ISR) for
+ an interrupt that has been assigned a priority above
+ configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
+ function. ISR safe FreeRTOS API functions must *only* be called
+ from interrupts that have been assigned a priority at or below
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Numerically low interrupt priority numbers represent logically high
+ interrupt priorities, therefore the priority of the interrupt must
+ be set to a value equal to or numerically *higher* than
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Interrupts that use the FreeRTOS API must not be left at their
+ default priority of zero as that is the highest possible priority,
+ which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
+ and therefore also guaranteed to be invalid.
+
+ FreeRTOS maintains separate thread and ISR API functions to ensure
+ interrupt entry is as fast and simple as possible.
+
+ The following links provide detailed information:
+ http://www.freertos.org/RTOS-Cortex-M3-M4.html
+ http://www.freertos.org/FAQHelp.html */
+ configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
+ }
+
+ /* Priority grouping: The interrupt controller (NVIC) allows the bits
+ that define each interrupt's priority to be split between bits that
+ define the interrupt's pre-emption priority bits and bits that define
+ the interrupt's sub-priority. For simplicity all bits must be defined
+ to be pre-emption priority bits. The following assertion will fail if
+ this is not the case (if some bits represent a sub-priority).
+
+ If CMSIS libraries are being used then the correct setting can be
+ achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
+ scheduler. */
+ configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
+ }
+
+#endif /* configASSERT_DEFINED */
+
+
diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM3/portmacro.h b/FreeRTOS/Source/portable/RVDS/ARM_CM3/portmacro.h
index 80a7b2f3f..8e3522657 100644
--- a/FreeRTOS/Source/portable/RVDS/ARM_CM3/portmacro.h
+++ b/FreeRTOS/Source/portable/RVDS/ARM_CM3/portmacro.h
@@ -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 )
/*-----------------------------------------------------------*/
+#ifdef configASSERT
+ void vPortValidateInterruptPriority( void );
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
+#else
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
+#endif
+
/* portNOP() is not required by this port. */
#define portNOP()
diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c
index 616a8330b..1877f9a16 100644
--- a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c
+++ b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c
@@ -117,6 +117,12 @@ is defined. */
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
+/* Constants required to check the validity of an interrupt prority. */
+#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
+#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
+#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
+#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
+
/* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
@@ -188,6 +194,16 @@ static void prvEnableVFP( void );
static unsigned long ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
+/*
+ * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
+ * FreeRTOS API functions are not called from interrupts that have been assigned
+ * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
+ */
+#if ( configASSERT_DEFINED == 1 )
+ static unsigned char ucMaxSysCallPriority = 0;
+ static const volatile unsigned char * const pcInterruptPriorityRegisters = ( unsigned char * ) portNVIC_IP_REGISTERS_OFFSET_16;
+#endif /* configASSERT_DEFINED */
+
/*-----------------------------------------------------------*/
/*
@@ -279,6 +295,33 @@ __asm void prvEnableVFP( void )
*/
portBASE_TYPE xPortStartScheduler( void )
{
+ #if( configASSERT_DEFINED == 1 )
+ {
+ volatile unsigned long ulOriginalPriority;
+ volatile char * const pcFirstUserPriorityRegister = ( char * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
+
+ /* Determine the maximum priority from which ISR safe FreeRTOS API
+ functions can be called. ISR safe functions are those that end in
+ "FromISR". FreeRTOS maintains separate thread and ISR API functions to
+ ensure interrupt entry is as fast and simple as possible.
+
+ Save the interrupt priority value that is about to be clobbered. */
+ ulOriginalPriority = *pcFirstUserPriorityRegister;
+
+ /* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
+ priority register. */
+ *pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
+
+ /* Read back the written priority to obtain its value as seen by the
+ hardware, which will only implement a subset of the priority bits. */
+ ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
+
+ /* Restore the clobbered interrupt priority register to its original
+ value. */
+ *pcFirstUserPriorityRegister = ulOriginalPriority;
+ }
+ #endif /* conifgASSERT_DEFINED */
+
/* Make PendSV and SysTick the lowest priority interrupts. */
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
@@ -587,3 +630,72 @@ __asm void vPortClearInterruptMask( unsigned long ulNewMask )
msr basepri, r0
bx r14
}
+/*-----------------------------------------------------------*/
+
+__asm unsigned long vPortGetIPSR( void )
+{
+ PRESERVE8
+
+ mrs r0, ipsr
+ bx r14
+}
+/*-----------------------------------------------------------*/
+
+#if( configASSERT_DEFINED == 1 )
+
+ void vPortValidateInterruptPriority( void )
+ {
+ unsigned long ulCurrentInterrupt;
+ unsigned char ucCurrentPriority;
+
+ /* Obtain the number of the currently executing interrupt. */
+ ulCurrentInterrupt = vPortGetIPSR();
+
+ /* Is the interrupt number a user defined interrupt? */
+ if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
+ {
+ /* Look up the interrupt's priority. */
+ ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
+
+ /* The following assertion will fail if a service routine (ISR) for
+ an interrupt that has been assigned a priority above
+ configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
+ function. ISR safe FreeRTOS API functions must *only* be called
+ from interrupts that have been assigned a priority at or below
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Numerically low interrupt priority numbers represent logically high
+ interrupt priorities, therefore the priority of the interrupt must
+ be set to a value equal to or numerically *higher* than
+ configMAX_SYSCALL_INTERRUPT_PRIORITY.
+
+ Interrupts that use the FreeRTOS API must not be left at their
+ default priority of zero as that is the highest possible priority,
+ which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
+ and therefore also guaranteed to be invalid.
+
+ FreeRTOS maintains separate thread and ISR API functions to ensure
+ interrupt entry is as fast and simple as possible.
+
+ The following links provide detailed information:
+ http://www.freertos.org/RTOS-Cortex-M3-M4.html
+ http://www.freertos.org/FAQHelp.html */
+ configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
+ }
+
+ /* Priority grouping: The interrupt controller (NVIC) allows the bits
+ that define each interrupt's priority to be split between bits that
+ define the interrupt's pre-emption priority bits and bits that define
+ the interrupt's sub-priority. For simplicity all bits must be defined
+ to be pre-emption priority bits. The following assertion will fail if
+ this is not the case (if some bits represent a sub-priority).
+
+ If CMSIS libraries are being used then the correct setting can be
+ achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
+ scheduler. */
+ configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
+ }
+
+#endif /* configASSERT_DEFINED */
+
+
diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/portmacro.h b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/portmacro.h
index ef8fa6252..d2ab5a527 100644
--- a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/portmacro.h
+++ b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/portmacro.h
@@ -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 )
/*-----------------------------------------------------------*/
+#ifdef configASSERT
+ void vPortValidateInterruptPriority( void );
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
+#else
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
+#endif
+
/* portNOP() is not required by this port. */
#define portNOP()