Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GetTick and DelayUntilMs/DelayUntilUs utilities for Delay? #446

Closed
romancardenas opened this issue Aug 10, 2022 · 4 comments
Closed

GetTick and DelayUntilMs/DelayUntilUs utilities for Delay? #446

romancardenas opened this issue Aug 10, 2022 · 4 comments

Comments

@romancardenas
Copy link

romancardenas commented Aug 10, 2022

Hi! I think it would be nice to add a DelayUntil utility to delays. In this way, we can have actual periodic tasks, regardless of the time consumed by a task when executing. To do so, we would need to add the following methods to delays:

  • get_tick(&self) -> u32 (I'm not sure which the return value should be): it returns the current internal clock tick value.
  • delay_until_ms(&mut self, tick_from: u32, ms: u16): it waits the given amount of milliseconds FROM THE BASELINE.
  • delay_until_us(&mut self, tick_from: u32, us: u32): it waits the given amount of microseconds FROM THE BASELINE.

With that, we could do something like this:

let tick = timer.get_tick();  // tick now represents the time
do_stuff(); // this takes time...
timer.delay_until_ms(tick, 1_000); // we wait one second starting from before we triggered do_stuff

Thus, we would not delay for one second, but 1 second SINCE WE CAPTURED THE BASELINE.

What do you think? Is there anything I'm missing that makes this a bad idea?

@adamgreig
Copy link
Member

Before I get into the rest of this comment, let me just start by saying this is a very sensible and useful thing to want, and it would be nice to have, but it's a bit tricky...

This crate actually just provides an implementation of the embedded-hal DelayMs and DelayUs traits (soon to be plain Delay in the upcoming 1.0 release) using the Cortex-M SysTick peripheral; other HALs can also provide implementations using timer peripherals etc. Probably the best place for such a method would be embedded-hal itself, but the Delay traits there are basically just a minimum viable delay for now until questions about how to best represent time can be worked out (see rust-embedded/embedded-hal#359).

In the Cortex-M implementation in this crate, you couldn't actually implement your proposed methods - it basically loads the required number of ticks into the SysTick timer, starts it running, then waits for it to run down to 0. There's no ongoing counter in the background, so there's no current "ticks" value.

Another hard part with this is that whatever value you return for get_tick() can overflow, and you can't be sure it hasn't overflowed when someone later calls delay_until(). If it's been more than half the maximum number of ticks between get_tick() and delay_until_ms(), the program can't really detect rollover, but won't wait the right amount of time. Getting this right ends up being quite application specific with regards to how long you expect to keep running and therefore how many bits you're willing to use for the timer (and how fast it runs, what resolution is OK, etc). It's something that specific HALs could provide configuration for, so it could live in a generic trait in embedded-hal too... but probably needs more thought about how to represent the time.

Other embedded projects like embassy can provide exactly what you're looking for by virtue of making more decisions about the platform; see the embassy time docs for example.

@romancardenas
Copy link
Author

Thank you so much for the response, it was very clarifying. I guess that you noticed that I'm quite new in this world of open source and embedded systems.
From what I understood, it seems that embedded-hal is clearly the right place to define a helpful interface for dealing with time and delays (which are vital in embedded systems). However, a right or sound way of dealing with time in multiple platforms is not a straightforward issue, and that is why embedded-has is removing timer in version 1.0.

It seems that embedded-time is quite an appealing alternative for this, and people in the wg of embedded-hal are discussing whether to adopt it or not. I guess that embedded-time will eventually be absorbed by embedded-hal (or at least the latter will implement something similar to the prior).
So, for now, my best option is perhaps to include embedded-time by my own and use it at my own risk.

Am I right? or did I misunderstood your message? Thanks in advance.

@adamgreig
Copy link
Member

Yep, that's about right! A more recent crate, fugit has also been very popular recently as an alternative design to embedded-time, which a number of HALs have started to adopt I believe.

@romancardenas
Copy link
Author

Great, thanks for your time! I'll close the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants