Add timer to Hardware struct
diff --git a/examples/adc.rs b/examples/adc.rs index afc110e..a47dd04 100644 --- a/examples/adc.rs +++ b/examples/adc.rs
@@ -3,17 +3,19 @@ use core::fmt::Write; use libtock::adc; use libtock::result::TockResult; -use libtock::timer; use libtock::timer::Duration; use libtock::Hardware; #[libtock::main] async fn main() -> TockResult<()> { - let context = timer::DriverContext::create()?; - let mut driver = context.create_timer_driver()?; - let timer_driver = driver.activate()?; + let Hardware { + console_driver, + timer_context, + .. + } = libtock::retrieve_hardware()?; - let Hardware { console_driver, .. } = libtock::retrieve_hardware()?; + let mut driver = timer_context.create_timer_driver(); + let timer_driver = driver.activate()?; let mut console = console_driver.create_console(); let mut with_callback = adc::with_callback(|channel: usize, value: usize| { writeln!(console, "channel: {}, value: {}", channel, value).unwrap();
diff --git a/examples/blink.rs b/examples/blink.rs index 88857c2..649a1bd 100644 --- a/examples/blink.rs +++ b/examples/blink.rs
@@ -1,16 +1,18 @@ #![no_std] use libtock::result::TockResult; -use libtock::timer; use libtock::timer::Duration; use libtock::Hardware; #[libtock::main] async fn main() -> TockResult<()> { - let Hardware { mut led_driver, .. } = libtock::retrieve_hardware()?; + let Hardware { + mut led_driver, + timer_context, + .. + } = libtock::retrieve_hardware()?; - let context = timer::DriverContext::create()?; - let mut driver = context.create_timer_driver()?; + let mut driver = timer_context.create_timer_driver(); let timer_driver = driver.activate()?; // Blink the LEDs in a binary count pattern and scale
diff --git a/examples/blink_random.rs b/examples/blink_random.rs index a857181..6786ecd 100644 --- a/examples/blink_random.rs +++ b/examples/blink_random.rs
@@ -3,14 +3,14 @@ use libtock::led::LedDriver; use libtock::result::TockResult; use libtock::rng; -use libtock::timer; use libtock::timer::Duration; use libtock::Hardware; #[libtock::main] async fn main() -> TockResult<()> { - let context = timer::DriverContext::create()?; - let mut driver = context.create_timer_driver()?; + let Hardware { timer_context, .. } = libtock::retrieve_hardware()?; + + let mut driver = timer_context.create_timer_driver(); let timer_driver = driver.activate()?; let Hardware { mut led_driver, .. } = libtock::retrieve_hardware()?;
diff --git a/examples/button_read.rs b/examples/button_read.rs index ddd98e8..edb4f49 100644 --- a/examples/button_read.rs +++ b/examples/button_read.rs
@@ -4,21 +4,23 @@ use libtock::buttons; use libtock::buttons::ButtonState; use libtock::result::TockResult; -use libtock::timer; use libtock::timer::Duration; use libtock::Hardware; #[libtock::main] async fn main() -> TockResult<()> { - let Hardware { console_driver, .. } = libtock::retrieve_hardware()?; + let Hardware { + console_driver, + timer_context, + .. + } = libtock::retrieve_hardware()?; let mut console = console_driver.create_console(); let mut with_callback = buttons::with_callback(|_, _| {}); let mut buttons = with_callback.init()?; let mut button = buttons.iter_mut().next().unwrap(); let button = button.enable()?; - let context = timer::DriverContext::create()?; - let mut driver = context.create_timer_driver()?; + let mut driver = timer_context.create_timer_driver(); let timer_driver = driver.activate()?; loop {
diff --git a/examples/gpio.rs b/examples/gpio.rs index e472f2a..62328d1 100644 --- a/examples/gpio.rs +++ b/examples/gpio.rs
@@ -2,16 +2,16 @@ use libtock::gpio::GpioPinUnitialized; use libtock::result::TockResult; -use libtock::timer; use libtock::timer::Duration; +use libtock::Hardware; // Example works on P0.03 #[libtock::main] async fn main() -> TockResult<()> { + let Hardware { timer_context, .. } = libtock::retrieve_hardware()?; let pin = GpioPinUnitialized::new(0); let pin = pin.open_for_write()?; - let context = timer::DriverContext::create()?; - let mut driver = context.create_timer_driver()?; + let mut driver = timer_context.create_timer_driver(); let timer_driver = driver.activate()?; loop {
diff --git a/examples/gpio_read.rs b/examples/gpio_read.rs index 9a69b8e..f3e6a8c 100644 --- a/examples/gpio_read.rs +++ b/examples/gpio_read.rs
@@ -4,19 +4,21 @@ use libtock::gpio::GpioPinUnitialized; use libtock::gpio::InputMode; use libtock::result::TockResult; -use libtock::timer; use libtock::timer::Duration; use libtock::Hardware; // example works on p0.03 #[libtock::main] async fn main() -> TockResult<()> { - let Hardware { console_driver, .. } = libtock::retrieve_hardware()?; + let Hardware { + console_driver, + timer_context, + .. + } = libtock::retrieve_hardware()?; let mut console = console_driver.create_console(); let pin = GpioPinUnitialized::new(0); let pin = pin.open_for_read(None, InputMode::PullDown)?; - let context = timer::DriverContext::create()?; - let mut driver = context.create_timer_driver()?; + let mut driver = timer_context.create_timer_driver(); let timer_driver = driver.activate()?; loop {
diff --git a/examples/hello.rs b/examples/hello.rs index 9bc98a8..9a7d11d 100644 --- a/examples/hello.rs +++ b/examples/hello.rs
@@ -2,16 +2,18 @@ use core::fmt::Write; use libtock::result::TockResult; -use libtock::timer; use libtock::timer::Duration; use libtock::Hardware; #[libtock::main] async fn main() -> TockResult<()> { - let Hardware { console_driver, .. } = libtock::retrieve_hardware()?; + let Hardware { + console_driver, + timer_context, + .. + } = libtock::retrieve_hardware()?; let mut console = console_driver.create_console(); - let context = timer::DriverContext::create()?; - let mut driver = context.create_timer_driver()?; + let mut driver = timer_context.create_timer_driver(); let timer_driver = driver.activate()?; for i in 0.. {
diff --git a/examples/sensors.rs b/examples/sensors.rs index e24c95b..6f772ec 100644 --- a/examples/sensors.rs +++ b/examples/sensors.rs
@@ -4,20 +4,22 @@ use libtock::result::TockResult; use libtock::sensors::Ninedof; use libtock::sensors::*; -use libtock::timer; use libtock::timer::Duration; use libtock::Hardware; #[libtock::main] async fn main() -> TockResult<()> { - let Hardware { console_driver, .. } = libtock::retrieve_hardware()?; + let Hardware { + console_driver, + timer_context, + .. + } = libtock::retrieve_hardware()?; let mut console = console_driver.create_console(); let mut humidity = HumiditySensor; let mut temperature = TemperatureSensor; let mut light = AmbientLightSensor; let mut ninedof = Ninedof::default(); - let context = timer::DriverContext::create()?; - let mut driver = context.create_timer_driver()?; + let mut driver = timer_context.create_timer_driver(); let timer_driver = driver.activate()?; loop {
diff --git a/examples/seven_segment.rs b/examples/seven_segment.rs index cf884e4..1b1b055 100644 --- a/examples/seven_segment.rs +++ b/examples/seven_segment.rs
@@ -3,8 +3,8 @@ use libtock::electronics::ShiftRegister; use libtock::gpio::GpioPinUnitialized; use libtock::result::TockResult; -use libtock::timer; use libtock::timer::Duration; +use libtock::Hardware; fn number_to_bits(n: u8) -> [bool; 8] { match n { @@ -25,14 +25,14 @@ // Example works on a shift register on P0.03, P0.04, P0.28 #[libtock::main] async fn main() -> TockResult<()> { + let Hardware { timer_context, .. } = libtock::retrieve_hardware()?; let shift_register = ShiftRegister::new( GpioPinUnitialized::new(0).open_for_write()?, GpioPinUnitialized::new(1).open_for_write()?, GpioPinUnitialized::new(2).open_for_write()?, ); - let context = timer::DriverContext::create()?; - let mut driver = context.create_timer_driver()?; + let mut driver = timer_context.create_timer_driver(); let timer_driver = driver.activate()?; let mut i = 0;
diff --git a/examples/simple_ble.rs b/examples/simple_ble.rs index 7988c9e..d96b799 100644 --- a/examples/simple_ble.rs +++ b/examples/simple_ble.rs
@@ -4,7 +4,6 @@ use libtock::ble_composer::BlePayload; use libtock::result::TockResult; use libtock::simple_ble::BleAdvertisingDriver; -use libtock::timer; use libtock::timer::Duration; use libtock::Hardware; use serde::Serialize; @@ -17,7 +16,11 @@ #[libtock::main] async fn main() -> TockResult<()> { - let Hardware { mut led_driver, .. } = libtock::retrieve_hardware()?; + let Hardware { + mut led_driver, + timer_context, + .. + } = libtock::retrieve_hardware()?; let mut led = led_driver.get(0).unwrap(); @@ -42,8 +45,7 @@ let _handle = BleAdvertisingDriver::initialize(100, &gap_payload, &mut buffer); - let context = timer::DriverContext::create()?; - let mut driver = context.create_timer_driver()?; + let mut driver = timer_context.create_timer_driver(); let timer_driver = driver.activate()?; loop {
diff --git a/examples/timer_parallel.rs b/examples/timer_parallel.rs index d640ebd..e0b42c9 100644 --- a/examples/timer_parallel.rs +++ b/examples/timer_parallel.rs
@@ -3,7 +3,6 @@ use futures::future; use libtock::led::Led; use libtock::result::TockResult; -use libtock::timer; use libtock::timer::Duration; use libtock::timer::ParallelSleepDriver; use libtock::Hardware; @@ -22,14 +21,17 @@ #[libtock::main] async fn main() -> TockResult<()> { - let Hardware { mut led_driver, .. } = libtock::retrieve_hardware()?; + let Hardware { + mut led_driver, + timer_context, + .. + } = libtock::retrieve_hardware()?; let mut led_iter = led_driver.all(); let mut led_1 = led_iter.next().unwrap(); let mut led_2 = led_iter.next().unwrap(); let mut led_3 = led_iter.next().unwrap(); - let context = timer::DriverContext::create()?; - let mut driver = context.create_timer_driver()?; + let mut driver = timer_context.create_timer_driver(); let timer_driver = driver.activate()?; let fut_1 = blink(&timer_driver, Duration::from_ms(500), &mut led_1);
diff --git a/src/hardware.rs b/src/hardware.rs index 9cf8e98..6e8b84d 100644 --- a/src/hardware.rs +++ b/src/hardware.rs
@@ -3,11 +3,14 @@ use crate::result::OtherError; use crate::result::TockError; use crate::result::TockResult; +use crate::timer::DriverContext; +use core::cell::Cell; /// Struct containing all drivers constructible through retrieve_hardware() pub struct Hardware { pub console_driver: ConsoleDriver, pub led_driver: LedDriver, + pub timer_context: DriverContext, } /// Retrieve Hardware struct. Returns Hardware only once. @@ -28,6 +31,7 @@ HARDWARE } +#[allow(clippy::declare_interior_mutable_const)] const HARDWARE: Hardware = Hardware { console_driver: ConsoleDriver { _unconstructible: (), @@ -35,6 +39,9 @@ led_driver: LedDriver { _unconstructible: (), }, + timer_context: DriverContext { + active_timer: Cell::new(None), + }, }; static mut HARDWARE_SINGLETON: Option<Hardware> = Some(HARDWARE);
diff --git a/src/lang_items.rs b/src/lang_items.rs index 0b3186e..b43b43f 100644 --- a/src/lang_items.rs +++ b/src/lang_items.rs
@@ -18,7 +18,6 @@ //! `rustc_main`. That's covered by the `_start` function in the root of this //! crate. -use crate::timer; use crate::timer::Duration; use crate::Hardware; use core::alloc::Layout; @@ -47,10 +46,13 @@ // Flash all LEDs (if available). executor::block_on(async { - let context = timer::DriverContext::create().ok(); - let mut driver = context.as_ref().map(|c| c.create_timer_driver_unsafe()); - let timer_driver = driver.as_mut().and_then(|d| d.activate().ok()); - let Hardware { mut led_driver, .. } = crate::retrieve_hardware_unsafe(); + let Hardware { + mut led_driver, + timer_context, + .. + } = crate::retrieve_hardware_unsafe(); + let mut driver = timer_context.create_timer_driver(); + let timer_driver = driver.activate().ok(); loop { for mut led in led_driver.all() { @@ -74,10 +76,13 @@ #[alloc_error_handler] unsafe fn cycle_leds(_: Layout) -> ! { executor::block_on(async { - let context = timer::DriverContext::create().ok(); - let mut driver = context.as_ref().map(|c| c.create_timer_driver_unsafe()); - let timer_driver = driver.as_mut().and_then(|d| d.activate().ok()); - let Hardware { mut led_driver, .. } = crate::retrieve_hardware_unsafe(); + let Hardware { + mut led_driver, + timer_context, + .. + } = crate::retrieve_hardware_unsafe(); + let mut driver = timer_context.create_timer_driver(); + let timer_driver = driver.activate().ok(); loop { for mut led in led_driver.all() {
diff --git a/src/timer.rs b/src/timer.rs index a0172b0..c4e452a 100644 --- a/src/timer.rs +++ b/src/timer.rs
@@ -282,10 +282,8 @@ } } -static mut TIMER_DRIVER_AVAILABLE: bool = true; - #[derive(Copy, Clone, Default, PartialEq, Eq)] -struct ActiveTimer { +pub(crate) struct ActiveTimer { instant: u32, set_at: u32, } @@ -295,54 +293,22 @@ /// ```no_run /// # use libtock::timer::DriverContext; /// # use libtock::result::TockResult; +/// # use libtock::Hardware; /// # #[libtock::main] /// # async fn main() -> TockResult<()> { -/// let context = DriverContext::create(); -/// # Ok(()) +/// let Hardware { timer_context,.. } = libtock::retrieve_hardware()?; +/// Ok(()) /// # } /// ``` pub struct DriverContext { - active_timer: Cell<Option<ActiveTimer>>, - current_time: Cell<usize>, + pub(crate) active_timer: Cell<Option<ActiveTimer>>, } impl DriverContext { - /// Create a driver context - pub fn create() -> TockResult<Self> { - let num_ticks = get_current_ticks()?; - Ok(DriverContext { - active_timer: Default::default(), - current_time: Cell::new(num_ticks), - }) - } - /// Create a driver timer from a context. As the driver is a singleton - /// from the app perspective this function will return None - /// if called more than once. - pub fn create_timer_driver<'a>(&'a self) -> TockResult<TimerDriver<'a>> { - if unsafe { TIMER_DRIVER_AVAILABLE } { - unsafe { - TIMER_DRIVER_AVAILABLE = false; - } - Ok(TimerDriver { - callback: Callback { - now: &self.current_time, - }, - context: &self, - }) - } else { - Err(TockError::Other(OtherError::DriverAlreadyTaken)) - } - } - - /// Create a timer driver instance without checking for running instance - /// # Safety - /// May lead to undefined behavior at the previous consumer of the timer driver. - /// Only safe if no other consumer is still running (e.g. on unwind) - pub unsafe fn create_timer_driver_unsafe(&self) -> TimerDriver<'_> { + /// Create a driver timer from a context. + pub fn create_timer_driver(&self) -> TimerDriver<'_> { TimerDriver { - callback: Callback { - now: &self.current_time, - }, + callback: Callback, context: &self, } } @@ -352,26 +318,24 @@ /// ```no_run /// # use libtock::timer::DriverContext; /// # use libtock::result::TockResult; +/// # use libtock::Hardware; /// # #[libtock::main] /// # async fn main() -> TockResult<()> { -/// let context = DriverContext::create()?; -/// context.create_timer_driver().expect("The timer driver is a singleton and can only created once."); +/// # let Hardware { timer_context,.. } = libtock::retrieve_hardware()?; +/// # let mut driver = timer_context.create_timer_driver(); +/// let timer_driver = driver.activate()?; /// # Ok(()) /// # } /// ``` pub struct TimerDriver<'a> { - callback: Callback<'a>, + callback: Callback, context: &'a DriverContext, } -struct Callback<'a> { - now: &'a Cell<usize>, -} +struct Callback; -impl<'a> SubscribableCallback for Callback<'a> { - fn call_rust(&mut self, now: usize, _: usize, _: usize) { - self.now.set(now); - } +impl SubscribableCallback for Callback { + fn call_rust(&mut self, _: usize, _: usize, _: usize) {} } /// Activated time driver. Updates current time in the context and manages @@ -381,10 +345,11 @@ /// # use libtock::timer::DriverContext; /// # use libtock::result::TockResult; /// # use libtock::timer::Duration; +/// # use libtock::Hardware; /// # #[libtock::main] /// # async fn main() -> TockResult<()> { -/// let context = DriverContext::create()?; -/// let mut driver = context.create_timer_driver().unwrap(); +/// # let Hardware { timer_context,.. } = libtock::retrieve_hardware()?; +/// # let mut driver = timer_context.create_timer_driver(); /// let timer_driver = driver.activate()?; /// timer_driver.sleep(Duration::from_ms(1000)).await?; /// # Ok(()) @@ -416,7 +381,6 @@ /// Sleep for the given duration pub async fn sleep(&self, duration: Duration<usize>) -> TockResult<()> { let now = get_current_ticks()?; - self.context.current_time.set(now); let freq = get_clock_frequency()?; let alarm_instant = Self::compute_alarm_instant(duration.ms, now, freq)?; let this_alarm = ActiveTimer {