1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
/*********************************************************************************************************************** * Copyright (c) 2019 by the authors * * Author: André Borrmann * License: Apache License 2.0 **********************************************************************************************************************/ #![doc(html_root_url = "https://docs.rs/ruspiro-timer/0.1.0")] #![no_std] #![feature(asm)] //! # Timer functions //! //! This crate provides simple timing functions to pause the core for a specific amount of time. //! //! # Usage //! //! ``` //! use rusprio_timer as timer; //! //! fn demo() { //! timer::sleep(1000); // pause for 1 milli second //! timer::sleepcycles(200); // pause for 200 CPU cycles //! } //! //! ``` //! use ruspiro_register::define_registers; pub type Useconds = u64; /// Pause the current execution for the given amount of micro seconds pub fn sleep(usec: Useconds) { let wait_until = now() + usec; while !is_due(wait_until) { }; } /// Pause the current execution for the given amount of CPU cycles pub fn sleepcycles(cycles: u32) { for _ in 0..cycles { unsafe { asm!("NOP") }; } } // MMIO peripheral base address based on the target family provided with the custom target config file. #[cfg(feature="ruspiro_pi3")] const PERIPHERAL_BASE: u32 = 0x3F00_0000; // Base address of timer MMIO register const TIMER_BASE: u32 = PERIPHERAL_BASE + 0x0000_3000; define_registers! [ TIMERCLO: ReadOnly<u32> @ TIMER_BASE + 0x04, TIMERCHI: ReadOnly<u32> @ TIMER_BASE + 0x08 ]; /// Get the current time as free running counter value of the system timer fn now() -> Useconds { let t_low = TIMERCLO::Register.get() as u64; let t_high = TIMERCHI::Register.get() as u64; (t_high << 32) | t_low } /// Compare the given time as free running counter value with the current time. /// Returns true if the current time is later than the time passed into this function. fn is_due(time: Useconds) -> bool { if time == 0 { // if no valid time is given, time is always due true } else { // returns true if we have reached the current time (counter) now() >= time } }