From 3ea77b1644668000ea12bae4837c920bfd4dce5c Mon Sep 17 00:00:00 2001 From: richardbarry Date: Mon, 29 Oct 2012 15:56:26 +0000 Subject: [PATCH] Make CM3/4 tick configuration a weak function to allow application writers to use an alternative tick source. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1803 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- FreeRTOS/Source/include/FreeRTOS.h | 4 +- FreeRTOS/Source/portable/GCC/ARM_CM3/port.c | 56 +++++--- FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c | 54 +++++--- .../Source/portable/GCC/ARM_CM4F/portmacro.h | 2 - FreeRTOS/Source/portable/IAR/ARM_CM3/port.c | 75 ++++++----- FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c | 75 ++++++----- FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c | 82 ++++++++---- FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c | 84 +++++++----- FreeRTOS/Source/tasks.c | 120 ++++++++++-------- 9 files changed, 338 insertions(+), 214 deletions(-) diff --git a/FreeRTOS/Source/include/FreeRTOS.h b/FreeRTOS/Source/include/FreeRTOS.h index c9eda0fd7..2c0c28d8c 100644 --- a/FreeRTOS/Source/include/FreeRTOS.h +++ b/FreeRTOS/Source/include/FreeRTOS.h @@ -535,11 +535,11 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #endif #ifndef configPRE_SLEEP_PROCESSING - #define configPRE_SLEEP_PROCESSING() + #define configPRE_SLEEP_PROCESSING( x ) #endif #ifndef configPOST_SLEEP_PROCESSING - #define configPOST_SLEEP_PROCESSING() + #define configPOST_SLEEP_PROCESSING( x ) #endif #endif /* INC_FREERTOS_H */ diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c index 440109489..206f484f5 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c @@ -83,15 +83,7 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */ #ifndef configSYSTICK_CLOCK_HZ #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ - #if configUSE_TICKLESS_IDLE == 1 - static const unsigned long ulStoppedTimerCompensation = 45UL; - #endif -#else /* configSYSTICK_CLOCK_HZ */ - #if configUSE_TICKLESS_IDLE == 1 - /* Assumes the SysTick clock is slower than the CPU clock. */ - static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - #endif -#endif /* configSYSTICK_CLOCK_HZ */ +#endif /* Constants required to manipulate the core. Registers first... */ #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) @@ -123,9 +115,11 @@ variable. */ static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; /* - * Setup the timer to generate the tick interrupts. + * 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 + * generate the tick interrupt. */ -static void prvSetupTimerInterrupt( void ); +void vPortSetupTimerInterrupt( void ); /* * Exception handlers. @@ -144,7 +138,9 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked )); /* * The number of SysTick increments that make up one tick period. */ -static unsigned long ulTimerReloadValueForOneTick = 0; +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulTimerReloadValueForOneTick = 0; +#endif /* * The maximum number of tick periods that can be suppressed is limited by the @@ -154,6 +150,13 @@ static unsigned long ulTimerReloadValueForOneTick = 0; static unsigned long xMaximumPossibleSuppressedTicks = 0; #endif /* configUSE_TICKLESS_IDLE */ +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ @@ -226,7 +229,7 @@ portBASE_TYPE xPortStartScheduler( void ) /* Start the timer that generates the tick ISR. Interrupts are disabled here already. */ - prvSetupTimerInterrupt(); + vPortSetupTimerInterrupt(); /* Initialise the critical nesting count ready for the first task. */ uxCriticalNesting = 0; @@ -295,6 +298,9 @@ __attribute__(( naked )) void vPortClearInterruptMask( unsigned long ulNewMaskVa " bx lr \n" \ :::"r0" \ ); + + /* Just to avoid compiler warnings. */ + ( void ) ulNewMaskValue; } /*-----------------------------------------------------------*/ @@ -340,6 +346,10 @@ void xPortSysTickHandler( void ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; #endif + /* Only reset the systick load register if configUSE_TICKLESS_IDLE is set to + 1. If it is set to 0 tickless idle is not being used. If it is set to a + value other than 0 or 1 then a timer other than the SysTick is being used + to generate the tick interrupt. */ #if configUSE_TICKLESS_IDLE == 1 portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; #endif @@ -403,9 +413,12 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. */ - configPRE_SLEEP_PROCESSING(); - __asm volatile( "wfi" ); - configPOST_SLEEP_PROCESSING(); + configPRE_SLEEP_PROCESSING( xExpectedIdleTime ); + if( xExpectedIdleTime > 0 ) + { + __asm volatile( "wfi" ); + } + 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 @@ -460,16 +473,19 @@ void xPortSysTickHandler( void ) * Setup the systick timer to generate the tick interrupts at the required * frequency. */ -void prvSetupTimerInterrupt( void ) +__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) { - /* Calculate the constants required to configure the tick interrupt. */ - ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + /* Calculate the constants required to configure the tick interrupt. */ #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); + ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } #endif /* configUSE_TICKLESS_IDLE */ /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c index 41da9a79e..b9394cc55 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c @@ -80,15 +80,7 @@ #ifndef configSYSTICK_CLOCK_HZ #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ - #if configUSE_TICKLESS_IDLE == 1 - static const unsigned long ulStoppedTimerCompensation = 45UL; - #endif -#else /* configSYSTICK_CLOCK_HZ */ - #if configUSE_TICKLESS_IDLE == 1 - /* Assumes the SysTick clock is slower than the CPU clock. */ - static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - #endif -#endif /* configSYSTICK_CLOCK_HZ */ +#endif /* Constants required to manipulate the core. Registers first... */ #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) @@ -125,9 +117,11 @@ variable. */ static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; /* - * Setup the timer to generate the tick interrupts. + * 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 + * generate the tick interrupt. */ -static void prvSetupTimerInterrupt( void ); +void vPortSetupTimerInterrupt( void ); /* * Exception handlers. @@ -151,7 +145,9 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked )); /* * The number of SysTick increments that make up one tick period. */ -static unsigned long ulTimerReloadValueForOneTick = 0; +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulTimerReloadValueForOneTick = 0; +#endif /* * The maximum number of tick periods that can be suppressed is limited by the @@ -161,6 +157,13 @@ static unsigned long ulTimerReloadValueForOneTick = 0; static unsigned long xMaximumPossibleSuppressedTicks = 0; #endif /* configUSE_TICKLESS_IDLE */ +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ @@ -244,7 +247,7 @@ portBASE_TYPE xPortStartScheduler( void ) /* Start the timer that generates the tick ISR. Interrupts are disabled here already. */ - prvSetupTimerInterrupt(); + vPortSetupTimerInterrupt(); /* Initialise the critical nesting count ready for the first task. */ uxCriticalNesting = 0; @@ -375,6 +378,10 @@ void xPortSysTickHandler( void ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; #endif + /* Only reset the systick load register if configUSE_TICKLESS_IDLE is set to + 1. If it is set to 0 tickless idle is not being used. If it is set to a + value other than 0 or 1 then a timer other than the SysTick is being used + to generate the tick interrupt. */ #if configUSE_TICKLESS_IDLE == 1 portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; #endif @@ -438,9 +445,12 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. */ - configPRE_SLEEP_PROCESSING(); - __asm volatile( "wfi" ); - configPOST_SLEEP_PROCESSING(); + configPRE_SLEEP_PROCESSING( xExpectedIdleTime ); + if( xExpectedIdleTime > 0 ) + { + __asm volatile( "wfi" ); + } + 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 @@ -495,17 +505,19 @@ void xPortSysTickHandler( void ) * Setup the systick timer to generate the tick interrupts at the required * frequency. */ -void prvSetupTimerInterrupt( void ) +__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) { - /* Calculate the constants required to configure the tick interrupt. */ - ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + /* Calculate the constants required to configure the tick interrupt. */ #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); + ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } #endif /* configUSE_TICKLESS_IDLE */ - /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h b/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h index d74c9bb2c..5bdcc58f0 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h +++ b/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h @@ -111,9 +111,7 @@ extern "C" { /* Scheduler utilities. */ extern void vPortYieldFromISR( void ); - #define portYIELD() vPortYieldFromISR() - #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR() /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c index 2601d5035..c501e7259 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c +++ b/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c @@ -1,7 +1,7 @@ /* FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd. - FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT + FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. *************************************************************************** @@ -42,7 +42,7 @@ FreeRTOS WEB site. 1 tab == 4 spaces! - + *************************************************************************** * * * Having a problem? Start by reading the FAQ "My application does * @@ -52,17 +52,17 @@ * * *************************************************************************** - - http://www.FreeRTOS.org - Documentation, training, latest versions, license - and contact details. - + + http://www.FreeRTOS.org - Documentation, training, latest versions, license + and contact details. + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool. - Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell - the code with commercial support, indemnification, and middleware, under + Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell + the code with commercial support, indemnification, and middleware, under the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also - provide a safety engineered and independently SIL3 certified version under + provide a safety engineered and independently SIL3 certified version under the SafeRTOS brand: http://www.SafeRTOS.com. */ @@ -70,6 +70,9 @@ * Implementation of functions defined in portable.h for the ARM CM3 port. *----------------------------------------------------------*/ +/* IAR includes. */ +#include + /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" @@ -80,15 +83,7 @@ #ifndef configSYSTICK_CLOCK_HZ #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ - #if configUSE_TICKLESS_IDLE == 1 - static const unsigned long ulStoppedTimerCompensation = 45UL; - #endif -#else /* configSYSTICK_CLOCK_HZ */ - #if configUSE_TICKLESS_IDLE == 1 - /* Assumes the SysTick clock is slower than the CPU clock. */ - static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - #endif -#endif /* configSYSTICK_CLOCK_HZ */ +#endif /* Constants required to manipulate the core. Registers first... */ #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) @@ -123,9 +118,11 @@ variable. */ static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; /* - * Setup the timer to generate the tick interrupts. + * 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 + * generate the tick interrupt. */ -static void prvSetupTimerInterrupt( void ); +void vPortSetupTimerInterrupt( void ); /* * Exception handlers. @@ -142,7 +139,9 @@ extern void vPortStartFirstTask( void ); /* * The number of SysTick increments that make up one tick period. */ -static unsigned long ulTimerReloadValueForOneTick = 0; +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulTimerReloadValueForOneTick = 0; +#endif /* * The maximum number of tick periods that can be suppressed is limited by the @@ -152,6 +151,14 @@ static unsigned long ulTimerReloadValueForOneTick = 0; static unsigned long xMaximumPossibleSuppressedTicks = 0; #endif /* configUSE_TICKLESS_IDLE */ +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + /*-----------------------------------------------------------*/ /* @@ -186,7 +193,7 @@ portBASE_TYPE xPortStartScheduler( void ) /* Start the timer that generates the tick ISR. Interrupts are disabled here already. */ - prvSetupTimerInterrupt(); + vPortSetupTimerInterrupt(); /* Initialise the critical nesting count ready for the first task. */ uxCriticalNesting = 0; @@ -237,6 +244,10 @@ void xPortSysTickHandler( void ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; #endif + /* Only reset the systick load register if configUSE_TICKLESS_IDLE is set to + 1. If it is set to 0 tickless idle is not being used. If it is set to a + value other than 0 or 1 then a timer other than the SysTick is being used + to generate the tick interrupt. */ #if configUSE_TICKLESS_IDLE == 1 portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; #endif @@ -300,9 +311,12 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. */ - configPRE_SLEEP_PROCESSING(); - __WFI(); - configPOST_SLEEP_PROCESSING(); + configPRE_SLEEP_PROCESSING( xExpectedIdleTime ); + if( xExpectedIdleTime > 0 ) + { + __WFI(); + } + 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 @@ -357,16 +371,19 @@ void xPortSysTickHandler( void ) * Setup the systick timer to generate the tick interrupts at the required * frequency. */ -void prvSetupTimerInterrupt( void ) +__weak void vPortSetupTimerInterrupt( void ) { - /* Configure the constants required to setup the tick interrupt. */ - ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + /* Calculate the constants required to configure the tick interrupt. */ #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); + ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } #endif /* configUSE_TICKLESS_IDLE */ /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c index 3ee8eb349..f6434caef 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c +++ b/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c @@ -1,7 +1,7 @@ /* FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd. - FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT + FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. *************************************************************************** @@ -42,7 +42,7 @@ FreeRTOS WEB site. 1 tab == 4 spaces! - + *************************************************************************** * * * Having a problem? Start by reading the FAQ "My application does * @@ -52,17 +52,17 @@ * * *************************************************************************** - - http://www.FreeRTOS.org - Documentation, training, latest versions, license - and contact details. - + + http://www.FreeRTOS.org - Documentation, training, latest versions, license + and contact details. + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool. - Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell - the code with commercial support, indemnification, and middleware, under + Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell + the code with commercial support, indemnification, and middleware, under the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also - provide a safety engineered and independently SIL3 certified version under + provide a safety engineered and independently SIL3 certified version under the SafeRTOS brand: http://www.SafeRTOS.com. */ @@ -70,6 +70,9 @@ * Implementation of functions defined in portable.h for the ARM CM4F port. *----------------------------------------------------------*/ +/* Compiler includes. */ +#include + /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" @@ -84,15 +87,7 @@ #ifndef configSYSTICK_CLOCK_HZ #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ - #if configUSE_TICKLESS_IDLE == 1 - static const unsigned long ulStoppedTimerCompensation = 45UL; - #endif -#else /* configSYSTICK_CLOCK_HZ */ - #if configUSE_TICKLESS_IDLE == 1 - /* Assumes the SysTick clock is slower than the CPU clock. */ - static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - #endif -#endif /* configSYSTICK_CLOCK_HZ */ +#endif /* Constants required to manipulate the core. Registers first... */ #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) @@ -125,9 +120,11 @@ variable. */ static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; /* - * Setup the timer to generate the tick interrupts. + * 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 + * generate the tick interrupt. */ -static void prvSetupTimerInterrupt( void ); +void vPortSetupTimerInterrupt( void ); /* * Exception handlers. @@ -149,7 +146,9 @@ extern void vPortEnableVFP( void ); /* * The number of SysTick increments that make up one tick period. */ -static unsigned long ulTimerReloadValueForOneTick = 0; +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulTimerReloadValueForOneTick = 0; +#endif /* * The maximum number of tick periods that can be suppressed is limited by the @@ -159,6 +158,14 @@ static unsigned long ulTimerReloadValueForOneTick = 0; static unsigned long xMaximumPossibleSuppressedTicks = 0; #endif /* configUSE_TICKLESS_IDLE */ +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + /*-----------------------------------------------------------*/ /* @@ -205,7 +212,7 @@ portBASE_TYPE xPortStartScheduler( void ) /* Start the timer that generates the tick ISR. Interrupts are disabled here already. */ - prvSetupTimerInterrupt(); + vPortSetupTimerInterrupt(); /* Initialise the critical nesting count ready for the first task. */ uxCriticalNesting = 0; @@ -262,6 +269,10 @@ void xPortSysTickHandler( void ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; #endif + /* Only reset the systick load register if configUSE_TICKLESS_IDLE is set to + 1. If it is set to 0 tickless idle is not being used. If it is set to a + value other than 0 or 1 then a timer other than the SysTick is being used + to generate the tick interrupt. */ #if configUSE_TICKLESS_IDLE == 1 portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; #endif @@ -325,9 +336,12 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. */ - configPRE_SLEEP_PROCESSING(); - __WFI(); - configPOST_SLEEP_PROCESSING(); + configPRE_SLEEP_PROCESSING( xExpectedIdleTime ); + if( xExpectedIdleTime > 0 ) + { + __WFI(); + } + 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 @@ -382,16 +396,19 @@ void xPortSysTickHandler( void ) * Setup the systick timer to generate the tick interrupts at the required * frequency. */ -void prvSetupTimerInterrupt( void ) +__weak void vPortSetupTimerInterrupt( void ) { - /* Configure the constants required to setup the tick interrupt. */ - ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + /* Calculate the constants required to configure the tick interrupt. */ #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); + ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } #endif /* configUSE_TICKLESS_IDLE */ /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c index 5c3a5534e..be3d8e643 100644 --- a/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c +++ b/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c @@ -84,15 +84,16 @@ #ifndef configSYSTICK_CLOCK_HZ #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ - #if configUSE_TICKLESS_IDLE == 1 - static const unsigned long ulStoppedTimerCompensation = 45UL; - #endif -#else /* configSYSTICK_CLOCK_HZ */ - #if configUSE_TICKLESS_IDLE == 1 - /* Assumes the SysTick clock is slower than the CPU clock. */ - static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - #endif -#endif /* configSYSTICK_CLOCK_HZ */ +#endif + +/* The __weak attribute does not work as you might expect with the Keil tools +so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if +the application writer wants to provide their own implementation of +vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION +is defined. */ +#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION + #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 +#endif /* Constants required to manipulate the core. Registers first... */ #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) @@ -120,9 +121,11 @@ variable. */ static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; /* - * Setup the timer to generate the tick interrupts. + * 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 + * generate the tick interrupt. */ -static void prvSetupTimerInterrupt( void ); +void vPortSetupTimerInterrupt( void ); /* * Exception handlers. @@ -141,7 +144,9 @@ static void prvStartFirstTask( void ); /* * The number of SysTick increments that make up one tick period. */ -static unsigned long ulTimerReloadValueForOneTick = 0; +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulTimerReloadValueForOneTick = 0; +#endif /* * The maximum number of tick periods that can be suppressed is limited by the @@ -151,6 +156,14 @@ static unsigned long ulTimerReloadValueForOneTick = 0; static unsigned long xMaximumPossibleSuppressedTicks = 0; #endif /* configUSE_TICKLESS_IDLE */ +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + /*-----------------------------------------------------------*/ /* @@ -219,7 +232,7 @@ portBASE_TYPE xPortStartScheduler( void ) /* Start the timer that generates the tick ISR. Interrupts are disabled here already. */ - prvSetupTimerInterrupt(); + vPortSetupTimerInterrupt(); /* Initialise the critical nesting count ready for the first task. */ uxCriticalNesting = 0; @@ -305,6 +318,10 @@ void xPortSysTickHandler( void ) } #endif + /* Only reset the systick load register if configUSE_TICKLESS_IDLE is set to + 1. If it is set to 0 tickless idle is not being used. If it is set to a + value other than 0 or 1 then a timer other than the SysTick is being used + to generate the tick interrupt. */ #if configUSE_TICKLESS_IDLE == 1 portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; #endif @@ -368,9 +385,12 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. */ - configPRE_SLEEP_PROCESSING(); - __wfi(); - configPOST_SLEEP_PROCESSING(); + configPRE_SLEEP_PROCESSING( xExpectedIdleTime ); + if( xExpectedIdleTime > 0 ) + { + __wfi(); + } + 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 @@ -426,18 +446,25 @@ void xPortSysTickHandler( void ) * Setup the SysTick timer to generate the tick interrupts at the required * frequency. */ -void prvSetupTimerInterrupt( void ) -{ - /* Calculate the constants required to configure the tick interrupt. */ - ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - #if configUSE_TICKLESS_IDLE == 1 - xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); - #endif /* configUSE_TICKLESS_IDLE */ +#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 - /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; -} + void vPortSetupTimerInterrupt( void ) + { + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); + ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + } + +#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ /*-----------------------------------------------------------*/ __asm unsigned long ulPortSetInterruptMask( void ) @@ -449,7 +476,6 @@ __asm unsigned long ulPortSetInterruptMask( void ) msr basepri, r1 bx r14 } - /*-----------------------------------------------------------*/ __asm void vPortClearInterruptMask( unsigned long ulNewMask ) diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c index 02818c5e2..2c2c4c79a 100644 --- a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c +++ b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c @@ -84,15 +84,16 @@ #ifndef configSYSTICK_CLOCK_HZ #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ - #if configUSE_TICKLESS_IDLE == 1 - static const unsigned long ulStoppedTimerCompensation = 45UL; - #endif -#else /* configSYSTICK_CLOCK_HZ */ - #if configUSE_TICKLESS_IDLE == 1 - /* Assumes the SysTick clock is slower than the CPU clock. */ - static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - #endif -#endif /* configSYSTICK_CLOCK_HZ */ +#endif + +/* The __weak attribute does not work as you might expect with the Keil tools +so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if +the application writer wants to provide their own implementation of +vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION +is defined. */ +#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION + #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 +#endif /* Constants required to manipulate the core. Registers first... */ #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000e010 ) ) @@ -125,9 +126,11 @@ variable. */ static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; /* - * Setup the timer to generate the tick interrupts. + * 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 + * generate the tick interrupt. */ -static void prvSetupTimerInterrupt( void ); +void vPortSetupTimerInterrupt( void ); /* * Exception handlers. @@ -150,7 +153,9 @@ static void prvEnableVFP( void ); /* * The number of SysTick increments that make up one tick period. */ -static unsigned long ulTimerReloadValueForOneTick = 0; +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulTimerReloadValueForOneTick = 0; +#endif /* * The maximum number of tick periods that can be suppressed is limited by the @@ -160,6 +165,14 @@ static unsigned long ulTimerReloadValueForOneTick = 0; static unsigned long xMaximumPossibleSuppressedTicks = 0; #endif /* configUSE_TICKLESS_IDLE */ +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if configUSE_TICKLESS_IDLE == 1 + static unsigned long ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ + /*-----------------------------------------------------------*/ /* @@ -257,7 +270,7 @@ portBASE_TYPE xPortStartScheduler( void ) /* Start the timer that generates the tick ISR. Interrupts are disabled here already. */ - prvSetupTimerInterrupt(); + vPortSetupTimerInterrupt(); /* Initialise the critical nesting count ready for the first task. */ uxCriticalNesting = 0; @@ -368,6 +381,10 @@ void xPortSysTickHandler( void ) } #endif + /* Only reset the systick load register if configUSE_TICKLESS_IDLE is set to + 1. If it is set to 0 tickless idle is not being used. If it is set to a + value other than 0 or 1 then a timer other than the SysTick is being used + to generate the tick interrupt. */ #if configUSE_TICKLESS_IDLE == 1 portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; #endif @@ -431,9 +448,12 @@ void xPortSysTickHandler( void ) portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; /* Sleep until something happens. */ - configPRE_SLEEP_PROCESSING(); - __wfi(); - configPOST_SLEEP_PROCESSING(); + configPRE_SLEEP_PROCESSING( xExpectedIdleTime ); + if( xExpectedIdleTime > 0 ) + { + __wfi(); + } + 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 @@ -486,21 +506,28 @@ void xPortSysTickHandler( void ) /*-----------------------------------------------------------*/ /* - * Setup the systick timer to generate the tick interrupts at the required + * Setup the SysTick timer to generate the tick interrupts at the required * frequency. */ -void prvSetupTimerInterrupt( void ) -{ - /* Calculate the constants required to configure the tick interrupt. */ - ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - #if configUSE_TICKLESS_IDLE == 1 - xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); - #endif /* configUSE_TICKLESS_IDLE */ +#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 - /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; -} + void vPortSetupTimerInterrupt( void ) + { + /* Calculate the constants required to configure the tick interrupt. */ + #if configUSE_TICKLESS_IDLE == 1 + { + ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL ); + ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;; + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + } + +#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ /*-----------------------------------------------------------*/ __asm unsigned long ulPortSetInterruptMask( void ) @@ -512,7 +539,6 @@ __asm unsigned long ulPortSetInterruptMask( void ) msr basepri, r1 bx r14 } - /*-----------------------------------------------------------*/ __asm void vPortClearInterruptMask( unsigned long ulNewMask ) diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index ef6208fc9..a7800fcc1 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -1,7 +1,7 @@ /* FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd. - FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT + FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. *************************************************************************** @@ -42,7 +42,7 @@ FreeRTOS WEB site. 1 tab == 4 spaces! - + *************************************************************************** * * * Having a problem? Start by reading the FAQ "My application does * @@ -52,17 +52,17 @@ * * *************************************************************************** - - http://www.FreeRTOS.org - Documentation, training, latest versions, license - and contact details. - + + http://www.FreeRTOS.org - Documentation, training, latest versions, license + and contact details. + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, including FreeRTOS+Trace - an indispensable productivity tool. - Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell - the code with commercial support, indemnification, and middleware, under + Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell + the code with commercial support, indemnification, and middleware, under the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also - provide a safety engineered and independently SIL3 certified version under + provide a safety engineered and independently SIL3 certified version under the SafeRTOS brand: http://www.SafeRTOS.com. */ @@ -463,8 +463,13 @@ static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TY /* * Return the amount of time, in ticks, that will pass before the kernel will * next move a task from the Blocked state to the Running state. + * + * This conditional compilation should use inequality to 0, not equality to 1. + * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user + * defined low power mode implementations require configUSE_TICKLESS_IDLE to be + * set to a value other than 1. */ -#if ( configUSE_TICKLESS_IDLE == 1 ) +#if ( configUSE_TICKLESS_IDLE != 0 ) static portTickType prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION; @@ -1314,28 +1319,32 @@ void vTaskSuspendAll( void ) } /*----------------------------------------------------------*/ -portTickType prvGetExpectedIdleTime( void ) -{ -portTickType xReturn; +#if ( configUSE_TICKLESS_IDLE != 0 ) - if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY ) + portTickType prvGetExpectedIdleTime( void ) { - xReturn = 0; - } - else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) - { - /* There are other idle priority tasks in the ready state. If - time slicing is used then the very next tick interrupt must be - processed. */ - xReturn = 0; - } - else - { - xReturn = xNextTaskUnblockTime - xTickCount; + portTickType xReturn; + + if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY ) + { + xReturn = 0; + } + else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) + { + /* There are other idle priority tasks in the ready state. If + time slicing is used then the very next tick interrupt must be + processed. */ + xReturn = 0; + } + else + { + xReturn = xNextTaskUnblockTime - xTickCount; + } + + return xReturn; } - return xReturn; -} +#endif /* configUSE_TICKLESS_IDLE != 0 */ /*----------------------------------------------------------*/ signed portBASE_TYPE xTaskResumeAll( void ) @@ -1627,7 +1636,11 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) #endif /*----------------------------------------------------------*/ -#if ( configUSE_TICKLESS_IDLE == 1 ) +/* This conditional compilation should use inequality to 0, not equality to 1. +This is to ensure vTaskStepTick() is available when user defined low power mode +implementations require configUSE_TICKLESS_IDLE to be set to a value other than +1. */ +#if ( configUSE_TICKLESS_IDLE != 0 ) void vTaskStepTick( portTickType xTicksToJump ) { @@ -2146,7 +2159,11 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) } #endif - #if ( configUSE_TICKLESS_IDLE == 1 ) + /* This conditional compilation should use inequality to 0, not equality + to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when + user defined low power mode implementations require + configUSE_TICKLESS_IDLE to be set to a value other than 1. */ + #if ( configUSE_TICKLESS_IDLE != 0 ) { portTickType xExpectedIdleTime; /* If the expected idle time is 1 then the idle time would end at @@ -2156,34 +2173,29 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) routines returns. */ const portTickType xMinimumExpectedIdleTime = ( portTickType ) 2; - /* Don't enter low power if there are still tasks waiting - deletion. */ - if( uxTasksDeleted == 0 ) + /* It is not desirable to suspend then resume the scheduler on + each iteration of the idle task. Therefore, a preliminary + test of the expected idle time is performed without the + scheduler suspended. The result here is not necessarily + valid. */ + xExpectedIdleTime = prvGetExpectedIdleTime(); + + if( xExpectedIdleTime >= xMinimumExpectedIdleTime ) { - /* It is not desirable to suspend then resume the scheduler on - each iteration of the idle task. Therefore, a preliminary - test of the expected idle time is performed without the - scheduler suspended. The result here is not necessarily - valid. */ - xExpectedIdleTime = prvGetExpectedIdleTime(); - - if( xExpectedIdleTime >= xMinimumExpectedIdleTime ) + vTaskSuspendAll(); { - vTaskSuspendAll(); - { - /* Now the scheduler is suspended, the expected idle - time can be sampled again, and this time its value can - be used. */ - configASSERT( xNextTaskUnblockTime >= xTickCount ); - xExpectedIdleTime = prvGetExpectedIdleTime(); + /* Now the scheduler is suspended, the expected idle + time can be sampled again, and this time its value can + be used. */ + configASSERT( xNextTaskUnblockTime >= xTickCount ); + xExpectedIdleTime = prvGetExpectedIdleTime(); - if( xExpectedIdleTime >= xMinimumExpectedIdleTime ) - { - portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); - } + if( xExpectedIdleTime >= xMinimumExpectedIdleTime ) + { + portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); } - xTaskResumeAll(); } + xTaskResumeAll(); } } #endif @@ -2328,7 +2340,7 @@ static void prvCheckTasksWaitingTermination( void ) /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called too often in the idle task. */ - if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U ) + while( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U ) { vTaskSuspendAll(); xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); -- 2.39.2