mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-01 08:54:14 -04:00
Make CM3/4 tick configuration a weak function to allow application writers to use an alternative tick source.
This commit is contained in:
parent
5e7c99d2aa
commit
ba686260ca
9 changed files with 338 additions and 214 deletions
|
@ -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()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue