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

Discussion: Add way to read the current timer value in CountDown trait #186

Open
conorpp opened this issue Feb 4, 2020 · 6 comments · May be fixed by #277
Open

Discussion: Add way to read the current timer value in CountDown trait #186

conorpp opened this issue Feb 4, 2020 · 6 comments · May be fixed by #277

Comments

@conorpp
Copy link

conorpp commented Feb 4, 2020

I'd like to use a timer to measure how long something takes. I can't use the timer trait currently since there's no way to read the current timer value. What do we think about adding a method to CountDown that returns the current timer value?

For example, see lap method below.

pub trait CountDown {
    /// The unit of time used by this timer
    type Time;

    /// Starts a new count down
    fn start<T>(&mut self, count: T)
    where
        T: Into<Self::Time>;

    /// Returns the current value of the timer as how much time has elapsed since starting.
    fn lap<T>(&self,) -> T
    where
        T: Into<Self::Time>;

    /// Non-blockingly "waits" until the count down finishes
    ///
    /// # Contract
    ///
    /// - If `Self: Periodic`, the timer will start a new count down right after the last one
    /// finishes.
    /// - Otherwise the behavior of calling `wait` after the last call returned `Ok` is UNSPECIFIED.
    /// Implementers are suggested to panic on this scenario to signal a programmer error.
    fn wait(&mut self) -> nb::Result<(), Infallible>;
}
@dbrgn
Copy link
Contributor

dbrgn commented Jun 28, 2020

I also need a way to get the current counter value of a timer. However, in my case I only need that, no need for starting / resetting / waiting.

In the case of an STM32 timer, an implementation is actually really simple, you just start the timer and then read the CNT (counter) register of the timer.

However, I'm not sure what the best API design is around timers... Seems that they can be used in a lot of different ways, so it's hard to build an abstraction that works everywhere. Maybe the focus should be on use cases, not on the capabilities.

One use case is "waiting until a certain time has elapsed". That is best solved by an interrupt based timer like CountDown.

Another use case is "measuring relative time that has elapsed" between two events. That can be done using a periodic up- or downcounting timer where the counter register can be read. Depending on timer resolution, an implementation might need to deal with overflows. I'm not sure whether this is something that should be in embedded_hal or whether this should be up to the implementation.

An example of the second use case is the Monotonic trait of RTIC:

https://github.com/rtic-rs/cortex-m-rtic/blob/8a4f9c6b8ae91bebeea0791680f89375a78bffc6/src/lib.rs#L129-L162

An example implementation can be found here.

@PTaylor-us
Copy link

PTaylor-us commented Jun 28, 2020

The embedded-time crate provides a Clock trait to abstract hardware timers/counters. It currently includes a blocking delay() function as well as the ability to get a duration elapsed since some point in time (stop-watch), but I am working on adding specific timer functionality in this PR (FluenTech/embedded-time#21). This timer functionality would include creating one-shot and periodic timers, setting a duration (in real-world units), checking for expiration, blocking until expiration, reading elapsed duration, reading remaining duration, etc. Timer will not be a trait, but rather it will rely on any provided Clock impl. In this way, you impl a Clock over any hardware timers/counters, and you can create and use any number of timers for various purposes. I also plan to add interrupt capabilities to the Clock trait and likely allow a Timer to use that for scheduling some task.

However, per current discussions, embedded-time will may not become a dependent of, or incorporated into embedded-hal, but rather may be a better fit with the device-specific HAL implementations.

@arjanmels
Copy link

Struggling with a similar problem, would be good if the CountDown trait would include the ability to allow reading back the current count.

(I am actually trying to make a specialized version of software timers similar to embedded-time, but which uses callback functions instead of the futures which is used in embedded-time.

@PTaylor-us Would adding this allow the embedded-time crate to use the CountDown trait as a basis instead of your more specialized Clock Trait?

@PTaylor-us
Copy link

@arjanmels Actually, embedded-time does not currently have any way to execute a task upon the expiration of a timer. It's something I tried to implement, but put it on hold because of other priorities. It is something I'd like to implement at some point.

Regarding the CountDown trait. It is actually something different than the embedded-time Clock trait. It is closer to the software timers as it counts to an expiration. If the CountDown trait fits anywhere in embedded-time it is as a trait implemented by the Timer (software timer) type(s).

@arjanmels
Copy link

@PTaylor-us thanks for the insight. Interesting thought that the embedded-rust trait would be the output instead of the input... That is for me an indication that the abstraction is not powerful enough in its current form.

Would love to get some input from the wider community.

@PTaylor-us
Copy link

I don't see much use for the CountDown trait in its current form. I think it needs a fair bit of attention.

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

Successfully merging a pull request may close this issue.

5 participants