Drift through k_sleep or k_msleep #api


Nikolaus Huber
 

Hi all, 

I was recently wondering about the correct usage of k_sleep or k_msleep for implementing periodic tasks. In FreeRTOS for example there is a function vTaskDelayUntil which takes a timestamp and a number of ticks to delay. By taking the timestamp at the beginning of the execution of a task we can then make sure that its release time does not slowly drift. So far I have not seen anything similar in Zephyr. Am I missing something, or do I have to somehow create a similar mechanism on my own by measuring the uptime at the release of a periodic task and then again just before using any sleep function to calculate the exact sleep time I want?

Thank you very much in advance,
Nick


Erik Englund
 

One possible solution is to create a periodic timer and post to a semaphore in the timer callback.
A thread could simply wait on the semaphore in an endless loop.

Linux clock_nanosleep (mostly used togheter with Preempt-rt patch) would be a nice addition to Zephyr, that would solve these kinds of tasks.

Med vänlig hälsning
Erik Englund

Innoware Development AB
Hyttvägen 13
73338 SALA


Org.nr. 556790-2977
www.innoware.se


Den ons 3 feb. 2021 kl 20:31 skrev Nikolaus Huber <nikolaus.huber@...>:

Hi all, 

I was recently wondering about the correct usage of k_sleep or k_msleep for implementing periodic tasks. In FreeRTOS for example there is a function vTaskDelayUntil which takes a timestamp and a number of ticks to delay. By taking the timestamp at the beginning of the execution of a task we can then make sure that its release time does not slowly drift. So far I have not seen anything similar in Zephyr. Am I missing something, or do I have to somehow create a similar mechanism on my own by measuring the uptime at the release of a periodic task and then again just before using any sleep function to calculate the exact sleep time I want?

Thank you very much in advance,
Nick


Lawrence King
 

When I need work to operate on a regular basis and not drift I create a work queue and a timer that is setup to submit the work to the queue on a regular basis. This way it doesn’t matter how long it takes to finish the work, the next work run will still start at exactly the right time. main() calls  clock_init() to get this started…

 

 

#include <stdio.h>

#include <stddef.h>

#include <stdint.h>

#include <zephyr.h>

#include <zephyr/types.h>

 

#define TIME_INC_FREQUENCY      10      // in secs

 

void my_work_handler(struct k_work *work)

{

     // do whatever here

}

 

K_WORK_DEFINE(my_work, my_work_handler);

 

void my_timer_handler(struct k_timer *dummy)

{

    k_work_submit(&my_work);

}

 

K_TIMER_DEFINE(my_timer, my_timer_handler, NULL);

 

void clock_init(void) {

    k_timer_start(&my_timer, K_SECONDS(TIME_INC_FREQUENCY), K_SECONDS(TIME_INC_FREQUENCY));

}

 

Lawrence King

Principal Developer

+1(416)627-7302

 

From: users@... <users@...> On Behalf Of Erik Englund
Sent: Wednesday, February 3, 2021 2:38 PM
To: Nikolaus Huber <nikolaus.huber@...>
Cc: users@...
Subject: Re: [Zephyr-users] Drift through k_sleep or k_msleep #api

 

One possible solution is to create a periodic timer and post to a semaphore in the timer callback.

A thread could simply wait on the semaphore in an endless loop.

 

Linux clock_nanosleep (mostly used togheter with Preempt-rt patch) would be a nice addition to Zephyr, that would solve these kinds of tasks.


Med vänlig hälsning

Erik Englund


Innoware Development AB
Hyttvägen 13
73338 SALA


Org.nr. 556790-2977
www.innoware.se

 

 

Den ons 3 feb. 2021 kl 20:31 skrev Nikolaus Huber <nikolaus.huber@...>:

Hi all, 

I was recently wondering about the correct usage of k_sleep or k_msleep for implementing periodic tasks. In FreeRTOS for example there is a function vTaskDelayUntil which takes a timestamp and a number of ticks to delay. By taking the timestamp at the beginning of the execution of a task we can then make sure that its release time does not slowly drift. So far I have not seen anything similar in Zephyr. Am I missing something, or do I have to somehow create a similar mechanism on my own by measuring the uptime at the release of a periodic task and then again just before using any sleep function to calculate the exact sleep time I want?

Thank you very much in advance,
Nick


Michael Rosen
 

Nick,

 

The design pattern Ive seen for this kind of thing uses the Timer API instead of sleep:

 

struct k_timer timer;

k_timer_init(&timer, NULL, NULL);

k_timer_start(&timer, 0, K_MSEC(1000));

while (1) {

  k_timer_status_sync(&timer);

  …

}

 

This lets the body of the main loop run only when the timer expires, and the periodic timer avoid drift from resetting the timer at the top of each loop.

 

Mike

 

From: users@... <users@...> On Behalf Of Erik Englund
Sent: Wednesday, February 3, 2021 2:38 PM
To: Nikolaus Huber <nikolaus.huber@...>
Cc: users@...
Subject: Re: [Zephyr-users] Drift through k_sleep or k_msleep #api

 

One possible solution is to create a periodic timer and post to a semaphore in the timer callback.

A thread could simply wait on the semaphore in an endless loop.

 

Linux clock_nanosleep (mostly used togheter with Preempt-rt patch) would be a nice addition to Zephyr, that would solve these kinds of tasks.


Med vänlig hälsning

Erik Englund


Innoware Development AB
Hyttvägen 13
73338 SALA


Org.nr. 556790-2977
www.innoware.se

 

 

Den ons 3 feb. 2021 kl 20:31 skrev Nikolaus Huber <nikolaus.huber@...>:

Hi all, 

I was recently wondering about the correct usage of k_sleep or k_msleep for implementing periodic tasks. In FreeRTOS for example there is a function vTaskDelayUntil which takes a timestamp and a number of ticks to delay. By taking the timestamp at the beginning of the execution of a task we can then make sure that its release time does not slowly drift. So far I have not seen anything similar in Zephyr. Am I missing something, or do I have to somehow create a similar mechanism on my own by measuring the uptime at the release of a periodic task and then again just before using any sleep function to calculate the exact sleep time I want?

Thank you very much in advance,
Nick


Erik Englund
 

I guess the internals of this uses a semaphore aswell to get realtime performance.

If you control the semaphore yourself as per my example, you can check the status of the semaphore in the end of the function to see if the timer has expired while the work was running, if so, you have a realtime problem.
We use this technique in Zephyr within a few PLC-type controller products, using 1000 ticks/second rate and cycletime of 10ms.

Med vänlig hälsning
Erik Englund

Innoware Development AB
Hyttvägen 13
73338 SALA


Org.nr. 556790-2977
www.innoware.se


Den ons 3 feb. 2021 kl 21:10 skrev Michael Rosen <michael.r.rosen@...>:

Nick,

 

The design pattern Ive seen for this kind of thing uses the Timer API instead of sleep:

 

struct k_timer timer;

k_timer_init(&timer, NULL, NULL);

k_timer_start(&timer, 0, K_MSEC(1000));

while (1) {

  k_timer_status_sync(&timer);

  …

}

 

This lets the body of the main loop run only when the timer expires, and the periodic timer avoid drift from resetting the timer at the top of each loop.

 

Mike

 

From: users@... <users@...> On Behalf Of Erik Englund
Sent: Wednesday, February 3, 2021 2:38 PM
To: Nikolaus Huber <nikolaus.huber@...>
Cc: users@...
Subject: Re: [Zephyr-users] Drift through k_sleep or k_msleep #api

 

One possible solution is to create a periodic timer and post to a semaphore in the timer callback.

A thread could simply wait on the semaphore in an endless loop.

 

Linux clock_nanosleep (mostly used togheter with Preempt-rt patch) would be a nice addition to Zephyr, that would solve these kinds of tasks.


Med vänlig hälsning

Erik Englund


Innoware Development AB
Hyttvägen 13
73338 SALA


Org.nr. 556790-2977
www.innoware.se

 

 

Den ons 3 feb. 2021 kl 20:31 skrev Nikolaus Huber <nikolaus.huber@...>:

Hi all, 

I was recently wondering about the correct usage of k_sleep or k_msleep for implementing periodic tasks. In FreeRTOS for example there is a function vTaskDelayUntil which takes a timestamp and a number of ticks to delay. By taking the timestamp at the beginning of the execution of a task we can then make sure that its release time does not slowly drift. So far I have not seen anything similar in Zephyr. Am I missing something, or do I have to somehow create a similar mechanism on my own by measuring the uptime at the release of a periodic task and then again just before using any sleep function to calculate the exact sleep time I want?

Thank you very much in advance,
Nick


Nikolaus Huber
 

Thank you all for your answers!

I was kind of assuming that I could achieve this by using a timer. I think that that might be the nicest solution for my use case.
I was just wondering if Zephyr maybe has an API similar to FreeRTOS with a dedicated delay command that eliminates drifts. But I guess using a timer actually makes it a bit more explicit.

Thank you very much :)

/Nick








När du har kontakt med oss på Uppsala universitet med e-post så innebär det att vi behandlar dina personuppgifter. För att läsa mer om hur vi gör det kan du läsa här: http://www.uu.se/om-uu/dataskydd-personuppgifter/

E-mailing Uppsala University means that we will process your personal data. For more information on how this is performed, please read here: http://www.uu.se/en/about-uu/data-protection-policy


Chruściński, Krzysztof
 

Hi,

One thing to consider is that k_timeout_t structure used for k_sleep and kernel timeouts can hold absolute value. Check out K_TIMEOUT_ABS_MS() for setting timeout in uptime milliseconds.

Regards,
Krzysztof

-----Original Message-----
From: users@lists.zephyrproject.org <users@lists.zephyrproject.org> On Behalf Of Nikolaus Huber via lists.zephyrproject.org
Sent: Wednesday, February 3, 2021 9:48 PM
To: users@lists.zephyrproject.org
Subject: Re: [Zephyr-users] Drift through k_sleep or k_msleep #api

Thank you all for your answers!

I was kind of assuming that I could achieve this by using a timer. I think that that might be the nicest solution for my use case.
I was just wondering if Zephyr maybe has an API similar to FreeRTOS with a dedicated delay command that eliminates drifts. But I guess using a timer actually makes it a bit more explicit.

Thank you very much :)

/Nick








När du har kontakt med oss på Uppsala universitet med e-post så innebär det att vi behandlar dina personuppgifter. För att läsa mer om hur vi gör det kan du läsa här: https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.uu.se%2Fom-uu%2Fdataskydd-personuppgifter%2F&;data=04%7C01%7Ckrzysztof.chruscinski%40nordicsemi.no%7C08dd3554ffe7423bee6008d8c8850e8a%7C28e5afa2bf6f419a8cf6b31c6e9e5e8d%7C0%7C0%7C637479821084758635%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=oxxw9PeN6d36zfphV4A%2BLfiDszb8EIsfI3grkUvoSI4%3D&amp;reserved=0

E-mailing Uppsala University means that we will process your personal data. For more information on how this is performed, please read here: https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.uu.se%2Fen%2Fabout-uu%2Fdata-protection-policy&;data=04%7C01%7Ckrzysztof.chruscinski%40nordicsemi.no%7C08dd3554ffe7423bee6008d8c8850e8a%7C28e5afa2bf6f419a8cf6b31c6e9e5e8d%7C0%7C0%7C637479821084758635%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=NUC%2B45wN6BAFk1jM%2B9tA6bXx8fHZLt7%2FNNp%2BTh%2FIQz4%3D&amp;reserved=0