Task notification with fixed frequency timeout (ulTaskNotifyTakeUntil)

I am trying to use ulTaskNotifyTake in a manner that shifts the timeout similar to vTaskDelayUntil. Can you please review the following attempt? (Sorry for the formatting)

static portMUX_TYPE xTaskNotifyTakeUntilMutex = portMUX_INITIALIZER_UNLOCKED;

uint32_t ulTaskNotifyTakeUntil( TickType_t * const pxPreviousWakeTime, const BaseType_t xClearCountOnExit, const TickType_t xTimeIncrement ) {
  TickType_t timeToWake;
  bool shouldDelay = false;
  uint32_t count = 0;

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

  taskENTER_CRITICAL( &xTaskNotifyTakeUntilMutex );
  {
    /* Minor optimisation.  The tick count cannot change in this block. */
    const TickType_t origTickCount = xTaskGetTickCount();

    /* Generate the tick time at which the task wants to wake. */
    timeToWake = *pxPreviousWakeTime + xTimeIncrement;

    if (origTickCount < *pxPreviousWakeTime) {
      /* The tick count has overflowed since this function was lasted called.
         In this case the only time we should ever actually delay is if the wake
         time has also overflowed, and the wake time is greater than the tick
         time. When this is the case it is as if neither time had overflowed. */
      if (timeToWake < *pxPreviousWakeTime && timeToWake > origTickCount) {
       shouldDelay = true;
      }
    } else {
     /* The tick time has not overflowed. In this case we will delay if either
         the wake time has overflowed, and/or the	tick time is less than the
        wake time. */
	  if (timeToWake < *pxPreviousWakeTime || timeToWake > origTickCount) {
		shouldDelay = true;
	  }
    }

    /* Update the wake time ready for the next call. */
    *pxPreviousWakeTime = timeToWake;

    if (shouldDelay) {
	/* ulTaskNotifyTake() needs the block time, not the time to wake, so
   subtract the current tick count. */
      count = ulTaskNotifyTake( pdTRUE, timeToWake - origTickCount );
    }
  }
  taskEXIT_CRITICAL( &xTaskNotifyTakeUntilMutex );

  return count;
}

I found that using

in combination with task notifications works pretty well. Have a look at the provided example there.

Thank you for pointing that out. The example is a little different as work is repeatedly chipping away at a singular timeout. However, I guess that makes no difference. So perhaps the following will achieve executing a task at a fixed rate unless notified?

TimeOut_t xTimeOut;
vTaskSetTimeOutState( &xTimeOut );
TickType_t xTickPeriod = pdMS_TO_TICKS( 50 );
while (isActive()) {
  TickType_t xTicksToWait = xTickPeriod;
  step();
  if( ! xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) ) {
    ulTaskNotifyTake( pdTRUE, xTicksToWait );
  }
}

Exactly :+1: That’s very similar to the way I’m using it.