`fugit` provides a comprehensive library of `Duration` and `Instant` for the handling of time in embedded systems, doing all it can at compile time.

Related tags

Miscellaneous fugit
Overview

fugit

fugit provides a comprehensive library of Duration and Instant for the handling of time in embedded systems, doing all it can at compile time.

This library is a heavily inspired of std::chrono's Duration from C++ which does all it can at compile time.

Aims

  • no_std library with goals of user-friendliness and performance first
    • All methods are const fn that can be (i.e. non-trait methods)
    • Use no traits, concrete types all the way for maximum const-ification
    • Operations are supported between different bases and backing storages instead of implementing custom traits
    • All constants needed for comparing or changing timebase are guaranteed compile time generated
  • Support for both u32 and u64 backing storage with efficient instruction lowering on MCUs
    • On Cortex-M3 and up: no soft-impls pulled in for both u32 and u64 except when changing base on u64
    • Comparisons on u32 and u64 do not use division, only changing base with all constants calculated at compile time
  • Selection of base happens at compile time
    • A common problem is that run time changing of base robs us of a lot of optimization opportunities, but since there are no traits and short-hands select the correct base at compile time.
Comments
  • Comparison with Instant of u32::MAX is unsound

    Comparison with Instant of u32::MAX is unsound

    I try this code on a thumbv7em-none-eabihf target:

    defmt::println!("{:?}", TimerInstantU32::<100_000_000>::from_ticks(u32::MAX) > TimerInstantU32::<100_000_000>::from_ticks(1000));
    
    

    Output:

    0.099983 false
    

    Since u32::MAX > 1000, something seems to be wrong inside of const_cmp?

    opened by henrikssn 7
  • use gcd crate & provide a way to convert between `Instant` fractions

    use gcd crate & provide a way to convert between `Instant` fractions

    remove existing const gcd implementation in favor of the GCD crate's implementation now that it provides it, and provide const into and try_into methods for converting between Instants of different fractions

    opened by TDHolmes 6
  • short functions which return fixed types

    short functions which return fixed types

    Now we have 2 main ways to create value

    1. DurarionType::from_ticks(val) - fixed type result, can be used in any context, but long call
    2. Ext traits: 1.millis() - generic type result, non-const. Can fail to resolve result type if information is not enough.

    Need short variant of 1 which looks similar to 2. cc @korken89

    opened by burrbull 5
  • Reexport aliases

    Reexport aliases

    Currently I have something like this:

    use fugit::{ExtU32, aliases::MillisDurationU32};
    
    pub struct SysTimer{
        start: fugit::Instant::<u32, 1, 1_000>,
        duration: MillisDurationU32,
    }
    

    I would prefer:

    pub struct SysTimer{
        start: fugit::Instant::<u32, 1, 1_000>,
        duration: fugit::MillisDurationU32,
    }
    

    Actually maybe it makes sense to create aliases also for Instants?

    opened by andresv 5
  • Add nanosecond units alongside the others

    Add nanosecond units alongside the others

    Since fugit already supports rendering nanosecond timebases, perhaps we could include nanoseconds alongside microseconds etc. Nanoseconds are used for PTP times so it would make working with them more convenient.

    By the way, I added .gitattributes to make merge conflicts on CHANGELOG less likely; union means it will try and combine lines from both commits if possible which should do the right thing on a changelog. Happy to take this out if you want, of course!

    opened by adamgreig 4
  • Implement *Assign ops

    Implement *Assign ops

    Implements +=, -=, *=, and /= where appropriate, by using the existing +, -, *, and / operators.

    This allows for example:

    let mut t = MillisDurationU64::millis(100);
    t += MillisDurationU64::millis(900);
    

    instead of what's currently required:

    let mut t = MillisDurationU64::millis(100);
    t = t + MillisDurationU64::millis(900);
    

    Sorry if this has been considered before, I couldn't find any previous discussions. I tried to add it wherever it makes sense alongside an existing operator implementation.

    opened by adamgreig 4
  • fugit compile problem

    fugit compile problem

    One of the last few commits, just prior to release of v0.3.3, has started giving me compile errors

       Compiling fugit v0.3.3
    error[E0658]: panicking in constants is unstable
      --> /home/paul/.cargo/registry/src/github.com-1ecc6299db9ec823/fugit-0.3.3/src/helpers.rs:48:32
       |
    48 |     pub const GREATER_EQ: () = assert!(L >= R);
       |                                ^^^^^^^^^^^^^^^
       |
       = note: see issue #51999 <https://github.com/rust-lang/rust/issues/51999> for more information
       = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
    
    

    Any ideas?

    opened by pdgilbert 3
  • Mention wrap-around behavior of const_cmp

    Mention wrap-around behavior of const_cmp

    This relates to #36.

    While the correct fix for #36 (if any) seems to be controversial, let's first document how the functions work in their current form.

    opened by jannic 2
  • Add Duration::to_nanos, to_micros, to_millis, to_secs, to_minutes, to_hours methods

    Add Duration::to_nanos, to_micros, to_millis, to_secs, to_minutes, to_hours methods

    I was worried this might lead to overflows when doing something like

    Duration::<u32, 1, 1_000_000_000>::from_ticks(1_000_000_000).to_nanos()
    

    because it's working out

    (1_000_000_000u32 * 1_000_000_000u32)/1_000_000_000u32
    

    but in practice it seems to do the right thing (and I cover this case with tests).

    In any event the maths is exactly the inverse of the existing micros() etc methods, so I guess it should work or fail in the same ways.

    opened by adamgreig 2
  • Impl defmt::Format trait

    Impl defmt::Format trait

    Currently Display is implemented for Duration: https://github.com/korken89/fugit/blob/master/src/duration.rs#L428-L448

    I guess there isn't any drawback if Format is also implemented?

    opened by andresv 2
  • Type aliases for common cases

    Type aliases for common cases

    What do you think about defining type aliases like type MillisDuration<T> = Duration<T, 1, 1000> (or similar) to cut down on typing and mental load? Or even MillisDurationU32 to simplify it even more?

    opened by Sympatron 2
  • `Instant::checked_add_duration` claims to check for overflow, doesn't

    `Instant::checked_add_duration` claims to check for overflow, doesn't

    use of wrapping_add where the bases are equal, here: https://github.com/korken89/fugit/blob/master/src/instant.rs#L171 and similarly if bases are different, here: https://github.com/korken89/fugit/blob/master/src/instant.rs#L181

    claim that it checks for overflow, here: https://github.com/korken89/fugit/blob/master/src/instant.rs#L156

    evcxr transcript showing that it wraps:

    >> :dep fugit = "0.3.6"
    >> fugit::Instant::<u32, 1, 1000>::from_ticks(0xffff_ffff) + fugit::Duration::<u32, 1, 1000>::from_ticks(10)
    Instant { ticks: 9 }
    
    opened by Dridus 2
  • Instant::cmp doesnt comply with Ord requirements

    Instant::cmp doesnt comply with Ord requirements

    The implementation impl<const NOM: u32, const DENOM: u32> Ord for Instant<u64, NOM, DENOM> (and same with u32) doesn't comply with the specified requirements for implementations of Ord.

    Ord requires the comparison to be transitive, ie. a < b and b < c implies a < c. (see https://doc.rust-lang.org/std/cmp/trait.Ord.html#corollaries)

    However the current implementation tries to handle wrap-around of the underlying ticks counter: https://github.com/korken89/fugit/blob/master/src/instant.rs#L55-L70. That breaks the mentioned requirement.

    So either the implementation should be changed, or Instant should not implement Ord (and neither PartialOrd).

    I noticed this when trying to find the minimum in a list of Instants, and getting inconsistent results.

    opened by jannic 11
  • Make proper documentation with a book

    Make proper documentation with a book

    I'd like to have a small mdbook for fugit showing how to use it. There is enough const generics shenanigans that would be great to have examples for, as reading the code is ... not trivial.

    If anyone feels like helping here, even just setting up the structure, I'd greatly welcome it!

    help wanted 
    opened by korken89 0
  • impl TryFrom<core::time::Duration> for Duration<...>

    impl TryFrom for Duration<...>

    It appears to me that it should be well possible to implement this conversion -- it wouldn't be as compile-time constant as the rest of fugit, but it would help gluing it to more generic code that works with standard, aeh, core durations.

    (I'm considering to move my bespoke timers for RIOT-OS to just be a newtype around, and after the next breaking API change, just a type alias for fugit's duration, in particular TimerDurationU32, but don't want to lose functionality for simple demos whose values are expressed in what the user may be familiar with).

    [edit: When I do switch over and there is soft approval of this, I can probably provide an implementation PR.]

    opened by chrysn 7
  • Support picoseconds

    Support picoseconds

    As a general purpose time library, it would be nice to also support picosecond timebases. These arise frequently in time-to-digital conversion (TDC, whiterabbit, ToF, OTDR) or other high accuracy measurement (time/frequency metrology). The stuff in helpers.rs would need a u64/u128 versions.

    opened by jordens 2
Owner
Emil Fresk
PhD in Robotics, embedded Rust nerd, and machine vision hardware/software designer from Sweden. Co-founder of WideFind AB.
Emil Fresk
QueingSimulator is an application that can be used to build intuitions about behavior of synchronous request/reply systems

Queueing Simulator QueingSimulator is an application that can be used to build intuitions about behavior of synchronous request/reply systems (such as

Joe Magerramov 7 Sep 11, 2022
constduck: compile-time duck typing and reflection

constduck provides a procmacro that can enable compile time duck typing and reflection on arbitrary struct types.

ferrouille 15 Oct 12, 2022
Option and Either types with variants known at compile time.

Const Either Some types to allow deciding at compile time if an option contains a value or which variant from the either type is active. This might be

null 1 May 5, 2022
Faster division by constants that aren't known at compile-time

Baseline implementation of division by constants When dividing integers by compile-time constants, compilers (LLVM) can be trusted to convert those to

Paul Khuong 18 Jul 6, 2022
This crate defines a single macro that is a brainfunct compile-time interpreter.

Compile Protection This crate defines a single macro that is a brainfunct compile-time interpreter. One example is as follows #![recursion_limit = "18

John Marsden 7 Nov 29, 2021
Allocate memory at compile time!

const-alloc Link to the docs! Allocate memory at compile time! Currently, in stable rust there is no way to dynamically allocate or deallocate memory

Sp00ph 1 Feb 5, 2022
Compile-time lifetimes for comments.

todo_by Compile-time lifetimes for comments. To use this macro, add it to your dependencies via Cargo: cargo add todo_by Then, import and invoke the m

Parker McMullin 116 May 23, 2023
Easier joystick, mouse and keyboard input handling in Bevy

Easier joystick, mouse and keyboard input handling in Bevy

Pedro Henrique 31 Dec 20, 2022
A Rust proc-macro crate which derives functions to compile and parse back enums and structs to and from a bytecode representation

Bytecode A simple way to derive bytecode for you Enums and Structs. What is this This is a crate that provides a proc macro which will derive bytecode

null 4 Sep 3, 2022
little brother of gnu-copypasta-maker To compile, use make.

UWU Maker little brother of gnu-copypasta-maker To compile, use make. To install, use sudo make install or if you are root make install To uninstall,

Ahmet Efe AKYAZI 1 Jan 12, 2022
Amethyst is a systems language aimed at being simple, small, portable, and safe.

amethyst Amethyst is a systems language aimed at being simple, small, portable, and safe. What is this language? From the r/ProgLangs discord server:

Amethyst Language 34 Dec 18, 2022
Rust embedded-HAL driver for the AHT20 temperature and humidity sensor.

AHT20-driver Rust embedded-HAL driver for the AHT20 temperature and humidity sensor. You can read my blog post AHT20 thermometer driver which details

Rikard Anglerud 3 Nov 15, 2022
Buildomat manages the provisioning of ephemeral UNIX systems on which to run software builds

B U I L D O M A T a software build labour-saving device Buildomat manages the provisioning of ephemeral UNIX systems (e.g., instances in AWS EC2) on w

Oxide Computer Company 33 Dec 4, 2022
Nimbus is a framework for building parachain consensus systems on cumulus-based parachains.

Cumulo -- Nimbus ⛈️ Nimbus is a framework for building parachain consensus systems on cumulus-based parachains. Given the regular six-second pulse-lik

null 36 Dec 14, 2022
Rust library that can be reset if you think it's slow

GoodbyeKT Rust library that can be reset if you think it's slow

null 39 Jun 16, 2022
Edgelord is a library for Cloudflare Workers. You can scaffold a basic bot for discord, slack, etc.

Edge Computing + chūnibyō = Edgelord ✨ ?? Edgelord Edgelord is now working. You can contribute for it. Edgelord is a Rust library for cloudflare worke

null 23 Dec 26, 2022
cargo extension for flashing embedded rust programs via dfu based on jacobrosenthals cargo-hf2

cargo-dfu This crate provides a cargo subcommand to flash ELF binaries via dfu Most STM chips will probably work with this, although you might need to

Roman Kretschmer 0 Feb 6, 2022
OpenEMC: open embedded management controller

OpenEMC OpenEMC is an open-source firmware implementing an embedded management controller (EMC) on an STM32F1 microcontroller. It consists of a bootlo

Sebastian Urban 5 Dec 25, 2022
Embedded demo based on esp32-c3

wot-esp-demo Demo Hygro-Thermometer based on the esp-rust-board. http version based on std-training Deploy Rust prerequisites Install espflash, ldprox

null 3 Dec 1, 2023