summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2017-03-28 03:13:48 +0000
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2017-03-28 03:13:48 +0000
commit29db80794b3bc852128135baf2dd96a2781b0977 (patch)
tree22f40e6f499000591ea7cc36aeb599a7ab92a22a
parentef081ae244103d9b938f5e683459ab9c6ce9dd81 (diff)
downloadfreertos-29db80794b3bc852128135baf2dd96a2781b0977.tar.gz
Updates to the Cortex-M tickless idle code to reduce clock slippage.
Updates to prevent the vTaskSwitchContext() function being removed from GCC builds when link time optimisation is used. git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@2493 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
-rw-r--r--FreeRTOS/Source/portable/CCS/ARM_CM3/port.c101
-rw-r--r--FreeRTOS/Source/portable/CCS/ARM_CM4F/port.c103
-rw-r--r--FreeRTOS/Source/portable/GCC/ARM_CM0/port.c15
-rw-r--r--FreeRTOS/Source/portable/GCC/ARM_CM3/port.c79
-rw-r--r--FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c98
-rw-r--r--FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c116
-rw-r--r--FreeRTOS/Source/portable/IAR/ARM_CM3/port.c102
-rw-r--r--FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h6
-rw-r--r--FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c100
-rw-r--r--FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h6
-rw-r--r--FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/port.c103
-rw-r--r--FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/portmacro.h6
-rw-r--r--FreeRTOS/Source/portable/MikroC/ARM_CM4F/port.c85
-rw-r--r--FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c103
-rw-r--r--FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c91
-rw-r--r--FreeRTOS/Source/portable/RVDS/ARM_CM7/r0p1/port.c99
16 files changed, 697 insertions, 516 deletions
diff --git a/FreeRTOS/Source/portable/CCS/ARM_CM3/port.c b/FreeRTOS/Source/portable/CCS/ARM_CM3/port.c
index 7ec544e04..0fc1a6271 100644
--- a/FreeRTOS/Source/portable/CCS/ARM_CM3/port.c
+++ b/FreeRTOS/Source/portable/CCS/ARM_CM3/port.c
@@ -75,7 +75,7 @@
#include "FreeRTOS.h"
#include "task.h"
-#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
+#if( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#endif
@@ -132,14 +132,6 @@ calculations. */
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
-/* Required to allow portasm.asm access the configMAX_SYSCALL_INTERRUPT_PRIORITY
-setting. */
-const uint32_t ulMaxSyscallInterruptPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY;
-
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
-
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
@@ -164,10 +156,18 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Required to allow portasm.asm access the configMAX_SYSCALL_INTERRUPT_PRIORITY
+setting. */
+const uint32_t ulMaxSyscallInterruptPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY;
+
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -175,7 +175,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -183,7 +183,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -384,12 +384,12 @@ void xPortSysTickHandler( void )
}
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
#pragma WEAK( vPortSuppressTicksAndSleep )
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@@ -466,23 +466,41 @@ void xPortSysTickHandler( void )
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above __disable_interrupt()
- call above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__asm( " cpsie i" );
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ __asm( " dsb" );
+ __asm( " isb" );
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __asm( " cpsid i" );
+ __asm( " dsb" );
+ __asm( " isb" );
+
+ /* Disable the SysTick clock without reading the
+ portNVIC_SYSTICK_CTRL_REG register to ensure the
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine if the SysTick clock has already counted to zero and
+ been set back to the current reload value (the reload back being
+ correct for the entire expected idle time) or if the SysTick is yet
+ to count to zero (in which case an interrupt other than the SysTick
+ must have brought the system out of sleep mode). */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -497,11 +515,9 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -523,21 +539,18 @@ void xPortSysTickHandler( void )
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __asm( " cpsie i" );
}
}
-#endif /* #if configUSE_TICKLESS_IDLE */
+#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/*
@@ -620,7 +633,7 @@ void vPortSetupTimerInterrupt( void )
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
diff --git a/FreeRTOS/Source/portable/CCS/ARM_CM4F/port.c b/FreeRTOS/Source/portable/CCS/ARM_CM4F/port.c
index d00990171..9457be19a 100644
--- a/FreeRTOS/Source/portable/CCS/ARM_CM4F/port.c
+++ b/FreeRTOS/Source/portable/CCS/ARM_CM4F/port.c
@@ -79,7 +79,7 @@
#error This port can only be used when the project options are configured to enable hardware floating point support.
#endif
-#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
+#if( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#endif
@@ -141,14 +141,6 @@ calculations. */
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
-/* Required to allow portasm.asm access the configMAX_SYSCALL_INTERRUPT_PRIORITY
-setting. */
-const uint32_t ulMaxSyscallInterruptPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY;
-
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
-
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
@@ -178,10 +170,18 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Required to allow portasm.asm access the configMAX_SYSCALL_INTERRUPT_PRIORITY
+setting. */
+const uint32_t ulMaxSyscallInterruptPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY;
+
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -189,7 +189,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -197,7 +197,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -409,12 +409,12 @@ void xPortSysTickHandler( void )
}
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
#pragma WEAK( vPortSuppressTicksAndSleep )
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@@ -491,23 +491,41 @@ void xPortSysTickHandler( void )
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above __disable_interrupt()
- call above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__asm( " cpsie i" );
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ __asm( " dsb" );
+ __asm( " isb" );
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __asm( " cpsid i" );
+ __asm( " dsb" );
+ __asm( " isb" );
+
+ /* Disable the SysTick clock without reading the
+ portNVIC_SYSTICK_CTRL_REG register to ensure the
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine if the SysTick clock has already counted to zero and
+ been set back to the current reload value (the reload back being
+ correct for the entire expected idle time) or if the SysTick is yet
+ to count to zero (in which case an interrupt other than the SysTick
+ must have brought the system out of sleep mode). */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -522,11 +540,9 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -548,21 +564,18 @@ void xPortSysTickHandler( void )
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __asm( " cpsie i" );
}
}
-#endif /* #if configUSE_TICKLESS_IDLE */
+#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/*
@@ -573,7 +586,7 @@ void xPortSysTickHandler( void )
void vPortSetupTimerInterrupt( void )
{
/* Calculate the constants required to configure the tick interrupt. */
- #if configUSE_TICKLESS_IDLE == 1
+ #if( configUSE_TICKLESS_IDLE == 1 )
{
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@@ -645,7 +658,7 @@ void vPortSetupTimerInterrupt( void )
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c
index 559883f58..c4c768bea 100644
--- a/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c
+++ b/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c
@@ -101,10 +101,6 @@ debugger. */
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
-
/*
* Setup the timer to generate the tick interrupts.
*/
@@ -129,6 +125,12 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
+/*-----------------------------------------------------------*/
+
/*
* See header file for description.
*/
@@ -220,8 +222,11 @@ BaseType_t xPortStartScheduler( void )
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
- functionality by defining configTASK_RETURN_ADDRESS. */
+ functionality by defining configTASK_RETURN_ADDRESS. Call
+ vTaskSwitchContext() so link time optimisation does not remove the
+ symbol. */
prvTaskExitError();
+ vTaskSwitchContext();
/* Should not get here! */
return 0;
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c
index ba512f0b4..1317a387e 100644
--- a/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c
+++ b/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c
@@ -144,10 +144,6 @@ debugger. */
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
-
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
@@ -174,10 +170,14 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -185,7 +185,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -193,7 +193,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -202,7 +202,7 @@ static void prvTaskExitError( void );
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/
-#if ( configASSERT_DEFINED == 1 )
+#if( configASSERT_DEFINED == 1 )
static uint8_t ucMaxSysCallPriority = 0;
static uint32_t ulMaxPRIGROUPValue = 0;
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
@@ -370,8 +370,11 @@ BaseType_t xPortStartScheduler( void )
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
- functionality by defining configTASK_RETURN_ADDRESS. */
+ functionality by defining configTASK_RETURN_ADDRESS. Call
+ vTaskSwitchContext() so link time optimisation does not remove the
+ symbol. */
prvTaskExitError();
+ vTaskSwitchContext();
/* Should not get here! */
return 0;
@@ -471,7 +474,7 @@ void xPortSysTickHandler( void )
}
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
@@ -551,13 +554,28 @@ void xPortSysTickHandler( void )
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Re-enable interrupts - see comments above the cpsid instruction()
- above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__asm volatile( "cpsie i" ::: "memory" );
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __asm volatile( "cpsid i" ::: "memory" );
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
/* Disable the SysTick clock without reading the
portNVIC_SYSTICK_CTRL_REG register to ensure the
- portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. */
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
/* Determine if the SysTick clock has already counted to zero and
@@ -569,8 +587,8 @@ void xPortSysTickHandler( void )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -585,11 +603,9 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -611,21 +627,18 @@ void xPortSysTickHandler( void )
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __asm volatile( "cpsie i" ::: "memory" );
}
}
-#endif /* #if configUSE_TICKLESS_IDLE */
+#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/*
@@ -635,7 +648,7 @@ void xPortSysTickHandler( void )
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
{
/* Calculate the constants required to configure the tick interrupt. */
- #if configUSE_TICKLESS_IDLE == 1
+ #if( configUSE_TICKLESS_IDLE == 1 )
{
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@@ -707,7 +720,7 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
index 54cb9a754..6fc47a045 100644
--- a/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
+++ b/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
@@ -152,10 +152,6 @@ debugger. */
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
-
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
@@ -187,10 +183,14 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -198,7 +198,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -206,7 +206,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -215,7 +215,7 @@ static void prvTaskExitError( void );
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/
-#if ( configASSERT_DEFINED == 1 )
+#if( configASSERT_DEFINED == 1 )
static uint8_t ucMaxSysCallPriority = 0;
static uint32_t ulMaxPRIGROUPValue = 0;
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
@@ -412,8 +412,11 @@ BaseType_t xPortStartScheduler( void )
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
- functionality by defining configTASK_RETURN_ADDRESS. */
+ functionality by defining configTASK_RETURN_ADDRESS. Call
+ vTaskSwitchContext() so link time optimisation does not remove the
+ symbol. */
prvTaskExitError();
+ vTaskSwitchContext();
/* Should not get here! */
return 0;
@@ -533,11 +536,11 @@ void xPortSysTickHandler( void )
}
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@@ -613,23 +616,41 @@ void xPortSysTickHandler( void )
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above the cpsid instruction()
- above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__asm volatile( "cpsie i" ::: "memory" );
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __asm volatile( "cpsid i" ::: "memory" );
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
+
+ /* Disable the SysTick clock without reading the
+ portNVIC_SYSTICK_CTRL_REG register to ensure the
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine if the SysTick clock has already counted to zero and
+ been set back to the current reload value (the reload back being
+ correct for the entire expected idle time) or if the SysTick is yet
+ to count to zero (in which case an interrupt other than the SysTick
+ must have brought the system out of sleep mode). */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -644,11 +665,9 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -670,17 +689,14 @@ void xPortSysTickHandler( void )
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __asm volatile( "cpsie i" ::: "memory" );
}
}
@@ -694,7 +710,7 @@ void xPortSysTickHandler( void )
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
{
/* Calculate the constants required to configure the tick interrupt. */
- #if configUSE_TICKLESS_IDLE == 1
+ #if( configUSE_TICKLESS_IDLE == 1 )
{
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@@ -781,7 +797,7 @@ static void vPortEnableVFP( void )
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c
index 132333daa..b80e0d0b3 100644
--- a/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c
+++ b/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c
@@ -118,25 +118,25 @@
#define portVECTACTIVE_MASK ( 0xFFUL )
/* Constants required to manipulate the VFP. */
-#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
-#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
+#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
+#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
/* Constants required to set up the initial stack. */
-#define portINITIAL_XPSR ( 0x01000000 )
-#define portINITIAL_EXEC_RETURN ( 0xfffffffd )
+#define portINITIAL_XPSR ( 0x01000000 )
+#define portINITIAL_EXEC_RETURN ( 0xfffffffd )
/* The systick is a 24-bit counter. */
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
+/* For strict compliance with the Cortex-M spec the task start address should
+have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
+#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
+
/* A fiddle factor to estimate the number of SysTick counts that would have
occurred while the SysTick counter is stopped during tickless idle
calculations. */
#define portMISSED_COUNTS_FACTOR ( 45UL )
-/* For strict compliance with the Cortex-M spec the task start address should
-have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
-#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
-
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case it messes up unwinding of the stack in the
debugger. */
@@ -146,10 +146,6 @@ debugger. */
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
-
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
@@ -172,7 +168,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
/*
* Function to enable the VFP.
*/
- static void vPortEnableVFP( void ) __attribute__ (( naked ));
+static void vPortEnableVFP( void ) __attribute__ (( naked ));
/*
* Used to catch tasks that attempt to return from their implementing function.
@@ -181,10 +177,14 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -192,7 +192,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -200,7 +200,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -209,7 +209,7 @@ static void prvTaskExitError( void );
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/
-#if ( configASSERT_DEFINED == 1 )
+#if( configASSERT_DEFINED == 1 )
static uint8_t ucMaxSysCallPriority = 0;
static uint32_t ulMaxPRIGROUPValue = 0;
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
@@ -400,8 +400,11 @@ BaseType_t xPortStartScheduler( void )
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
- functionality by defining configTASK_RETURN_ADDRESS. */
+ functionality by defining configTASK_RETURN_ADDRESS. Call
+ vTaskSwitchContext() so link time optimisation does not remove the
+ symbol. */
prvTaskExitError();
+ vTaskSwitchContext();
/* Should not get here! */
return 0;
@@ -523,11 +526,11 @@ void xPortSysTickHandler( void )
}
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@@ -603,23 +606,41 @@ void xPortSysTickHandler( void )
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above the cpsid instruction()
- above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__asm volatile( "cpsie i" ::: "memory" );
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __asm volatile( "cpsid i" ::: "memory" );
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
+
+ /* Disable the SysTick clock without reading the
+ portNVIC_SYSTICK_CTRL_REG register to ensure the
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine if the SysTick clock has already counted to zero and
+ been set back to the current reload value (the reload back being
+ correct for the entire expected idle time) or if the SysTick is yet
+ to count to zero (in which case an interrupt other than the SysTick
+ must have brought the system out of sleep mode). */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -634,11 +655,9 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -660,17 +679,14 @@ void xPortSysTickHandler( void )
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __asm volatile( "cpsie i" ::: "memory" );
}
}
@@ -684,7 +700,7 @@ void xPortSysTickHandler( void )
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
{
/* Calculate the constants required to configure the tick interrupt. */
- #if configUSE_TICKLESS_IDLE == 1
+ #if( configUSE_TICKLESS_IDLE == 1 )
{
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@@ -771,7 +787,7 @@ static void vPortEnableVFP( void )
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c
index d8a10ae1a..272706596 100644
--- a/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c
+++ b/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c
@@ -78,7 +78,7 @@
#include "FreeRTOS.h"
#include "task.h"
-#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
+#if( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#endif
@@ -142,10 +142,6 @@ FreeRTOS.org versions prior to V4.3.0 did not include this definition. */
#define configKERNEL_INTERRUPT_PRIORITY 255
#endif
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
-
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
@@ -170,10 +166,14 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -181,7 +181,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -189,7 +189,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -198,7 +198,7 @@ static void prvTaskExitError( void );
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/
-#if ( configASSERT_DEFINED == 1 )
+#if( configASSERT_DEFINED == 1 )
static uint8_t ucMaxSysCallPriority = 0;
static uint32_t ulMaxPRIGROUPValue = 0;
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
@@ -246,6 +246,10 @@ static void prvTaskExitError( void )
*/
BaseType_t xPortStartScheduler( void )
{
+ /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
+ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+ configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
+
#if( configASSERT_DEFINED == 1 )
{
volatile uint32_t ulOriginalPriority;
@@ -383,11 +387,11 @@ void xPortSysTickHandler( void )
}
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@@ -417,7 +421,6 @@ void xPortSysTickHandler( void )
__DSB();
__ISB();
-
/* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
@@ -464,23 +467,41 @@ void xPortSysTickHandler( void )
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above __disable_interrupt()
- call above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__enable_interrupt();
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ __DSB();
+ __ISB();
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __disable_interrupt();
+ __DSB();
+ __ISB();
+
+ /* Disable the SysTick clock without reading the
+ portNVIC_SYSTICK_CTRL_REG register to ensure the
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine if the SysTick clock has already counted to zero and
+ been set back to the current reload value (the reload back being
+ correct for the entire expected idle time) or if the SysTick is yet
+ to count to zero (in which case an interrupt other than the SysTick
+ must have brought the system out of sleep mode). */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -495,11 +516,9 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -521,21 +540,18 @@ void xPortSysTickHandler( void )
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __enable_interrupt();
}
}
-#endif /* #if configUSE_TICKLESS_IDLE */
+#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/*
@@ -571,7 +587,7 @@ __weak void vPortSetupTimerInterrupt( void )
uint8_t ucCurrentPriority;
/* Obtain the number of the currently executing interrupt. */
- __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
+ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
/* Is the interrupt number a user defined interrupt? */
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
@@ -617,7 +633,7 @@ __weak void vPortSetupTimerInterrupt( void )
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h b/FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h
index 7b96b771e..e2c3b2f62 100644
--- a/FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h
+++ b/FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h
@@ -85,6 +85,9 @@ extern "C" {
*-----------------------------------------------------------
*/
+/* IAR includes. */
+#include <intrinsics.h>
+
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
@@ -138,7 +141,7 @@ typedef unsigned long UBaseType_t;
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
-#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
+#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
/* Check the configuration. */
#if( configMAX_PRIORITIES > 32 )
@@ -151,7 +154,6 @@ typedef unsigned long UBaseType_t;
/*-----------------------------------------------------------*/
- #include <intrinsics.h>
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( ( uint32_t ) __CLZ( ( uxReadyPriorities ) ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c
index 18854f5b3..cd773cffc 100644
--- a/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c
+++ b/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c
@@ -71,7 +71,7 @@
* Implementation of functions defined in portable.h for the ARM CM4F port.
*----------------------------------------------------------*/
-/* Compiler includes. */
+/* IAR includes. */
#include <intrinsics.h>
/* Scheduler includes. */
@@ -82,7 +82,7 @@
#error This port can only be used when the project options are configured to enable hardware floating point support.
#endif
-#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
+#if( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#endif
@@ -150,10 +150,6 @@ calculations. */
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
-
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
@@ -183,10 +179,14 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -194,7 +194,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -202,7 +202,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -211,7 +211,7 @@ static void prvTaskExitError( void );
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/
-#if ( configASSERT_DEFINED == 1 )
+#if( configASSERT_DEFINED == 1 )
static uint8_t ucMaxSysCallPriority = 0;
static uint32_t ulMaxPRIGROUPValue = 0;
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
@@ -424,11 +424,11 @@ void xPortSysTickHandler( void )
}
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@@ -458,7 +458,6 @@ void xPortSysTickHandler( void )
__DSB();
__ISB();
-
/* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
@@ -505,23 +504,41 @@ void xPortSysTickHandler( void )
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above __disable_interrupt()
- call above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__enable_interrupt();
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ __DSB();
+ __ISB();
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __disable_interrupt();
+ __DSB();
+ __ISB();
+
+ /* Disable the SysTick clock without reading the
+ portNVIC_SYSTICK_CTRL_REG register to ensure the
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine if the SysTick clock has already counted to zero and
+ been set back to the current reload value (the reload back being
+ correct for the entire expected idle time) or if the SysTick is yet
+ to count to zero (in which case an interrupt other than the SysTick
+ must have brought the system out of sleep mode). */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -536,11 +553,9 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -562,21 +577,18 @@ void xPortSysTickHandler( void )
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __enable_interrupt();
}
}
-#endif /* #if configUSE_TICKLESS_IDLE */
+#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/*
@@ -612,7 +624,7 @@ __weak void vPortSetupTimerInterrupt( void )
uint8_t ucCurrentPriority;
/* Obtain the number of the currently executing interrupt. */
- __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
+ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
/* Is the interrupt number a user defined interrupt? */
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
@@ -658,7 +670,7 @@ __weak void vPortSetupTimerInterrupt( void )
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h b/FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h
index 007dcfaca..a14a7cd20 100644
--- a/FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h
+++ b/FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h
@@ -84,6 +84,9 @@ extern "C" {
*-----------------------------------------------------------
*/
+/* IAR includes. */
+#include <intrinsics.h>
+
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
@@ -137,7 +140,7 @@ typedef unsigned long UBaseType_t;
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
-#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
+#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
/* Check the configuration. */
#if( configMAX_PRIORITIES > 32 )
@@ -150,7 +153,6 @@ typedef unsigned long UBaseType_t;
/*-----------------------------------------------------------*/
- #include <intrinsics.h>
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( ( uint32_t ) __CLZ( ( uxReadyPriorities ) ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/port.c
index f5a30bc63..7ec4084df 100644
--- a/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/port.c
+++ b/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/port.c
@@ -71,7 +71,7 @@
* Implementation of functions defined in portable.h for the ARM CM4F port.
*----------------------------------------------------------*/
-/* Compiler includes. */
+/* IAR includes. */
#include <intrinsics.h>
/* Scheduler includes. */
@@ -82,7 +82,7 @@
#error This port can only be used when the project options are configured to enable hardware floating point support.
#endif
-#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
+#if( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#endif
@@ -144,10 +144,6 @@ calculations. */
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
-
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
@@ -177,10 +173,14 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -188,7 +188,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -196,7 +196,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -205,7 +205,7 @@ static void prvTaskExitError( void );
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/
-#if ( configASSERT_DEFINED == 1 )
+#if( configASSERT_DEFINED == 1 )
static uint8_t ucMaxSysCallPriority = 0;
static uint32_t ulMaxPRIGROUPValue = 0;
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
@@ -265,6 +265,10 @@ static void prvTaskExitError( void )
*/
BaseType_t xPortStartScheduler( void )
{
+ /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
+ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+ configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
+
#if( configASSERT_DEFINED == 1 )
{
volatile uint32_t ulOriginalPriority;
@@ -408,11 +412,11 @@ void xPortSysTickHandler( void )
}
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@@ -488,23 +492,41 @@ void xPortSysTickHandler( void )
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above __disable_interrupt()
- call above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__enable_interrupt();
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ __DSB();
+ __ISB();
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __disable_interrupt();
+ __DSB();
+ __ISB();
+
+ /* Disable the SysTick clock without reading the
+ portNVIC_SYSTICK_CTRL_REG register to ensure the
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine if the SysTick clock has already counted to zero and
+ been set back to the current reload value (the reload back being
+ correct for the entire expected idle time) or if the SysTick is yet
+ to count to zero (in which case an interrupt other than the SysTick
+ must have brought the system out of sleep mode). */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -519,11 +541,9 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -545,21 +565,18 @@ void xPortSysTickHandler( void )
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __enable_interrupt();
}
}
-#endif /* #if configUSE_TICKLESS_IDLE */
+#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/*
@@ -595,7 +612,7 @@ __weak void vPortSetupTimerInterrupt( void )
uint8_t ucCurrentPriority;
/* Obtain the number of the currently executing interrupt. */
- __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
+ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
/* Is the interrupt number a user defined interrupt? */
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
@@ -641,7 +658,7 @@ __weak void vPortSetupTimerInterrupt( void )
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/portmacro.h b/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/portmacro.h
index a1534cd8f..bf8d19845 100644
--- a/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/portmacro.h
+++ b/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/portmacro.h
@@ -84,6 +84,9 @@ extern "C" {
*-----------------------------------------------------------
*/
+/* IAR includes. */
+#include <intrinsics.h>
+
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
@@ -137,7 +140,7 @@ typedef unsigned long UBaseType_t;
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
-#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
+#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
/* Check the configuration. */
#if( configMAX_PRIORITIES > 32 )
@@ -150,7 +153,6 @@ typedef unsigned long UBaseType_t;
/*-----------------------------------------------------------*/
- #include <intrinsics.h>
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( ( uint32_t ) __CLZ( ( uxReadyPriorities ) ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
diff --git a/FreeRTOS/Source/portable/MikroC/ARM_CM4F/port.c b/FreeRTOS/Source/portable/MikroC/ARM_CM4F/port.c
index 3345a5d3d..761806d21 100644
--- a/FreeRTOS/Source/portable/MikroC/ARM_CM4F/port.c
+++ b/FreeRTOS/Source/portable/MikroC/ARM_CM4F/port.c
@@ -196,7 +196,7 @@ static void prvTaskExitError( void );
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -204,7 +204,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -212,7 +212,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -535,7 +535,7 @@ void xPortSysTickHandler( void ) iv IVT_INT_SysTick ics ICS_AUTO
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@@ -611,25 +611,41 @@ void xPortSysTickHandler( void ) iv IVT_INT_SysTick ics ICS_AUTO
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above the cpsid instruction()
- above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__asm { "cpsie i" };
- __asm { "wfi" };
- __asm { "isb" };
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ __asm { "dsb" };
+ __asm { "isb" };
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __asm { "cpsid i" };
+ __asm { "dsb" };
+ __asm { "isb" };
+
+ /* Disable the SysTick clock without reading the
+ portNVIC_SYSTICK_CTRL_REG register to ensure the
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine if the SysTick clock has already counted to zero and
+ been set back to the current reload value (the reload back being
+ correct for the entire expected idle time) or if the SysTick is yet
+ to count to zero (in which case an interrupt other than the SysTick
+ must have brought the system out of sleep mode). */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -644,11 +660,9 @@ void xPortSysTickHandler( void ) iv IVT_INT_SysTick ics ICS_AUTO
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -665,22 +679,19 @@ void xPortSysTickHandler( void ) iv IVT_INT_SysTick ics ICS_AUTO
/* The reload value is set to whatever fraction of a single tick
period remains. */
- portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
+ portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
}
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __asm { "cpsie i" };
}
}
@@ -696,7 +707,7 @@ void xPortSysTickHandler( void ) iv IVT_INT_SysTick ics ICS_AUTO
void vPortSetupTimerInterrupt( void )
{
/* Calculate the constants required to configure the tick interrupt. */
- #if configUSE_TICKLESS_IDLE == 1
+ #if( configUSE_TICKLESS_IDLE == 1 )
{
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@@ -812,7 +823,7 @@ BaseType_t xReturn;
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c
index 6956b1a46..5fd109146 100644
--- a/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c
+++ b/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c
@@ -114,9 +114,6 @@ is defined. */
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
-/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
-#define portVECTACTIVE_MASK ( 0xFFUL )
-
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
@@ -130,6 +127,9 @@ is defined. */
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
#define portPRIGROUP_SHIFT ( 8UL )
+/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
+#define portVECTACTIVE_MASK ( 0xFFUL )
+
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 )
@@ -145,10 +145,6 @@ calculations. */
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
-
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
@@ -175,10 +171,14 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -186,7 +186,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -194,7 +194,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -313,6 +313,10 @@ BaseType_t xPortStartScheduler( void )
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
+ /* The kernel interrupt priority should be set to the lowest
+ priority. */
+ configASSERT( ucMaxPriorityValue == ( configKERNEL_INTERRUPT_PRIORITY & ucMaxPriorityValue ) );
+
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
@@ -467,11 +471,11 @@ void xPortSysTickHandler( void )
}
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@@ -547,23 +551,41 @@ void xPortSysTickHandler( void )
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above __disable_irq() call
- above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__enable_irq();
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ __dsb( portSY_FULL_READ_WRITE );
+ __isb( portSY_FULL_READ_WRITE );
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __disable_irq();
+ __dsb( portSY_FULL_READ_WRITE );
+ __isb( portSY_FULL_READ_WRITE );
+
+ /* Disable the SysTick clock without reading the
+ portNVIC_SYSTICK_CTRL_REG register to ensure the
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine if the SysTick clock has already counted to zero and
+ been set back to the current reload value (the reload back being
+ correct for the entire expected idle time) or if the SysTick is yet
+ to count to zero (in which case an interrupt other than the SysTick
+ must have brought the system out of sleep mode). */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -578,11 +600,9 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -604,17 +624,14 @@ void xPortSysTickHandler( void )
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __enable_irq();
}
}
@@ -626,12 +643,12 @@ void xPortSysTickHandler( void )
* Setup the SysTick timer to generate the tick interrupts at the required
* frequency.
*/
-#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0
+#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
void vPortSetupTimerInterrupt( void )
{
/* Calculate the constants required to configure the tick interrupt. */
- #if configUSE_TICKLESS_IDLE == 1
+ #if( configUSE_TICKLESS_IDLE == 1 )
{
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@@ -714,7 +731,7 @@ __asm uint32_t vPortGetIPSR( void )
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c
index 9086cc9a6..5d33ef8f5 100644
--- a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c
+++ b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c
@@ -156,10 +156,6 @@ calculations. */
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
-
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
@@ -191,10 +187,14 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -202,7 +202,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -210,7 +210,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -561,11 +561,11 @@ void xPortSysTickHandler( void )
}
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@@ -641,23 +641,41 @@ void xPortSysTickHandler( void )
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above __disable_irq() call
- above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__enable_irq();
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ __dsb( portSY_FULL_READ_WRITE );
+ __isb( portSY_FULL_READ_WRITE );
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __disable_irq();
+ __dsb( portSY_FULL_READ_WRITE );
+ __isb( portSY_FULL_READ_WRITE );
+
+ /* Disable the SysTick clock without reading the
+ portNVIC_SYSTICK_CTRL_REG register to ensure the
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine if the SysTick clock has already counted to zero and
+ been set back to the current reload value (the reload back being
+ correct for the entire expected idle time) or if the SysTick is yet
+ to count to zero (in which case an interrupt other than the SysTick
+ must have brought the system out of sleep mode). */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -672,11 +690,9 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -698,17 +714,14 @@ void xPortSysTickHandler( void )
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __enable_irq();
}
}
@@ -725,7 +738,7 @@ void xPortSysTickHandler( void )
void vPortSetupTimerInterrupt( void )
{
/* Calculate the constants required to configure the tick interrupt. */
- #if configUSE_TICKLESS_IDLE == 1
+ #if( configUSE_TICKLESS_IDLE == 1 )
{
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@@ -808,7 +821,7 @@ __asm uint32_t vPortGetIPSR( void )
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM7/r0p1/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM7/r0p1/port.c
index c851e695b..e3ca6f4d3 100644
--- a/FreeRTOS/Source/portable/RVDS/ARM_CM7/r0p1/port.c
+++ b/FreeRTOS/Source/portable/RVDS/ARM_CM7/r0p1/port.c
@@ -139,20 +139,16 @@ is defined. */
#define portINITIAL_EXEC_RETURN ( 0xfffffffd )
/* The systick is a 24-bit counter. */
-#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
+#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
/* A fiddle factor to estimate the number of SysTick counts that would have
occurred while the SysTick counter is stopped during tickless idle
calculations. */
-#define portMISSED_COUNTS_FACTOR ( 45UL )
+#define portMISSED_COUNTS_FACTOR ( 45UL )
/* For strict compliance with the Cortex-M spec the task start address should
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
-#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
-
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
-static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
/*
* Setup the timer to generate the tick interrupts. The implementation in this
@@ -185,10 +181,14 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
/*
* The number of SysTick increments that make up one tick period.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -196,7 +196,7 @@ static void prvTaskExitError( void );
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -204,7 +204,7 @@ static void prvTaskExitError( void );
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
@@ -547,11 +547,11 @@ void xPortSysTickHandler( void )
}
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE == 1
+#if( configUSE_TICKLESS_IDLE == 1 )
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
- uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@@ -627,23 +627,41 @@ void xPortSysTickHandler( void )
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
- /* Stop SysTick. Again, the time the SysTick is stopped for is
- accounted for as best it can be, but using the tickless mode will
- inevitably result in some tiny drift of the time maintained by the
- kernel with respect to calendar time. */
- ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
- portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
-
- /* Re-enable interrupts - see comments above __disable_irq() call
- above. */
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ out of sleep mode to execute immediately. see comments above
+ __disable_interrupt() call above. */
__enable_irq();
-
- if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ __dsb( portSY_FULL_READ_WRITE );
+ __isb( portSY_FULL_READ_WRITE );
+
+ /* Disable interrupts again because the clock is about to be stopped
+ and interrupts that execute while the clock is stopped will increase
+ any slippage between the time maintained by the RTOS and calendar
+ time. */
+ __disable_irq();
+ __dsb( portSY_FULL_READ_WRITE );
+ __isb( portSY_FULL_READ_WRITE );
+
+ /* Disable the SysTick clock without reading the
+ portNVIC_SYSTICK_CTRL_REG register to ensure the
+ portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ the time the SysTick is stopped for is accounted for as best it can
+ be, but using the tickless mode will inevitably result in some tiny
+ drift of the time maintained by the kernel with respect to calendar
+ time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine if the SysTick clock has already counted to zero and
+ been set back to the current reload value (the reload back being
+ correct for the entire expected idle time) or if the SysTick is yet
+ to count to zero (in which case an interrupt other than the SysTick
+ must have brought the system out of sleep mode). */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
- /* The tick interrupt has already executed, and the SysTick
- count reloaded with ulReloadValue. Reset the
+ /* The tick interrupt is already pending, and the SysTick count
+ reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
@@ -658,11 +676,9 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
- /* The tick interrupt handler will already have pended the tick
- processing in the kernel. As the pending tick will be
- processed as soon as this function exits, the tick value
- maintained by the tick is stepped forward by one less than the
- time spent waiting. */
+ /* As the pending tick will be processed as soon as this
+ function exits, the tick value maintained by the tick is stepped
+ forward by one less than the time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
@@ -684,17 +700,14 @@ void xPortSysTickHandler( void )
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
- value. The critical section is used to ensure the tick interrupt
- can only execute once in the case that the reload register is near
- zero. */
+ value. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
- portENTER_CRITICAL();
- {
- portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
- vTaskStepTick( ulCompleteTickPeriods );
- portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
- }
- portEXIT_CRITICAL();
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+ vTaskStepTick( ulCompleteTickPeriods );
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+ /* Exit with interrpts enabled. */
+ __enable_irq();
}
}
@@ -706,12 +719,12 @@ void xPortSysTickHandler( void )
* Setup the SysTick timer to generate the tick interrupts at the required
* frequency.
*/
-#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0
+#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
void vPortSetupTimerInterrupt( void )
{
/* Calculate the constants required to configure the tick interrupt. */
- #if configUSE_TICKLESS_IDLE == 1
+ #if( configUSE_TICKLESS_IDLE == 1 )
{
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
@@ -794,7 +807,7 @@ __asm uint32_t vPortGetIPSR( void )
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
- of zero will result in unpredicable behaviour. */
+ of zero will result in unpredictable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}