mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-06-05 20:09:05 -04:00
Add some defensive programming in the default tickless mode in case the application supplied post tick hook takes a long time to complete.
This commit is contained in:
parent
aedf7824cb
commit
0c56f5018d
|
@ -547,12 +547,24 @@ void xPortSysTickHandler( void )
|
||||||
|
|
||||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
{
|
{
|
||||||
|
unsigned long ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt has already executed, and the SysTick
|
/* The tick interrupt has already executed, and the SysTick
|
||||||
count reloaded with ulReloadValue. Reset the
|
count reloaded with ulReloadValue. Reset the
|
||||||
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
period. */
|
period. */
|
||||||
portNVIC_SYSTICK_LOAD_REG = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt handler will already have pended the tick
|
/* The tick interrupt handler will already have pended the tick
|
||||||
processing in the kernel. As the pending tick will be
|
processing in the kernel. As the pending tick will be
|
||||||
processed as soon as this function exits, the tick value
|
processed as soon as this function exits, the tick value
|
||||||
|
|
|
@ -590,12 +590,24 @@ void xPortSysTickHandler( void )
|
||||||
|
|
||||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
{
|
{
|
||||||
|
unsigned long ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt has already executed, and the SysTick
|
/* The tick interrupt has already executed, and the SysTick
|
||||||
count reloaded with ulReloadValue. Reset the
|
count reloaded with ulReloadValue. Reset the
|
||||||
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
period. */
|
period. */
|
||||||
portNVIC_SYSTICK_LOAD_REG = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt handler will already have pended the tick
|
/* The tick interrupt handler will already have pended the tick
|
||||||
processing in the kernel. As the pending tick will be
|
processing in the kernel. As the pending tick will be
|
||||||
processed as soon as this function exits, the tick value
|
processed as soon as this function exits, the tick value
|
||||||
|
|
|
@ -440,12 +440,24 @@ void xPortSysTickHandler( void )
|
||||||
|
|
||||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
{
|
{
|
||||||
|
unsigned long ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt has already executed, and the SysTick
|
/* The tick interrupt has already executed, and the SysTick
|
||||||
count reloaded with ulReloadValue. Reset the
|
count reloaded with ulReloadValue. Reset the
|
||||||
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
period. */
|
period. */
|
||||||
portNVIC_SYSTICK_LOAD_REG = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt handler will already have pended the tick
|
/* The tick interrupt handler will already have pended the tick
|
||||||
processing in the kernel. As the pending tick will be
|
processing in the kernel. As the pending tick will be
|
||||||
processed as soon as this function exits, the tick value
|
processed as soon as this function exits, the tick value
|
||||||
|
|
|
@ -154,6 +154,11 @@ extern void vPortStartFirstTask( void );
|
||||||
*/
|
*/
|
||||||
extern void vPortEnableVFP( void );
|
extern void vPortEnableVFP( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to catch tasks that attempt to return from their implementing function.
|
||||||
|
*/
|
||||||
|
static void prvTaskExitError( void );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -208,7 +213,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
|
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = 0; /* LR */
|
*pxTopOfStack = ( portSTACK_TYPE ) prvTaskExitError; /* LR */
|
||||||
|
|
||||||
/* Save code space by skipping register initialisation. */
|
/* Save code space by skipping register initialisation. */
|
||||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||||
|
@ -225,6 +230,20 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTaskExitError( void )
|
||||||
|
{
|
||||||
|
/* A function that implements a task must not exit or attempt to return to
|
||||||
|
its caller as there is nothing to return to. If a task wants to exit it
|
||||||
|
should instead call vTaskDelete( NULL ).
|
||||||
|
|
||||||
|
Artificially force an assert() to be triggered if configASSERT() is
|
||||||
|
defined, then stop here so application writers can catch the error. */
|
||||||
|
configASSERT( uxCriticalNesting == ~0UL );
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
for( ;; );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See header file for description.
|
* See header file for description.
|
||||||
*/
|
*/
|
||||||
|
@ -393,9 +412,17 @@ void xPortSysTickHandler( void )
|
||||||
to be unsuspended then abandon the low power entry. */
|
to be unsuspended then abandon the low power entry. */
|
||||||
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
{
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
/* Restart SysTick. */
|
/* Restart SysTick. */
|
||||||
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
/* Re-enable interrupts - see comments above __disable_interrupt()
|
/* Re-enable interrupts - see comments above __disable_interrupt()
|
||||||
call above. */
|
call above. */
|
||||||
__enable_interrupt();
|
__enable_interrupt();
|
||||||
|
@ -439,12 +466,24 @@ void xPortSysTickHandler( void )
|
||||||
|
|
||||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
{
|
{
|
||||||
|
unsigned long ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt has already executed, and the SysTick
|
/* The tick interrupt has already executed, and the SysTick
|
||||||
count reloaded with ulReloadValue. Reset the
|
count reloaded with ulReloadValue. Reset the
|
||||||
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
period. */
|
period. */
|
||||||
portNVIC_SYSTICK_LOAD_REG = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt handler will already have pended the tick
|
/* The tick interrupt handler will already have pended the tick
|
||||||
processing in the kernel. As the pending tick will be
|
processing in the kernel. As the pending tick will be
|
||||||
processed as soon as this function exits, the tick value
|
processed as soon as this function exits, the tick value
|
||||||
|
|
|
@ -516,12 +516,24 @@ void xPortSysTickHandler( void )
|
||||||
|
|
||||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
{
|
{
|
||||||
|
unsigned long ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt has already executed, and the SysTick
|
/* The tick interrupt has already executed, and the SysTick
|
||||||
count reloaded with ulReloadValue. Reset the
|
count reloaded with ulReloadValue. Reset the
|
||||||
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
period. */
|
period. */
|
||||||
portNVIC_SYSTICK_LOAD_REG = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt handler will already have pended the tick
|
/* The tick interrupt handler will already have pended the tick
|
||||||
processing in the kernel. As the pending tick will be
|
processing in the kernel. As the pending tick will be
|
||||||
processed as soon as this function exits, the tick value
|
processed as soon as this function exits, the tick value
|
||||||
|
|
|
@ -587,12 +587,24 @@ void xPortSysTickHandler( void )
|
||||||
|
|
||||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
{
|
{
|
||||||
|
unsigned long ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt has already executed, and the SysTick
|
/* The tick interrupt has already executed, and the SysTick
|
||||||
count reloaded with ulReloadValue. Reset the
|
count reloaded with ulReloadValue. Reset the
|
||||||
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
period. */
|
period. */
|
||||||
portNVIC_SYSTICK_LOAD_REG = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
/* The tick interrupt handler will already have pended the tick
|
/* The tick interrupt handler will already have pended the tick
|
||||||
processing in the kernel. As the pending tick will be
|
processing in the kernel. As the pending tick will be
|
||||||
processed as soon as this function exits, the tick value
|
processed as soon as this function exits, the tick value
|
||||||
|
|
Loading…
Reference in a new issue