0
\$\begingroup\$

I was wondering how I can delay for longer periods of time using freertos function vTaskDelay(). Because the largest number you can store in a 16bit unsigned integer is 65535, the longest I can delay for is a little under 2 hours. I have currently implemented a method which uses a counter. Is this approach the best or is there another way?

  void vSomeTask(void) {
  static int16_t counter = 0;

  // DO SOMETHING

  //WAIT 24 Hours
  while (counter != 23) {
    vTaskDelay((1000*3600) / portTICK_RATE_MS);
    counter++
  }
    counter = 0;

  //DO SOMETHING ELSE AFTER ONE DAY DELAY


  vTaskDelete(NULL);
} 

EDIT: I just realized that because vTaskDelay is relative, it does not account for time that passes after the delay ends if other tasks of greater priority keep running. So a more refined approach would be to get the current time and instead use vTaskDelayUntil() because it's based of absolute time.

\$\endgroup\$
  • \$\begingroup\$ Usually you use counters, yes. Together with an on-chip hardware timer with the slowest pre-scaler value you can set. Waiting 24 hours may not be all that accurate though, depending on oscillator type. \$\endgroup\$ – Lundin Jul 7 '17 at 12:55
3
\$\begingroup\$

What you have proposed will work in concept, and at relatively low cost - though it might be implemented more cleanly as a for loop.

FreeRTOS's scheduled timer callback functions use the same TickType_t argument, so those won't be of a help to you.

However, it is worth noting that the 16 bit limit you mention is not actually fixed - rather it is configurable in FreeRTOSConfig.h

Defining configUSE_16_BIT_TICKS as 0 causes TickType_t to be defined (typedef'ed) as an unsigned 32bit type.

Using a 16 bit type will greatly improve performance on 8 and 16 bit architectures, but limits the maximum specifiable time period to 65535 'ticks'. Therefore, assuming a tick frequency of 250Hz, the maximum time a task can delay or block when a 16bit counter is used is 262 seconds, compared to 17179869 seconds when using a 32bit counter.

So especially if you have a 32-bit MCU you could consider using the larger type.

However, there will probably be many, many variables of TickType_t stored and used having nothing to do with your delay, and even on a 32 bit MCU this still costs memory, and your counting delay task will only wake up to count quite infrequently, so changing the data type for this purpose alone may not be worthwhile.

\$\endgroup\$
1
\$\begingroup\$

xTaskCheckForTimeout() will take care of timing, even when other tasks are executing in between. That should not be necessary though if you set configUSE_16_BIT_TICKS to 0, as already mentioned.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.