Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/FreeRTOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,14 @@
#define traceRETURN_vTaskDelete()
#endif

#ifndef traceENTER_xTaskPeriodicDelay
#define traceENTER_xTaskPeriodicDelay( pxPreviousWakeTime, xTimeIncrement )
#endif

#ifndef traceRETURN_xTaskPeriodicDelay
#define traceRETURN_xTaskPeriodicDelay( xIncrements )
#endif

#ifndef traceENTER_xTaskDelayUntil
#define traceENTER_xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement )
#endif
Expand Down
37 changes: 37 additions & 0 deletions include/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,43 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;
*/
void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION;

/**
* task. h
* @code{c}
* TickType_t xTaskPeriodicDelay( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
* @endcode
*
* INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be available.
* See the configuration section for more information.
*
* Periodic task delay to ensure a constant execution frequency.
*
* This function is similar to xTaskDelayUntil () with a few important differences:
* - pxPreviousWakeTime contains the last past wake time, so it never runs away
* - if you suspend the task, when you resume it pxPreviousWakeTime will instantly
* catch up all skipped increments
* - it returns the number of increments added to pxPreviosWakeTime
*
* @param pxPreviousWakeTime Pointer to a variable that holds the time at which the
* task was last unblocked. The variable must be initialised with the current time
* prior to its first use. Following this the variable is automatically updated.
*
* @param xTimeIncrement The cycle time period. The task will be unblocked at
* time *pxPreviousWakeTime + xTimeIncrement. Passing the same xTimeIncrement
* parameter value will cause the task to execute with a fixed interface period.
*
* @return Number of times xTimeIncrement has been added to pxPreviousWakeTime.
* It is 0 on the first call or if not enough ticks have been elapsed since the
* last call, 1 in normal circumstances or more than 1 if some period has been
* skipped for some reason (e.g. when the caller task is suspended for more than
* xTimeIncrement ticks).
*
* \defgroup xTaskPeriodicDelay xTaskPeriodicDelay
* \ingroup TaskCtrl
*/
TickType_t xTaskPeriodicDelay( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION;

/**
* task. h
* @code{c}
Expand Down
58 changes: 58 additions & 0 deletions tasks.c
Original file line number Diff line number Diff line change
Expand Up @@ -2374,6 +2374,64 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,

#if ( INCLUDE_xTaskDelayUntil == 1 )

TickType_t xTaskPeriodicDelay( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement )
{
BaseType_t xAlreadyYielded;
TickType_t xIncrements, xTicksIncrements, xTicksToWait;

traceENTER_xTaskPeriodicDelay( pxPreviousWakeTime, xTimeIncrement );

configASSERT( pxPreviousWakeTime );
configASSERT( xTimeIncrement > 0 );

vTaskSuspendAll();
{
/* This plays well with overflows */
const TickType_t xTicksElapsed = xTickCount - *pxPreviousWakeTime;

configASSERT( uxSchedulerSuspended == 1U );

/* Number of increments to catch up: it could be 0 if
* not enough ticks have elapsed, 1 in the common case or
* more than 1 if the task has not been resumed in time */
xIncrements = xTicksElapsed / xTimeIncrement;
xTicksIncrements = xIncrements * xTimeIncrement;

/* Update to the last wake time */
*pxPreviousWakeTime += xTicksIncrements;

/* Ticks to the next wake time */
xTicksToWait = xTimeIncrement - ( xTicksElapsed - xTicksIncrements );

if( xTicksToWait > 0 )
{
prvAddCurrentTaskToDelayedList( xTicksToWait, pdFALSE );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
xAlreadyYielded = xTaskResumeAll();

/* Force a reschedule if xTaskResumeAll has not already done so, we may
* have put ourselves to sleep. */
if( xAlreadyYielded == pdFALSE )
{
taskYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}

traceRETURN_xTaskPeriodicDelay( xIncrements );

return xIncrements;
}


BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement )
{
Expand Down
Loading