__weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )\r
{\r
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;\r
+ portTickType xModifiableIdleTime;\r
\r
/* Make sure the SysTick reload value does not overflow the counter. */\r
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )\r
kernel with respect to calendar time. */\r
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
\r
- /* If a context switch is pending then abandon the low power entry as\r
- the context switch might have been pended by an external interrupt that\r
- requires processing. */\r
- if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )\r
+ /* Adjust the reload value to take into account that the current\r
+ time slice is already partially complete. */\r
+ ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );\r
+\r
+ /* Enter a critical section but don't use the taskENTER_CRITICAL()\r
+ method as that will mask interrupts that should exit sleep mode. */\r
+ __disable_interrupt();\r
+\r
+ /* If a context switch is pending or a task is waiting for the scheduler\r
+ to be unsuspended then abandon the low power entry. */\r
+ if( eTaskConfirmSleepModeStatus() == eAbortSleep )\r
{\r
/* Restart SysTick. */\r
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+ /* Re-enable interrupts - see comments above __disable_interrupt()\r
+ call above. */\r
+ __enable_interrupt();\r
}\r
else\r
{\r
- /* Adjust the reload value to take into account that the current\r
- time slice is already partially complete. */\r
- ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );\r
+ /* Set the new reload value. */\r
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;\r
\r
/* Clear the SysTick count flag and set the count value back to\r
/* Restart SysTick. */\r
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
\r
- /* Sleep until something happens. */\r
- configPRE_SLEEP_PROCESSING( xExpectedIdleTime );\r
- if( xExpectedIdleTime > 0 )\r
+ /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can\r
+ set its parameter to 0 to indicate that its implementation contains\r
+ its own wait for interrupt or wait for event instruction, and so wfi\r
+ should not be executed again. However, the original expected idle\r
+ time variable must remain unmodified, so a copy is taken. */\r
+ xModifiableIdleTime = xExpectedIdleTime;\r
+ configPRE_SLEEP_PROCESSING( xModifiableIdleTime );\r
+ if( xModifiableIdleTime > 0 )\r
{\r
__WFI();\r
}\r
kernel with respect to calendar time. */\r
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
\r
+ /* Re-enable interrupts - see comments above __disable_interrupt()\r
+ call above. */\r
+ __enable_interrupt();\r
+\r
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )\r
{\r
/* The tick interrupt has already executed, and the SysTick\r
*/\r
__weak void vPortSetupTimerInterrupt( void )\r
{\r
- /* Calculate the constants required to configure the tick interrupt. */ \r
+ /* Calculate the constants required to configure the tick interrupt. */\r
#if configUSE_TICKLESS_IDLE == 1\r
{\r
ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r