diff options
author | richardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2> | 2013-07-04 11:20:28 +0000 |
---|---|---|
committer | richardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2> | 2013-07-04 11:20:28 +0000 |
commit | 03ddb80a20e723631c54fa1c01a70f8d2806f541 (patch) | |
tree | 26a52035eed459783742083160d6135d30af66b1 /FreeRTOS/Source/portable | |
parent | cf20d8ab394f87e350c90c3c9f6a3dd990772734 (diff) | |
download | freertos-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.c | 120 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h | 7 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c | 102 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h | 7 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/IAR/ARM_CM3/port.c | 120 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h | 7 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c | 120 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h | 7 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c | 112 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/RVDS/ARM_CM3/portmacro.h | 7 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c | 112 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/RVDS/ARM_CM4F/portmacro.h | 7 |
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()
|