|
|
@ -114,9 +114,6 @@ is defined. */
|
|
|
|
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
|
|
|
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
|
|
|
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
|
|
|
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
|
|
|
|
|
|
|
|
|
|
|
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
|
|
|
|
|
|
|
#define portVECTACTIVE_MASK ( 0xFFUL )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
|
|
|
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
|
|
|
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
|
|
|
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
|
|
|
|
|
|
|
|
|
|
@ -130,6 +127,9 @@ is defined. */
|
|
|
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
|
|
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
|
|
|
#define portPRIGROUP_SHIFT ( 8UL )
|
|
|
|
#define portPRIGROUP_SHIFT ( 8UL )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
|
|
|
|
|
|
|
#define portVECTACTIVE_MASK ( 0xFFUL )
|
|
|
|
|
|
|
|
|
|
|
|
/* Constants required to set up the initial stack. */
|
|
|
|
/* Constants required to set up the initial stack. */
|
|
|
|
#define portINITIAL_XPSR ( 0x01000000 )
|
|
|
|
#define portINITIAL_XPSR ( 0x01000000 )
|
|
|
|
|
|
|
|
|
|
|
@ -145,10 +145,6 @@ calculations. */
|
|
|
|
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
|
|
|
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
|
|
|
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
|
|
|
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
|
|
|
|
|
|
|
|
|
|
|
/* Each task maintains its own interrupt status in the critical nesting
|
|
|
|
|
|
|
|
variable. */
|
|
|
|
|
|
|
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Setup the timer to generate the tick interrupts. The implementation in this
|
|
|
|
* 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
|
|
|
|
* file is weak to allow application writers to change the timer used to
|
|
|
@ -175,10 +171,14 @@ static void prvTaskExitError( void );
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Each task maintains its own interrupt status in the critical nesting
|
|
|
|
|
|
|
|
variable. */
|
|
|
|
|
|
|
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* The number of SysTick increments that make up one tick period.
|
|
|
|
* The number of SysTick increments that make up one tick period.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
#if configUSE_TICKLESS_IDLE == 1
|
|
|
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
|
|
|
static uint32_t ulTimerCountsForOneTick = 0;
|
|
|
|
static uint32_t ulTimerCountsForOneTick = 0;
|
|
|
|
#endif /* configUSE_TICKLESS_IDLE */
|
|
|
|
#endif /* configUSE_TICKLESS_IDLE */
|
|
|
|
|
|
|
|
|
|
|
@ -186,7 +186,7 @@ static void prvTaskExitError( void );
|
|
|
|
* The maximum number of tick periods that can be suppressed is limited by the
|
|
|
|
* The maximum number of tick periods that can be suppressed is limited by the
|
|
|
|
* 24 bit resolution of the SysTick timer.
|
|
|
|
* 24 bit resolution of the SysTick timer.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
#if configUSE_TICKLESS_IDLE == 1
|
|
|
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
|
|
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
|
|
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
|
|
|
#endif /* configUSE_TICKLESS_IDLE */
|
|
|
|
#endif /* configUSE_TICKLESS_IDLE */
|
|
|
|
|
|
|
|
|
|
|
@ -194,7 +194,7 @@ static void prvTaskExitError( void );
|
|
|
|
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
|
|
|
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
|
|
|
* power functionality only.
|
|
|
|
* power functionality only.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
#if configUSE_TICKLESS_IDLE == 1
|
|
|
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
|
|
|
static uint32_t ulStoppedTimerCompensation = 0;
|
|
|
|
static uint32_t ulStoppedTimerCompensation = 0;
|
|
|
|
#endif /* configUSE_TICKLESS_IDLE */
|
|
|
|
#endif /* configUSE_TICKLESS_IDLE */
|
|
|
|
|
|
|
|
|
|
|
@ -313,6 +313,10 @@ BaseType_t xPortStartScheduler( void )
|
|
|
|
/* Read the value back to see how many bits stuck. */
|
|
|
|
/* Read the value back to see how many bits stuck. */
|
|
|
|
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
|
|
|
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The kernel interrupt priority should be set to the lowest
|
|
|
|
|
|
|
|
priority. */
|
|
|
|
|
|
|
|
configASSERT( ucMaxPriorityValue == ( configKERNEL_INTERRUPT_PRIORITY & ucMaxPriorityValue ) );
|
|
|
|
|
|
|
|
|
|
|
|
/* Use the same mask on the maximum system call priority. */
|
|
|
|
/* Use the same mask on the maximum system call priority. */
|
|
|
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
|
|
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
|
|
|
|
|
|
|
|
|
|
@ -467,11 +471,11 @@ void xPortSysTickHandler( void )
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
#if configUSE_TICKLESS_IDLE == 1
|
|
|
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
|
|
|
|
|
|
|
|
|
|
|
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
|
|
|
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
|
|
|
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
|
|
|
TickType_t xModifiableIdleTime;
|
|
|
|
TickType_t xModifiableIdleTime;
|
|
|
|
|
|
|
|
|
|
|
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
|
|
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
|
|
@ -547,23 +551,41 @@ void xPortSysTickHandler( void )
|
|
|
|
}
|
|
|
|
}
|
|
|
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
|
|
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
|
|
|
|
|
|
|
|
|
|
|
/* Stop SysTick. Again, the time the SysTick is stopped for is
|
|
|
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
|
|
|
accounted for as best it can be, but using the tickless mode will
|
|
|
|
out of sleep mode to execute immediately. see comments above
|
|
|
|
inevitably result in some tiny drift of the time maintained by the
|
|
|
|
__disable_interrupt() call above. */
|
|
|
|
kernel with respect to calendar time. */
|
|
|
|
|
|
|
|
ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
|
|
|
|
|
|
|
|
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Re-enable interrupts - see comments above __disable_irq() call
|
|
|
|
|
|
|
|
above. */
|
|
|
|
|
|
|
|
__enable_irq();
|
|
|
|
__enable_irq();
|
|
|
|
|
|
|
|
__dsb( portSY_FULL_READ_WRITE );
|
|
|
|
|
|
|
|
__isb( portSY_FULL_READ_WRITE );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Disable interrupts again because the clock is about to be stopped
|
|
|
|
|
|
|
|
and interrupts that execute while the clock is stopped will increase
|
|
|
|
|
|
|
|
any slippage between the time maintained by the RTOS and calendar
|
|
|
|
|
|
|
|
time. */
|
|
|
|
|
|
|
|
__disable_irq();
|
|
|
|
|
|
|
|
__dsb( portSY_FULL_READ_WRITE );
|
|
|
|
|
|
|
|
__isb( portSY_FULL_READ_WRITE );
|
|
|
|
|
|
|
|
|
|
|
|
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
|
|
|
/* Disable the SysTick clock without reading the
|
|
|
|
|
|
|
|
portNVIC_SYSTICK_CTRL_REG register to ensure the
|
|
|
|
|
|
|
|
portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
|
|
|
|
|
|
|
|
the time the SysTick is stopped for is accounted for as best it can
|
|
|
|
|
|
|
|
be, but using the tickless mode will inevitably result in some tiny
|
|
|
|
|
|
|
|
drift of the time maintained by the kernel with respect to calendar
|
|
|
|
|
|
|
|
time*/
|
|
|
|
|
|
|
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Determine if the SysTick clock has already counted to zero and
|
|
|
|
|
|
|
|
been set back to the current reload value (the reload back being
|
|
|
|
|
|
|
|
correct for the entire expected idle time) or if the SysTick is yet
|
|
|
|
|
|
|
|
to count to zero (in which case an interrupt other than the SysTick
|
|
|
|
|
|
|
|
must have brought the system out of sleep mode). */
|
|
|
|
|
|
|
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint32_t ulCalculatedLoadValue;
|
|
|
|
uint32_t ulCalculatedLoadValue;
|
|
|
|
|
|
|
|
|
|
|
|
/* The tick interrupt has already executed, and the SysTick
|
|
|
|
/* The tick interrupt is already pending, and the SysTick count
|
|
|
|
count reloaded with ulReloadValue. Reset the
|
|
|
|
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. */
|
|
|
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
|
|
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
|
|
@ -578,11 +600,9 @@ void xPortSysTickHandler( void )
|
|
|
|
|
|
|
|
|
|
|
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
|
|
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
|
|
|
|
|
|
|
|
|
|
|
/* The tick interrupt handler will already have pended the tick
|
|
|
|
/* As the pending tick will be processed as soon as this
|
|
|
|
processing in the kernel. As the pending tick will be
|
|
|
|
function exits, the tick value maintained by the tick is stepped
|
|
|
|
processed as soon as this function exits, the tick value
|
|
|
|
forward by one less than the time spent waiting. */
|
|
|
|
maintained by the tick is stepped forward by one less than the
|
|
|
|
|
|
|
|
time spent waiting. */
|
|
|
|
|
|
|
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
|
|
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
@ -604,17 +624,14 @@ void xPortSysTickHandler( void )
|
|
|
|
|
|
|
|
|
|
|
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
|
|
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
|
|
|
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
|
|
|
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
|
|
|
value. The critical section is used to ensure the tick interrupt
|
|
|
|
value. */
|
|
|
|
can only execute once in the case that the reload register is near
|
|
|
|
|
|
|
|
zero. */
|
|
|
|
|
|
|
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
|
|
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
|
|
|
portENTER_CRITICAL();
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
|
|
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
|
|
|
vTaskStepTick( ulCompleteTickPeriods );
|
|
|
|
vTaskStepTick( ulCompleteTickPeriods );
|
|
|
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
|
|
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
|
|
|
}
|
|
|
|
|
|
|
|
portEXIT_CRITICAL();
|
|
|
|
/* Exit with interrpts enabled. */
|
|
|
|
|
|
|
|
__enable_irq();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -626,12 +643,12 @@ 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.
|
|
|
|
* frequency.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0
|
|
|
|
#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
|
|
|
|
|
|
|
|
|
|
|
|
void vPortSetupTimerInterrupt( void )
|
|
|
|
void vPortSetupTimerInterrupt( void )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Calculate the constants required to configure the tick interrupt. */
|
|
|
|
/* Calculate the constants required to configure the tick interrupt. */
|
|
|
|
#if configUSE_TICKLESS_IDLE == 1
|
|
|
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
|
|
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
|
|
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
|
|
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
|
|
@ -714,7 +731,7 @@ __asm uint32_t vPortGetIPSR( void )
|
|
|
|
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
|
|
|
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
|
|
|
scheduler. Note however that some vendor specific peripheral libraries
|
|
|
|
scheduler. Note however that some vendor specific peripheral libraries
|
|
|
|
assume a non-zero priority group setting, in which cases using a value
|
|
|
|
assume a non-zero priority group setting, in which cases using a value
|
|
|
|
of zero will result in unpredicable behaviour. */
|
|
|
|
of zero will result in unpredictable behaviour. */
|
|
|
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
|
|
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|