From 8868752e37a83ccffd0149cc96d65397fcc51d33 Mon Sep 17 00:00:00 2001 From: Zach Halvorsen Date: Tue, 11 Jul 2023 08:42:50 -0700 Subject: [PATCH] Remove duplicated alarm syscall. (#636) The alarm syscall is implemented in libtock-rs, but was duplicated here. This removes the duplicated code and changes the references to point to libtock-rs directly. Co-authored-by: kaczmarczyck <43844792+kaczmarczyck@users.noreply.github.com> --- Cargo.lock | 10 ++ Cargo.toml | 1 + src/env/tock/clock.rs | 10 +- third_party/lang-items/Cargo.toml | 1 + third_party/lang-items/src/util.rs | 8 +- third_party/libtock-drivers/Cargo.toml | 1 + third_party/libtock-drivers/src/timer.rs | 121 ++--------------------- 7 files changed, 31 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d236ccca..5dd32390 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -168,6 +168,7 @@ dependencies = [ "ed25519-compact", "enum-iterator", "lang_items", + "libtock_alarm", "libtock_buttons", "libtock_console", "libtock_drivers", @@ -374,6 +375,7 @@ dependencies = [ name = "lang_items" version = "0.1.0" dependencies = [ + "libtock_alarm", "libtock_console", "libtock_drivers", "libtock_leds", @@ -389,6 +391,13 @@ version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" +[[package]] +name = "libtock_alarm" +version = "0.1.0" +dependencies = [ + "libtock_platform", +] + [[package]] name = "libtock_buttons" version = "0.1.0" @@ -407,6 +416,7 @@ dependencies = [ name = "libtock_drivers" version = "0.1.0" dependencies = [ + "libtock_alarm", "libtock_console", "libtock_platform", ] diff --git a/Cargo.toml b/Cargo.toml index f4c451d6..8aeae9ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ features = ["no_auto_layout", "no_debug_memop"] libtock_buttons = { path = "third_party/libtock-rs/apis/buttons" } libtock_platform = { path = "third_party/libtock-rs/platform" } libtock_drivers = { path = "third_party/libtock-drivers" } +libtock_alarm = { path = "third_party/libtock-rs/apis/alarm" } libtock_console = { path = "third_party/libtock-rs/apis/console" } libtock_leds = { path = "third_party/libtock-rs/apis/leds" } lang_items = { path = "third_party/lang-items" } diff --git a/src/env/tock/clock.rs b/src/env/tock/clock.rs index 589a4ee6..016afd3d 100644 --- a/src/env/tock/clock.rs +++ b/src/env/tock/clock.rs @@ -13,7 +13,9 @@ // limitations under the License. use core::marker::PhantomData; -use libtock_drivers::timer::{get_clock_frequency, get_ticks}; +use libtock_alarm::Alarm; +use libtock_drivers::result::FlexUnwrap; +use libtock_drivers::timer::Timer; use libtock_platform::Syscalls; use opensk::api::clock::Clock; @@ -63,7 +65,7 @@ impl TockClock { /// /// Call this regularly to timeout reliably despite wrapping clock ticks. pub fn tickle(&mut self) { - let cur_tick = get_ticks::().ok().unwrap(); + let cur_tick = Timer::::get_ticks().flex_unwrap(); if cur_tick < self.now.tick { self.now.epoch += 1; } @@ -77,7 +79,7 @@ impl Clock for TockClock { fn make_timer(&mut self, milliseconds: usize) -> Self::Timer { let milliseconds = milliseconds as u32; self.tickle(); - let clock_frequency = get_clock_frequency::().ok().unwrap(); + let clock_frequency = Alarm::::get_frequency().ok().unwrap().0; let delta_tick = match milliseconds.checked_mul(clock_frequency) { Some(x) => x / 1000, // All CTAP timeouts are multiples of 100 so far. Worst case we timeout too early. @@ -95,7 +97,7 @@ impl Clock for TockClock { #[cfg(feature = "debug_ctap")] fn timestamp_us(&mut self) -> usize { - let clock_frequency = get_clock_frequency::().ok().unwrap(); + let clock_frequency = Alarm::::get_frequency().ok().unwrap().0; let total_ticks = 0x100_0000u64 * self.now.epoch as u64 + self.now.tick as u64; (total_ticks.wrapping_mul(1_000_000u64) / clock_frequency as u64) as usize } diff --git a/third_party/lang-items/Cargo.toml b/third_party/lang-items/Cargo.toml index 60ba0f6c..fe27ae33 100644 --- a/third_party/lang-items/Cargo.toml +++ b/third_party/lang-items/Cargo.toml @@ -18,6 +18,7 @@ libtock_drivers = { path = "../libtock-drivers" } libtock_platform = { path = "../../third_party/libtock-rs/platform" } libtock_low_level_debug = { path = "../../third_party/libtock-rs/apis/low_level_debug" } libtock_leds = { path = "../../third_party/libtock-rs/apis/leds" } +libtock_alarm = { path = "../../third_party/libtock-rs/apis/alarm" } libtock_console = { path = "../../third_party/libtock-rs/apis/console" } [dependencies.linked_list_allocator] diff --git a/third_party/lang-items/src/util.rs b/third_party/lang-items/src/util.rs index 390d8a6c..0017190b 100644 --- a/third_party/lang-items/src/util.rs +++ b/third_party/lang-items/src/util.rs @@ -1,4 +1,4 @@ -use libtock_drivers::timer; +use libtock_alarm::{Alarm, Milliseconds}; use libtock_leds::Leds; use libtock_low_level_debug::{AlertCode, LowLevelDebug}; use libtock_platform as platform; @@ -28,13 +28,13 @@ impl Util { let _ = Leds::::on(led); } } - let _ = timer::Alarm::::sleep_for(timer::Milliseconds(100)); + let _ = Alarm::::sleep_for(Milliseconds(100)); if let Ok(led_count) = Leds::::count() { for led in 0..led_count { let _ = Leds::::off(led); } } - let _ = timer::Alarm::::sleep_for(timer::Milliseconds(100)); + let _ = Alarm::::sleep_for(Milliseconds(100)); } } @@ -47,7 +47,7 @@ impl Util { if let Ok(leds) = Leds::::count() { for led in 0..leds { let _ = Leds::::on(led); - let _ = timer::Alarm::::sleep_for(timer::Milliseconds(100)); + let _ = Alarm::::sleep_for(Milliseconds(100)); let _ = Leds::::off(led); } } diff --git a/third_party/libtock-drivers/Cargo.toml b/third_party/libtock-drivers/Cargo.toml index 65c33565..3b3841fa 100644 --- a/third_party/libtock-drivers/Cargo.toml +++ b/third_party/libtock-drivers/Cargo.toml @@ -9,6 +9,7 @@ license = "MIT/Apache-2.0" edition = "2018" [dependencies] +libtock_alarm = { path = "../../third_party/libtock-rs/apis/alarm" } libtock_console = { path = "../../third_party/libtock-rs/apis/console" } libtock_platform = { path = "../../third_party/libtock-rs/platform" } diff --git a/third_party/libtock-drivers/src/timer.rs b/third_party/libtock-drivers/src/timer.rs index a8aa7fe6..55479597 100644 --- a/third_party/libtock-drivers/src/timer.rs +++ b/third_party/libtock-drivers/src/timer.rs @@ -8,105 +8,16 @@ //! //! Adapted from the [libtock-rs](https://github.com/tock/libtock-rs/blob/master/apis/alarm/src/lib.rs) alarm driver interface -use crate::result::{FlexUnwrap, OtherError, TockError, TockResult}; -use crate::util::Util; -use core::cell::Cell; +use crate::result::{OtherError, TockResult}; use core::marker::PhantomData; use core::ops::{Add, AddAssign, Sub}; +use libtock_alarm::{Hz, Alarm, Milliseconds, Convert}; use libtock_platform as platform; -use libtock_platform::{share, DefaultConfig, ErrorCode, Syscalls}; +use libtock_platform::{DefaultConfig, ErrorCode, Syscalls}; use platform::share::Handle; use platform::subscribe::OneId; use platform::{Subscribe, Upcall}; -pub struct Alarm(S, C); - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub struct Hz(pub u32); - -pub trait Convert { - /// Converts a time unit by rounding up. - fn to_ticks(self, freq: Hz) -> Ticks; -} - -#[derive(Copy, Clone, Debug)] -pub struct Ticks(pub u32); - -impl Convert for Ticks { - fn to_ticks(self, _freq: Hz) -> Ticks { - self - } -} - -pub fn get_ticks() -> TockResult { - Ok(S::command(DRIVER_NUM, command::TIME, 0, 0).to_result::()?) -} - -pub fn get_clock_frequency() -> TockResult { - Ok(S::command(DRIVER_NUM, command::FREQUENCY, 0, 0).to_result::()?) -} - -#[derive(Copy, Clone)] -pub struct Milliseconds(pub u32); - -impl Convert for Milliseconds { - fn to_ticks(self, freq: Hz) -> Ticks { - // Saturating multiplication will top out at about 1 hour at 1MHz. - // It's large enough for an alarm, and much simpler than failing - // or losing precision for short sleeps. - - /// u32::div_ceil is still unstable. - fn div_ceil(a: u32, other: u32) -> u32 { - let d = a / other; - let m = a % other; - if m == 0 { - d - } else { - d + 1 - } - } - Ticks(div_ceil(self.0.saturating_mul(freq.0), 1000)) - } -} - -impl Alarm { - /// Run a check against the console capsule to ensure it is present. - /// - /// Returns number of concurrent notifications supported, - /// 0 if unbounded. - #[inline(always)] - pub fn driver_check() -> Result { - S::command(DRIVER_NUM, command::DRIVER_CHECK, 0, 0).to_result() - } - - pub fn get_frequency() -> Result { - S::command(DRIVER_NUM, command::FREQUENCY, 0, 0) - .to_result() - .map(Hz) - } - - pub fn sleep_for(time: T) -> Result<(), ErrorCode> { - let freq = Self::get_frequency()?; - let ticks = time.to_ticks(freq); - - let called: Cell> = Cell::new(None); - share::scope(|subscribe| { - S::subscribe::<_, _, C, DRIVER_NUM, { subscribe::CALLBACK }>(subscribe, &called)?; - - S::command(DRIVER_NUM, command::SET_RELATIVE, ticks.0, 0) - .to_result() - .map(|_when: u32| ())?; - - loop { - S::yield_wait(); - if let Some((_when, _ref)) = called.get() { - return Ok(()); - } - } - }) - } -} - pub struct Timer { clock_frequency: Hz, s: PhantomData, @@ -157,16 +68,13 @@ impl S::command(DRIVER_NUM, command::DRIVER_CHECK, 0, 0).to_result::<(), ErrorCode>()?; // Alarm driver only returns success as only a single concurrent timer is supported. - let clock_frequency = - S::command(DRIVER_NUM, command::FREQUENCY, 0, 0).to_result::()?; + let clock_frequency = Alarm::::get_frequency()?; - if clock_frequency < 1_000 { + if clock_frequency.0 < 1_000 { // The alarm's frequency must be at least 1 kHz. return Err(OtherError::TimerDriverErroneousClockFrequency.into()); } - let clock_frequency = Hz(clock_frequency); - Ok(Timer { clock_frequency, c: PhantomData, @@ -202,19 +110,8 @@ impl Timer { } } - pub fn sleep(duration: Duration) -> TockResult<()> { - let expired = Cell::new(false); - let mut with_callback = with_callback::(|_| expired.set(true)); - - let mut timer = with_callback.init().flex_unwrap(); - timer.set_alarm(duration).flex_unwrap(); - - Util::::yieldk_for(|| expired.get()); - - match timer.stop_alarm() { - Ok(_) | Err(TockError::Command(ErrorCode::Already)) => Ok(()), - Err(e) => Err(e), - } + pub fn get_ticks() -> TockResult { + Ok(S::command(DRIVER_NUM, command::TIME, 0, 0).to_result::()?) } /// Returns the clock frequency of the timer. @@ -224,10 +121,8 @@ impl Timer { /// Returns the current counter tick value. pub fn get_current_counter_ticks(&self) -> TockResult { - let ticks = S::command(DRIVER_NUM, command::TIME, 0, 0).to_result::()?; - Ok(ClockValue { - num_ticks: ticks as isize, + num_ticks: Self::get_ticks()? as isize, clock_frequency: self.clock_frequency(), }) }