Skip to content

Commit

Permalink
Remove duplicated alarm syscall.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
zhalvorsen committed Jun 27, 2023
1 parent f0e87ee commit 07ad869
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 118 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
10 changes: 6 additions & 4 deletions src/env/tock/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -63,7 +65,7 @@ impl<S: Syscalls> TockClock<S> {
///
/// Call this regularly to timeout reliably despite wrapping clock ticks.
pub fn tickle(&mut self) {
let cur_tick = get_ticks::<S>().ok().unwrap();
let cur_tick = Timer::<S>::get_ticks().flex_unwrap();
if cur_tick < self.now.tick {
self.now.epoch += 1;
}
Expand All @@ -77,7 +79,7 @@ impl<S: Syscalls> Clock for TockClock<S> {
fn make_timer(&mut self, milliseconds: usize) -> Self::Timer {
let milliseconds = milliseconds as u32;
self.tickle();
let clock_frequency = get_clock_frequency::<S>().ok().unwrap();
let clock_frequency = Alarm::<S>::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.
Expand All @@ -95,7 +97,7 @@ impl<S: Syscalls> Clock for TockClock<S> {

#[cfg(feature = "debug_ctap")]
fn timestamp_us(&mut self) -> usize {
let clock_frequency = get_clock_frequency::<S>().ok().unwrap();
let clock_frequency = Alarm::<S>::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
}
Expand Down
1 change: 1 addition & 0 deletions third_party/lang-items/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
8 changes: 4 additions & 4 deletions third_party/lang-items/src/util.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -28,13 +28,13 @@ impl<S: Syscalls, C: platform::subscribe::Config> Util<S, C> {
let _ = Leds::<S>::on(led);
}
}
let _ = timer::Alarm::<S, C>::sleep_for(timer::Milliseconds(100));
let _ = Alarm::<S, C>::sleep_for(Milliseconds(100));
if let Ok(led_count) = Leds::<S>::count() {
for led in 0..led_count {
let _ = Leds::<S>::off(led);
}
}
let _ = timer::Alarm::<S, C>::sleep_for(timer::Milliseconds(100));
let _ = Alarm::<S, C>::sleep_for(Milliseconds(100));
}
}

Expand All @@ -47,7 +47,7 @@ impl<S: Syscalls, C: platform::subscribe::Config> Util<S, C> {
if let Ok(leds) = Leds::<S>::count() {
for led in 0..leds {
let _ = Leds::<S>::on(led);
let _ = timer::Alarm::<S, C>::sleep_for(timer::Milliseconds(100));
let _ = Alarm::<S, C>::sleep_for(Milliseconds(100));
let _ = Leds::<S>::off(led);
}
}
Expand Down
1 change: 1 addition & 0 deletions third_party/libtock-drivers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }

Expand Down
117 changes: 7 additions & 110 deletions third_party/libtock-drivers/src/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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: Syscalls, C: platform::subscribe::Config = DefaultConfig>(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<S: Syscalls>() -> TockResult<u32> {
Ok(S::command(DRIVER_NUM, command::TIME, 0, 0).to_result::<u32, ErrorCode>()?)
}

pub fn get_clock_frequency<S: Syscalls>() -> TockResult<u32> {
Ok(S::command(DRIVER_NUM, command::FREQUENCY, 0, 0).to_result::<u32, ErrorCode>()?)
}

#[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<S: Syscalls, C: platform::subscribe::Config> Alarm<S, C> {
/// 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<u32, ErrorCode> {
S::command(DRIVER_NUM, command::DRIVER_CHECK, 0, 0).to_result()
}

pub fn get_frequency() -> Result<Hz, ErrorCode> {
S::command(DRIVER_NUM, command::FREQUENCY, 0, 0)
.to_result()
.map(Hz)
}

pub fn sleep_for<T: Convert>(time: T) -> Result<(), ErrorCode> {
let freq = Self::get_frequency()?;
let ticks = time.to_ticks(freq);

let called: Cell<Option<(u32, u32)>> = 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<S: Syscalls, C: platform::subscribe::Config = DefaultConfig> {
clock_frequency: Hz,
s: PhantomData<S>,
Expand Down Expand Up @@ -157,16 +68,13 @@ impl<S: Syscalls, C: platform::subscribe::Config, CB: Fn(ClockValue)>
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::<u32, ErrorCode>()?;
let clock_frequency = Alarm::<S>::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,
Expand Down Expand Up @@ -202,19 +110,8 @@ impl<S: Syscalls, C: platform::subscribe::Config> Timer<S, C> {
}
}

pub fn sleep(duration: Duration<isize>) -> TockResult<()> {
let expired = Cell::new(false);
let mut with_callback = with_callback::<S, C, _>(|_| expired.set(true));

let mut timer = with_callback.init().flex_unwrap();
timer.set_alarm(duration).flex_unwrap();

Util::<S>::yieldk_for(|| expired.get());

match timer.stop_alarm() {
Ok(_) | Err(TockError::Command(ErrorCode::Already)) => Ok(()),
Err(e) => Err(e),
}
pub fn get_ticks() -> TockResult<u32> {
Ok(S::command(DRIVER_NUM, command::TIME, 0, 0).to_result::<u32, ErrorCode>()?)
}

/// Returns the clock frequency of the timer.
Expand Down

0 comments on commit 07ad869

Please sign in to comment.