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,
|
|
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
Den ons 3 feb. 2021 kl 20:31 skrev Nikolaus Huber <nikolaus.huber@...>:
|
|
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
Den ons 3 feb. 2021 kl 20:31 skrev Nikolaus Huber <nikolaus.huber@...>:
|
|
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@...>:
|
|
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,
toggle quoted messageShow quoted text
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@... <users@...> On Behalf Of Nikolaus Huber via lists.zephyrproject.org Sent: Wednesday, February 3, 2021 9:48 PM To: users@... 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&sdata=oxxw9PeN6d36zfphV4A%2BLfiDszb8EIsfI3grkUvoSI4%3D&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&sdata=NUC%2B45wN6BAFk1jM%2B9tA6bXx8fHZLt7%2FNNp%2BTh%2FIQz4%3D&reserved=0
|
|