Make CM3/4 tick configuration a weak function to allow application writers to use an alternative tick source.

pull/4/head
Richard Barry 12 years ago
parent 5e7c99d2aa
commit ba686260ca

@ -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 */

@ -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;
}
/*-----------------------------------------------------------*/

@ -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;
}
/*-----------------------------------------------------------*/

@ -111,9 +111,7 @@ extern "C" {
/* Scheduler utilities. */
extern void vPortYieldFromISR( void );
#define portYIELD() vPortYieldFromISR()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
/*-----------------------------------------------------------*/

@ -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 <intrinsics.h>
/* 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;
}
/*-----------------------------------------------------------*/

@ -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 <intrinsics.h>
/* 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;
}
/*-----------------------------------------------------------*/

@ -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 )

@ -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 )

@ -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 );

Loading…
Cancel
Save