New API xTaskPeriodicDelay (#1349) (#1368)

* New API xTaskPeriodicDelay (#1349)

New function to be used for periodic tasks to ensure a constant
execution frequency. It is intended to supersede xTaskDelayUntil to
overcome its shortcomings, that is:

- avoid run away of pxPreviousWakeTime (#1339)
- catch up any skipped period immediately (and update pxPreviousWakeTime
  accordingly), notify the caller of the number of periods skipped (by
  returning them) and wait until the next period (it could be less than
  xTimeIncrement if we are close to the next period)
- notify the caller when not enough ticks have been elapsed (by
  returning 0) and handle the situation gracefully (by properly waiting
  until the next wake time)

Signed-off-by: Nicola Fontana <ntd@entidi.it>
Co-authored-by: Kody Stribrny <89810515+kstribrnAmzn@users.noreply.github.com>
This commit is contained in:
Nicola Fontana 2026-08-03 17:04:06 +02:00 • committed by GitHub
parent 4269c69a16
commit b178814998
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 94 additions and 0 deletions

49
tasks.c
View file

@ -2362,6 +2362,55 @@ STATIC void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
#if ( INCLUDE_xTaskDelayUntil == 1 )
TickType_t xTaskPeriodicDelay( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement )
{
TickType_t xIncrements, xTicksIncrements, xTicksToWait;
traceENTER_xTaskPeriodicDelay( pxPreviousWakeTime, xTimeIncrement );
configASSERT( pxPreviousWakeTime );
configASSERT( ( xTimeIncrement > 0U ) );
vTaskSuspendAll();
{
/* As long as everything is the same type, 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 );
prvAddCurrentTaskToDelayedList( xTicksToWait, pdFALSE );
}
/* Force a reschedule if xTaskResumeAll has not already done so, we may
* have put ourselves to sleep. */
if( xTaskResumeAll() == pdFALSE )
{
taskYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
traceRETURN_xTaskPeriodicDelay( xIncrements );
return xIncrements;
}
BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement )
{