+ Moved the History.txt file from the website git repo into the source code SVN repo.

+ Added xTaskCatchUpTicks() which corrects the tick count value after the application code has held interrupts disabled for an extended period.
+ Updated the xTaskResumeAll() implementation so it uses the new xTaskCatchUpTicks() function mentioned above to unwind ticks that were pended while the scheduler was suspended.
+ Various maintenance on the message buffer, stream buffer and abort delay demos.
+ Change type of uxPendedTicks from UBaseType_t to TickType_t to ensure it has same type as variables it is compared to, and therefore also rename the variable xPendingTicks.
+ Correct spelling mistake within a comment that was common to all the ARMv7-M ports.
pull/1/head
Richard Barry 6 years ago
parent 72af51cd86
commit 7d285f3dcb

@ -430,7 +430,7 @@ static void prvTestAbortingStreamBufferReceive( void )
{
TickType_t xTimeAtStart;
StreamBufferHandle_t xStreamBuffer;
EventBits_t xReturn;
size_t xReturn;
const size_t xTriggerLevelBytes = ( size_t ) 1;
uint8_t uxRxData;

@ -57,7 +57,7 @@ priority tasks, and from high to low priority tasks. */
#define mbHIGHER_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* Block times used when sending and receiving from the message buffers. */
#define mbRX_TX_BLOCK_TIME pdMS_TO_TICKS( 125UL )
#define mbRX_TX_BLOCK_TIME pdMS_TO_TICKS( 175UL )
/* A block time of 0 means "don't block". */
#define mbDONT_BLOCK ( 0 )
@ -245,8 +245,8 @@ UBaseType_t uxOriginalPriority;
xReturned = xMessageBufferSend( xMessageBuffer, ( void * ) pucData, sizeof( pucData[ 0 ] ), xBlockTime );
xTimeAfterCall = xTaskGetTickCount();
vTaskPrioritySet( NULL, uxOriginalPriority );
configASSERT( ( xTimeAfterCall - xTimeBeforeCall ) >= xBlockTime );
configASSERT( ( xTimeAfterCall - xTimeBeforeCall ) < ( xBlockTime + xAllowableMargin ) );
configASSERT( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) >= xBlockTime );
configASSERT( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) < ( xBlockTime + xAllowableMargin ) );
configASSERT( xReturned == 0 );
( void ) xReturned; /* In case configASSERT() is not defined. */
( void ) xTimeBeforeCall;
@ -758,7 +758,7 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 250UL );
/* Don't expect to receive anything yet! */
xTimeOnEntering = xTaskGetTickCount();
xReceivedLength = xMessageBufferReceive( xMessageBuffers.xEchoClientBuffer, ( void * ) pcReceivedString, mbMESSAGE_BUFFER_LENGTH_BYTES, xTicksToBlock );
configASSERT( ( xTaskGetTickCount() - xTimeOnEntering ) >= xTicksToBlock );
configASSERT( ( ( TickType_t ) ( xTaskGetTickCount() - xTimeOnEntering ) ) >= xTicksToBlock );
configASSERT( xReceivedLength == 0 );
( void ) xTimeOnEntering; /* In case configASSERT() is not defined. */

@ -283,8 +283,8 @@ UBaseType_t uxOriginalPriority;
xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( pucData[ 0 ] ), xBlockTime );
xTimeAfterCall = xTaskGetTickCount();
vTaskPrioritySet( NULL, uxOriginalPriority );
prvCheckExpectedState( ( xTimeAfterCall - xTimeBeforeCall ) >= xBlockTime );
prvCheckExpectedState( ( xTimeAfterCall - xTimeBeforeCall ) < ( xBlockTime + xAllowableMargin ) );
prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) >= xBlockTime );
prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) < ( xBlockTime + xAllowableMargin ) );
prvCheckExpectedState( xReturned == 0 );
/* The buffer is now full of data in the form "000000", "111111", etc. Make
@ -331,8 +331,8 @@ UBaseType_t uxOriginalPriority;
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucReadData, x6ByteLength, xBlockTime );
xTimeAfterCall = xTaskGetTickCount();
vTaskPrioritySet( NULL, uxOriginalPriority );
prvCheckExpectedState( ( xTimeAfterCall - xTimeBeforeCall ) >= xBlockTime );
prvCheckExpectedState( ( xTimeAfterCall - xTimeBeforeCall ) < ( xBlockTime + xAllowableMargin ) );
prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) >= xBlockTime );
prvCheckExpectedState( ( ( TickType_t ) ( xTimeAfterCall - xTimeBeforeCall ) ) < ( xBlockTime + xAllowableMargin ) );
prvCheckExpectedState( xReturned == 0 );
@ -847,7 +847,7 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 350UL );
/* Don't expect to receive anything yet! */
xTimeOnEntering = xTaskGetTickCount();
xReceivedLength = xStreamBufferReceive( xStreamBuffers.xEchoClientBuffer, ( void * ) pcReceivedString, sbSTREAM_BUFFER_LENGTH_BYTES, xTicksToBlock );
prvCheckExpectedState( ( xTaskGetTickCount() - xTimeOnEntering ) >= xTicksToBlock );
prvCheckExpectedState( ( ( TickType_t ) ( xTaskGetTickCount() - xTimeOnEntering ) ) >= xTicksToBlock );
prvCheckExpectedState( xReceivedLength == 0 );
/* Now the stream buffers have been created the echo client task can be
@ -933,6 +933,7 @@ BaseType_t xErrorDetected = pdFALSE;
{
/* Create the stream buffer that will be used from inside the tick
interrupt. */
memset( ucRxData, 0x00, sizeof( ucRxData ) );
xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );
configASSERT( xStreamBuffer );
@ -958,21 +959,34 @@ BaseType_t xErrorDetected = pdFALSE;
/* Now check the number of bytes received equals the trigger level,
except in the case that the read timed out before the trigger level
was reached. */
if( xBytesReceived < xTriggerLevel )
if( xTriggerLevel > xReadBlockTime )
{
/* This should only happen if the trigger level was greater than
the block time. */
if( xTriggerLevel < xReadBlockTime )
/* Trigger level was greater than the block time so expect to
time out having received xReadBlockTime bytes. */
if( ( xReadBlockTime - xBytesReceived ) > xAllowableMargin )
{
xErrorDetected = pdTRUE;
}
}
else if( ( xBytesReceived - xTriggerLevel ) > xAllowableMargin )
else if( xTriggerLevel < xReadBlockTime )
{
/* A margin may be required here if there are other high priority
tasks prevent the task that reads from the message buffer running
immediately. */
xErrorDetected = pdTRUE;
/* Trigger level was less than the block time so we expect to
have received the trigger level number of bytes. */
if( ( xTriggerLevel - xBytesReceived ) > xAllowableMargin )
{
xErrorDetected = pdTRUE;
}
}
else
{
/* The trigger level equaled the block time, so expect to
receive no greater than the block time, but one or two less is
ok due to variations in how far through the time slice the
functions get executed. */
if( xBytesReceived > xReadBlockTime )
{
xErrorDetected = pdTRUE;
}
}
if( xBytesReceived > sizeof( ucRxData ) )

File diff suppressed because it is too large Load Diff

@ -69,7 +69,7 @@ void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseTy
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) FREERTOS_SYSTEM_CALL;
TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL;
UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL;
TickType_t MPU_xTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL;
uint32_t MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskList( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) FREERTOS_SYSTEM_CALL;
@ -82,6 +82,7 @@ void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CAL
BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) FREERTOS_SYSTEM_CALL;
void MPU_vTaskMissedYield( void ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL;
BaseType_t MPU_xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) FREERTOS_SYSTEM_CALL;
/* MPU versions of queue.h API functions. */
BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) FREERTOS_SYSTEM_CALL;

@ -77,11 +77,12 @@ only for ports that are using the MPU. */
#define uxTaskGetSystemState MPU_uxTaskGetSystemState
#define vTaskList MPU_vTaskList
#define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats
#define xTaskGetIdleRunTimeCounter MPU_xTaskGetIdleRunTimeCounter
#define ulTaskGetIdleRunTimeCounter MPU_ulTaskGetIdleRunTimeCounter
#define xTaskGenericNotify MPU_xTaskGenericNotify
#define xTaskNotifyWait MPU_xTaskNotifyWait
#define ulTaskNotifyTake MPU_ulTaskNotifyTake
#define xTaskNotifyStateClear MPU_xTaskNotifyStateClear
#define xTaskCatchUpTicks MPU_xTaskCatchUpTicks
#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
#define vTaskSetTimeOutState MPU_vTaskSetTimeOutState

@ -1738,7 +1738,7 @@ void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e9
/**
* task. h
* <PRE>TickType_t xTaskGetIdleRunTimeCounter( void );</PRE>
* <PRE>uint32_t ulTaskGetIdleRunTimeCounter( void );</PRE>
*
* configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS
* must both be defined as 1 for this function to be available. The application
@ -1753,7 +1753,7 @@ void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e9
* of the accumulated time value depends on the frequency of the timer
* configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro.
* While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total
* execution time of each task into a buffer, xTaskGetIdleRunTimeCounter()
* execution time of each task into a buffer, ulTaskGetIdleRunTimeCounter()
* returns the total execution time of just the idle task.
*
* @return The total run time of the idle task. This is the amount of time the
@ -1761,10 +1761,10 @@ void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e9
* frequency configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and
* portGET_RUN_TIME_COUNTER_VALUE() macros.
*
* \defgroup xTaskGetIdleRunTimeCounter xTaskGetIdleRunTimeCounter
* \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter
* \ingroup TaskUtils
*/
TickType_t xTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION;
uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION;
/**
* task. h
@ -2383,6 +2383,19 @@ void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) PRIVIL
*/
void vTaskStepTick( const TickType_t xTicksToJump ) PRIVILEGED_FUNCTION;
/* Correct the tick count value after the application code has held
interrupts disabled for an extended period. xTicksToCatchUp is the number
of tick interrupts that have been missed due to interrupts being disabled.
Its value is not computed automatically, so must be computed by the
application writer.
This function is similar to vTaskStepTick(), however, unlike
vTaskStepTick(), xTaskCatchUpTicks() may move the tick count forward past a
time at which a task should be removed from the blocked state. That means
tasks may have to be removed from the blocked state as the tick count is
moved. */
BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION;
/*
* Only available when configUSE_TICKLESS_IDLE is set to 1.
* Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port

@ -505,7 +505,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__asm( " cpsie i" );
}
}

@ -528,7 +528,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__asm( " cpsie i" );
}
}

@ -602,7 +602,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__asm volatile( "cpsie i" ::: "memory" );
}
}

@ -664,7 +664,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__asm volatile( "cpsie i" ::: "memory" );
}
}

@ -654,7 +654,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__asm volatile( "cpsie i" ::: "memory" );
}
}

@ -504,7 +504,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__enable_interrupt();
}
}

@ -541,7 +541,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__enable_interrupt();
}
}

@ -529,7 +529,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__enable_interrupt();
}
}

@ -648,7 +648,7 @@ void xPortSysTickHandler( void ) iv IVT_INT_SysTick ics ICS_AUTO
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__asm { "cpsie i" };
}
}

@ -588,7 +588,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__enable_irq();
}
}

@ -678,7 +678,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__enable_irq();
}
}

@ -664,7 +664,7 @@ void xPortSysTickHandler( void )
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrpts enabled. */
/* Exit with interrupts enabled. */
__enable_irq();
}
}

@ -368,7 +368,7 @@ PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseTyp
PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U;
PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
@ -2175,6 +2175,7 @@ BaseType_t xTaskResumeAll( void )
{
TCB_t *pxTCB = NULL;
BaseType_t xAlreadyYielded = pdFALSE;
TickType_t xTicksToNextUnblockTime;
/* If uxSchedulerSuspended is zero then this function does not match a
previous call to vTaskSuspendAll(). */
@ -2229,30 +2230,51 @@ BaseType_t xAlreadyYielded = pdFALSE;
they should be processed now. This ensures the tick count does
not slip, and that any delayed tasks are resumed at the correct
time. */
while( xPendedTicks > ( TickType_t ) 0 )
{
UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */
/* Calculate how far into the future the next task will
leave the Blocked state because its timeout expired. If
there are no tasks due to leave the blocked state between
the time now and the time at which the tick count overflows
then xNextTaskUnblockTime will the tick overflow time.
This means xNextTaskUnblockTime can never be less than
xTickCount, and the following can therefore not
underflow. */
configASSERT( xNextTaskUnblockTime >= xTickCount );
xTicksToNextUnblockTime = xNextTaskUnblockTime - xTickCount;
if( uxPendedCounts > ( UBaseType_t ) 0U )
/* Don't want to move the tick count more than the number
of ticks that are pending, so cap if necessary. */
if( xTicksToNextUnblockTime > xPendedTicks )
{
do
{
if( xTaskIncrementTick() != pdFALSE )
{
xYieldPending = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
--uxPendedCounts;
} while( uxPendedCounts > ( UBaseType_t ) 0U );
xTicksToNextUnblockTime = xPendedTicks;
}
uxPendedTicks = 0;
if( xTicksToNextUnblockTime == 0 )
{
/* xTicksToNextUnblockTime could be zero if the tick
count is about to overflow and xTicksToNetUnblockTime
holds the time at which the tick count will overflow
(rather than the time at which the next task will
unblock). Set to 1 otherwise xPendedTicks won't be
decremented below. */
xTicksToNextUnblockTime = ( TickType_t ) 1;
}
else
else if( xTicksToNextUnblockTime > ( TickType_t ) 1 )
{
mtCOVERAGE_TEST_MARKER();
/* Move the tick count one short of the next unblock
time, then call xTaskIncrementTick() to move the tick
count up to the next unblock time to unblock the task,
if any. This will also swap the blocked task and
overflow blocked task lists if necessary. */
xTickCount += ( xTicksToNextUnblockTime - ( TickType_t ) 1 );
}
xYieldPending |= xTaskIncrementTick();
/* Adjust for the number of ticks just added to
xTickCount and go around the loop again if
xTicksToCatchUp is still greater than 0. */
xPendedTicks -= xTicksToNextUnblockTime;
}
if( xYieldPending != pdFALSE )
@ -2586,6 +2608,24 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
#endif /* configUSE_TICKLESS_IDLE */
/*----------------------------------------------------------*/
BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp )
{
BaseType_t xYieldRequired = pdFALSE;
/* Must not be called with the scheduler suspended as the implementation
relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */
configASSERT( uxSchedulerSuspended == 0 );
/* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occuring when
the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */
vTaskSuspendAll();
xPendedTicks += xTicksToCatchUp;
xYieldRequired = xTaskResumeAll();
return xYieldRequired;
}
/*----------------------------------------------------------*/
#if ( INCLUDE_xTaskAbortDelay == 1 )
BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
@ -2793,7 +2833,7 @@ BaseType_t xSwitchRequired = pdFALSE;
{
/* Guard against the tick hook being called when the pended tick
count is being unwound (when the scheduler is being unlocked). */
if( uxPendedTicks == ( UBaseType_t ) 0U )
if( xPendedTicks == ( TickType_t ) 0 )
{
vApplicationTickHook();
}
@ -2806,7 +2846,7 @@ BaseType_t xSwitchRequired = pdFALSE;
}
else
{
++uxPendedTicks;
++xPendedTicks;
/* The tick hook gets called at regular intervals, even if the
scheduler is locked. */
@ -5078,7 +5118,7 @@ TickType_t uxReturn;
#if( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
TickType_t xTaskGetIdleRunTimeCounter( void )
uint32_t ulTaskGetIdleRunTimeCounter( void )
{
return xIdleTaskHandle->ulRunTimeCounter;
}

Loading…
Cancel
Save