Merge #122
122: Create 'drivers' singleton r=torfmaster a=torfmaster
# Overview
The drivers as well as the hardware represented by the drivers is only available once. To prevent hacing multiple mutable references to this global mutable state we do the following:
* collect all drivers in a `drivers` object which is a singleton
* ~if a driver allows to create a mutable reference to a part (e.g. an led) mutably borrow the driver as whole~
# Progress
The following drivers have been migrated:
[x] Timer
[x] Led
[x] Console
[x] GPIO
[x] Temperature
[x] Buttons
[x] ADC
[x] RNG
[x] BLE
[x] ninedof
# Help needed
As this PR concerns API design comments are welcome!
Moreover, the initialization of the `Hardware` struct is very verbose. However, initialization using a
`Default` implementation is not desired as this would make the individual drivers constructible outside the trate which is unsafe. Any ideas are very welcome.
Co-authored-by: torfmaster <briefe@kebes.de>
diff --git a/.travis.yml b/.travis.yml
index 0bcbb0c..d3547db 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,7 +13,7 @@
- linux
- osx
-cache: rust
+cache: cargo
install:
- rustup target add thumbv7em-none-eabi
@@ -22,7 +22,4 @@
- rustup component add clippy
script:
- - cargo fmt --all -- --check
- - cargo test --workspace
- - cargo clippy --workspace --all-targets
- - ./build_examples.sh
+ - ./run_all_checks.sh
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 17c8d81..d15206f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,7 +17,8 @@
- `syscalls::allow_ptr` becomes `syscalls::raw::allow`
- Targets without support for atomics can be built
- Most API functions, including `main()`, return a `Result<T, TockError>`
-- The timer now supports to be used simultaneously. To make this safe, `TimerDriver` is now a singleton.
+- The library now supports parallel timers
+- all drivers can exclusively be retrieved by `retrieve_drivers` which returns a `Drivers`-singleton. Drivers can be shared between different tasks only if it is safe to do so.
## a8bb4fa9be504517d5533511fd8e607ea61f1750 (0.1.0)
diff --git a/examples/adc.rs b/examples/adc.rs
index 61894ad..ef100a3 100644
--- a/examples/adc.rs
+++ b/examples/adc.rs
@@ -1,20 +1,23 @@
#![no_std]
use core::fmt::Write;
-use libtock::adc;
-use libtock::console::Console;
use libtock::result::TockResult;
-use libtock::timer;
use libtock::timer::Duration;
+use libtock::Drivers;
#[libtock::main]
async fn main() -> TockResult<()> {
- let context = timer::DriverContext::create()?;
- let mut driver = context.create_timer_driver()?;
- let timer_driver = driver.activate()?;
+ let Drivers {
+ console_driver,
+ timer_context,
+ adc_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
- let mut console = Console::default();
- let mut with_callback = adc::with_callback(|channel: usize, value: usize| {
+ 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_driver.with_callback(|channel: usize, value: usize| {
writeln!(console, "channel: {}, value: {}", channel, value).unwrap();
});
diff --git a/examples/adc_buffer.rs b/examples/adc_buffer.rs
index 406bf57..b948b93 100644
--- a/examples/adc_buffer.rs
+++ b/examples/adc_buffer.rs
@@ -1,22 +1,26 @@
#![no_std]
use core::fmt::Write;
-use libtock::adc;
use libtock::adc::AdcBuffer;
-use libtock::console::Console;
use libtock::result::TockResult;
use libtock::syscalls;
+use libtock::Drivers;
#[libtock::main]
/// Reads a 128 byte sample into a buffer and prints the first value to the console.
async fn main() -> TockResult<()> {
- let mut console = Console::default();
+ let Drivers {
+ console_driver,
+ adc_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let mut console = console_driver.create_console();
let mut adc_buffer = AdcBuffer::default();
let mut temp_buffer = [0; libtock::adc::BUFFER_SIZE];
let adc_buffer = libtock::adc::Adc::init_buffer(&mut adc_buffer)?;
- let mut with_callback = adc::with_callback(|_, _| {
+ let mut with_callback = adc_driver.with_callback(|_, _| {
adc_buffer.read_bytes(&mut temp_buffer[..]);
writeln!(console, "First sample in buffer: {}", temp_buffer[0]).unwrap();
});
diff --git a/examples/ble_scanning.rs b/examples/ble_scanning.rs
index 78de325..a00ed46 100644
--- a/examples/ble_scanning.rs
+++ b/examples/ble_scanning.rs
@@ -2,11 +2,11 @@
use futures::future;
use libtock::ble_parser;
-use libtock::led;
use libtock::result::TockResult;
use libtock::simple_ble;
use libtock::simple_ble::BleCallback;
-use libtock::simple_ble::BleDriver;
+use libtock::simple_ble::BleScanningDriver;
+use libtock::Drivers;
use serde::Deserialize;
#[derive(Deserialize)]
@@ -17,19 +17,31 @@
#[libtock::main]
async fn main() -> TockResult<()> {
- let mut shared_buffer = BleDriver::create_scan_buffer();
- let mut my_buffer = BleDriver::create_scan_buffer();
- let shared_memory = BleDriver::share_memory(&mut shared_buffer)?;
+ let Drivers {
+ led_driver_factory,
+ mut ble_scanning_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
+
+ let led_driver = led_driver_factory.create_driver()?;
+
+ let mut shared_buffer = BleScanningDriver::create_scan_buffer();
+ let mut my_buffer = BleScanningDriver::create_scan_buffer();
+ let shared_memory = ble_scanning_driver.share_memory(&mut shared_buffer)?;
let mut callback = BleCallback::new(|_: usize, _: usize| {
shared_memory.read_bytes(&mut my_buffer[..]);
ble_parser::find(&my_buffer, simple_ble::gap_data::SERVICE_DATA as u8)
.and_then(|service_data| ble_parser::extract_for_service([91, 79], service_data))
.and_then(|payload| corepack::from_bytes::<LedCommand>(&payload).ok())
- .and_then(|msg| led::get(msg.nr as usize).map(|led| led.set_state(msg.st)));
+ .and_then(|msg| {
+ led_driver
+ .get(msg.nr as usize)
+ .map(|led| led.set_state(msg.st))
+ });
});
- let _subscription = BleDriver::start(&mut callback)?;
+ let _subscription = ble_scanning_driver.start(&mut callback)?;
future::pending().await
}
diff --git a/examples/blink.rs b/examples/blink.rs
index f37fd12..aa9b64c 100644
--- a/examples/blink.rs
+++ b/examples/blink.rs
@@ -1,26 +1,31 @@
#![no_std]
-use libtock::led;
use libtock::result::TockResult;
-use libtock::timer;
use libtock::timer::Duration;
+use libtock::Drivers;
#[libtock::main]
async fn main() -> TockResult<()> {
- let num_leds = led::count()?;
- let context = timer::DriverContext::create()?;
- let mut driver = context.create_timer_driver()?;
+ let Drivers {
+ led_driver_factory,
+ timer_context,
+ ..
+ } = libtock::retrieve_drivers()?;
+
+ let mut driver = timer_context.create_timer_driver();
let timer_driver = driver.activate()?;
+ let led_driver = led_driver_factory.create_driver()?;
// Blink the LEDs in a binary count pattern and scale
// to the number of LEDs on the board.
let mut count: usize = 0;
loop {
- for i in 0..num_leds {
+ for led in led_driver.all() {
+ let i = led.number();
if count & (1 << i) == (1 << i) {
- led::get(i).unwrap().on()?;
+ led.on()?;
} else {
- led::get(i).unwrap().off()?;
+ led.off()?;
}
}
count = count.wrapping_add(1);
diff --git a/examples/blink_random.rs b/examples/blink_random.rs
index 6b964a2..8734693 100644
--- a/examples/blink_random.rs
+++ b/examples/blink_random.rs
@@ -1,38 +1,45 @@
#![no_std]
-use libtock::led;
+use libtock::led::LedDriver;
use libtock::result::TockResult;
-use libtock::rng;
-use libtock::timer;
use libtock::timer::Duration;
+use libtock::Drivers;
#[libtock::main]
async fn main() -> TockResult<()> {
- let context = timer::DriverContext::create()?;
- let mut driver = context.create_timer_driver()?;
+ let Drivers {
+ timer_context,
+ mut rng_driver,
+ led_driver_factory,
+ ..
+ } = libtock::retrieve_drivers()?;
+
+ let led_driver = led_driver_factory.create_driver()?;
+
+ let mut driver = timer_context.create_timer_driver();
let timer_driver = driver.activate()?;
- let num_leds = led::count()?;
+ let num_leds = led_driver.count()?;
// blink_nibble assumes 4 leds.
assert_eq!(num_leds, 4);
let mut buf = [0; 64];
loop {
- rng::fill_buffer(&mut buf).await?;
+ rng_driver.fill_buffer(&mut buf).await?;
for &x in buf.iter() {
- blink_nibble(x)?;
+ blink_nibble(x, &led_driver)?;
timer_driver.sleep(Duration::from_ms(100)).await?;
- blink_nibble(x >> 4)?;
+ blink_nibble(x >> 4, &led_driver)?;
timer_driver.sleep(Duration::from_ms(100)).await?;
}
}
}
// Takes the 4 least-significant bits of x, and turn the 4 leds on/off accordingly.
-fn blink_nibble(x: u8) -> TockResult<()> {
+fn blink_nibble(x: u8, led_driver: &LedDriver) -> TockResult<()> {
for i in 0..4 {
- let led = led::get(i).unwrap();
+ let led = led_driver.get(i).unwrap();
if (x >> i) & 1 != 0 {
led.on()?;
} else {
diff --git a/examples/button_leds.rs b/examples/button_leds.rs
index 294d45a..ce6565f 100644
--- a/examples/button_leds.rs
+++ b/examples/button_leds.rs
@@ -1,16 +1,23 @@
#![no_std]
use futures::future;
-use libtock::buttons;
use libtock::buttons::ButtonState;
-use libtock::led;
use libtock::result::TockResult;
+use libtock::Drivers;
#[libtock::main]
async fn main() -> TockResult<()> {
- let mut with_callback = buttons::with_callback(|button_num: usize, state| {
+ let Drivers {
+ led_driver_factory,
+ button_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
+
+ let led_driver = led_driver_factory.create_driver()?;
+
+ let mut with_callback = button_driver.with_callback(|button_num: usize, state| {
match state {
- ButtonState::Pressed => led::get(button_num).unwrap().toggle().ok().unwrap(),
+ ButtonState::Pressed => led_driver.get(button_num).unwrap().toggle().ok().unwrap(),
ButtonState::Released => (),
};
});
diff --git a/examples/button_read.rs b/examples/button_read.rs
index d86e70d..2ce209f 100644
--- a/examples/button_read.rs
+++ b/examples/button_read.rs
@@ -1,23 +1,26 @@
#![no_std]
use core::fmt::Write;
-use libtock::buttons;
use libtock::buttons::ButtonState;
-use libtock::console::Console;
use libtock::result::TockResult;
-use libtock::timer;
use libtock::timer::Duration;
+use libtock::Drivers;
#[libtock::main]
async fn main() -> TockResult<()> {
- let mut console = Console::default();
- let mut with_callback = buttons::with_callback(|_, _| {});
+ let Drivers {
+ console_driver,
+ timer_context,
+ button_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let mut console = console_driver.create_console();
+ let mut with_callback = button_driver.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/button_subscribe.rs b/examples/button_subscribe.rs
index 3453c9b..268e6f0 100644
--- a/examples/button_subscribe.rs
+++ b/examples/button_subscribe.rs
@@ -2,17 +2,20 @@
use core::fmt::Write;
use futures::future;
-use libtock::buttons;
use libtock::buttons::ButtonState;
-use libtock::console::Console;
use libtock::result::TockResult;
+use libtock::Drivers;
// FIXME: Hangs up when buttons are pressed rapidly. Yielding in callback leads to stack overflow.
#[libtock::main]
async fn main() -> TockResult<()> {
- let mut console = Console::default();
-
- let mut with_callback = buttons::with_callback(|button_num: usize, state| {
+ let Drivers {
+ console_driver,
+ button_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let mut console = console_driver.create_console();
+ let mut with_callback = button_driver.with_callback(|button_num: usize, state| {
writeln!(
console,
"Button: {} - State: {}",
diff --git a/examples/gpio.rs b/examples/gpio.rs
index e472f2a..ee42d69 100644
--- a/examples/gpio.rs
+++ b/examples/gpio.rs
@@ -1,17 +1,20 @@
#![no_std]
-use libtock::gpio::GpioPinUnitialized;
use libtock::result::TockResult;
-use libtock::timer;
use libtock::timer::Duration;
+use libtock::Drivers;
// Example works on P0.03
#[libtock::main]
async fn main() -> TockResult<()> {
- let pin = GpioPinUnitialized::new(0);
+ let Drivers {
+ timer_context,
+ gpio_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let pin = gpio_driver.pin(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 ad871ac..5e3d403 100644
--- a/examples/gpio_read.rs
+++ b/examples/gpio_read.rs
@@ -1,21 +1,24 @@
#![no_std]
use core::fmt::Write;
-use libtock::console::Console;
-use libtock::gpio::GpioPinUnitialized;
use libtock::gpio::InputMode;
use libtock::result::TockResult;
-use libtock::timer;
use libtock::timer::Duration;
+use libtock::Drivers;
// example works on p0.03
#[libtock::main]
async fn main() -> TockResult<()> {
- let mut console = Console::default();
- let pin = GpioPinUnitialized::new(0);
+ let Drivers {
+ console_driver,
+ timer_context,
+ gpio_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let mut console = console_driver.create_console();
+ let pin = gpio_driver.pin(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/hardware_test.rs b/examples/hardware_test.rs
index 4f8ad5f..db2dd34 100644
--- a/examples/hardware_test.rs
+++ b/examples/hardware_test.rs
@@ -8,10 +8,13 @@
use core::fmt::Write;
use futures::future;
use libtock::console::Console;
-use libtock::gpio::{GpioPinUnitialized, InputMode};
+use libtock::gpio::GpioPinRead;
+use libtock::gpio::GpioPinWrite;
+use libtock::gpio::InputMode;
use libtock::result::TockResult;
-use libtock::timer;
+use libtock::timer::DriverContext;
use libtock::timer::Duration;
+use libtock::Drivers;
static mut STATIC: usize = 0;
@@ -33,18 +36,30 @@
#[libtock::main]
async fn main() -> TockResult<()> {
- let mut console = Console::default();
+ let Drivers {
+ console_driver,
+ gpio_driver,
+ mut timer_context,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let mut gpio_iter = gpio_driver.all_pins()?;
+ let mut console = console_driver.create_console();
+ let pin_in = gpio_iter.next().unwrap();
+ let pin_out = gpio_iter.next().unwrap();
+ let pin_in = pin_in.open_for_read(None, InputMode::PullDown)?;
+ let mut pin_out = pin_out.open_for_write()?;
+
writeln!(console, "[test-results]")?;
test_heap(&mut console);
test_formatting(&mut console);
test_static_mut(&mut console);
- test_gpio(&mut console);
+ test_gpio(&mut console, &pin_in, &mut pin_out);
- test_trait_objects(&mut console)?;
+ test_trait_objects(&mut console, &pin_in, &mut pin_out)?;
- test_callbacks_and_wait_forever(&mut console).await
+ test_callbacks_and_wait_forever(&mut console, &mut timer_context).await
}
fn test_heap(console: &mut Console) {
@@ -61,12 +76,11 @@
/// Output order should be:
/// trait_obj_value_usize = 1
/// trait_obj_value_string = string
-fn test_trait_objects(console: &mut Console) -> TockResult<()> {
- let pin_in = GpioPinUnitialized::new(0);
- let pin_in = pin_in.open_for_read(None, InputMode::PullDown)?;
-
- let pin_out = GpioPinUnitialized::new(1);
- let pin_out = pin_out.open_for_write()?;
+fn test_trait_objects(
+ console: &mut Console,
+ pin_in: &GpioPinRead,
+ pin_out: &mut GpioPinWrite,
+) -> TockResult<()> {
pin_out.set_high()?;
let string = String::from("string");
@@ -95,22 +109,17 @@
}
/// needs P0.03 and P0.04 to be connected
-fn test_gpio(console: &mut Console) {
- let pin_in = GpioPinUnitialized::new(0);
- let pin_in = pin_in
- .open_for_read(None, InputMode::PullDown)
- .ok()
- .unwrap();
-
- let pin_out = GpioPinUnitialized::new(1);
- let pin_out = pin_out.open_for_write().ok().unwrap();
+fn test_gpio(console: &mut Console, pin_in: &GpioPinRead, pin_out: &mut GpioPinWrite) {
pin_out.set_high().ok().unwrap();
writeln!(console, "gpio_works = {}", pin_in.read()).unwrap();
}
-async fn test_callbacks_and_wait_forever(console: &mut Console) -> TockResult<()> {
- let mut with_callback = timer::with_callback(|_, _| {
+async fn test_callbacks_and_wait_forever(
+ console: &mut Console,
+ timer_context: &mut DriverContext,
+) -> TockResult<()> {
+ let mut with_callback = timer_context.with_callback(|_, _| {
writeln!(console, "callbacks_work = true").unwrap();
writeln!(console, "all_tests_run = true").unwrap();
});
diff --git a/examples/hello.rs b/examples/hello.rs
index 5e4f987..3cbaf2f 100644
--- a/examples/hello.rs
+++ b/examples/hello.rs
@@ -1,16 +1,19 @@
#![no_std]
use core::fmt::Write;
-use libtock::console::Console;
use libtock::result::TockResult;
-use libtock::timer;
use libtock::timer::Duration;
+use libtock::Drivers;
#[libtock::main]
async fn main() -> TockResult<()> {
- let mut console = Console::default();
- let context = timer::DriverContext::create()?;
- let mut driver = context.create_timer_driver()?;
+ let Drivers {
+ console_driver,
+ timer_context,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let mut console = console_driver.create_console();
+ 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 9936d31..4e72c8c 100644
--- a/examples/sensors.rs
+++ b/examples/sensors.rs
@@ -1,29 +1,35 @@
#![no_std]
use core::fmt::Write;
-use libtock::console::Console;
use libtock::result::TockResult;
-use libtock::sensors::Ninedof;
use libtock::sensors::*;
-use libtock::timer;
use libtock::timer::Duration;
+use libtock::Drivers;
#[libtock::main]
async fn main() -> TockResult<()> {
- let mut console = Console::default();
- 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 Drivers {
+ console_driver,
+ timer_context,
+ mut temperature_sensor,
+ mut humidity_sensor,
+ mut ambient_light_sensor,
+ mut ninedof_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let mut console = console_driver.create_console();
+ let mut driver = timer_context.create_timer_driver();
let timer_driver = driver.activate()?;
loop {
- writeln!(console, "Humidity: {}\n", humidity.read()?)?;
- writeln!(console, "Temperature: {}\n", temperature.read()?)?;
- writeln!(console, "Light: {}\n", light.read()?)?;
- writeln!(console, "Accel: {}\n", ninedof.read_acceleration()?)?;
+ writeln!(console, "Humidity: {}\n", humidity_sensor.read()?)?;
+ writeln!(console, "Temperature: {}\n", temperature_sensor.read()?)?;
+ writeln!(console, "Light: {}\n", ambient_light_sensor.read()?)?;
+ writeln!(
+ console,
+ "Accel: {}\n",
+ ninedof_driver.read_acceleration()?
+ )?;
timer_driver.sleep(Duration::from_ms(500)).await?;
}
}
diff --git a/examples/seven_segment.rs b/examples/seven_segment.rs
index cf884e4..4249157 100644
--- a/examples/seven_segment.rs
+++ b/examples/seven_segment.rs
@@ -1,10 +1,9 @@
#![no_std]
use libtock::electronics::ShiftRegister;
-use libtock::gpio::GpioPinUnitialized;
use libtock::result::TockResult;
-use libtock::timer;
use libtock::timer::Duration;
+use libtock::Drivers;
fn number_to_bits(n: u8) -> [bool; 8] {
match n {
@@ -25,14 +24,18 @@
// Example works on a shift register on P0.03, P0.04, P0.28
#[libtock::main]
async fn main() -> TockResult<()> {
- let shift_register = ShiftRegister::new(
- GpioPinUnitialized::new(0).open_for_write()?,
- GpioPinUnitialized::new(1).open_for_write()?,
- GpioPinUnitialized::new(2).open_for_write()?,
+ let Drivers {
+ timer_context,
+ gpio_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let mut shift_register = ShiftRegister::new(
+ gpio_driver.pin(0)?.open_for_write()?,
+ gpio_driver.pin(1)?.open_for_write()?,
+ gpio_driver.pin(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 97511a0..e312ef5 100644
--- a/examples/simple_ble.rs
+++ b/examples/simple_ble.rs
@@ -2,11 +2,10 @@
use libtock::ble_composer;
use libtock::ble_composer::BlePayload;
-use libtock::led;
use libtock::result::TockResult;
use libtock::simple_ble::BleAdvertisingDriver;
-use libtock::timer;
use libtock::timer::Duration;
+use libtock::Drivers;
use serde::Serialize;
#[derive(Serialize)]
@@ -17,7 +16,16 @@
#[libtock::main]
async fn main() -> TockResult<()> {
- let led = led::get(0).unwrap();
+ let Drivers {
+ led_driver_factory,
+ timer_context,
+ mut ble_advertising_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
+
+ let led_driver = led_driver_factory.create_driver()?;
+
+ let led = led_driver.get(0).unwrap();
let uuid: [u8; 2] = [0x00, 0x18];
@@ -38,10 +46,9 @@
.unwrap();
gap_payload.add_service_payload([91, 79], &payload).unwrap();
- let _handle = BleAdvertisingDriver::initialize(100, &gap_payload, &mut buffer);
+ let _handle = ble_advertising_driver.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/temperature.rs b/examples/temperature.rs
index 8a3eef0..9198f1b 100644
--- a/examples/temperature.rs
+++ b/examples/temperature.rs
@@ -1,13 +1,17 @@
#![no_std]
use core::fmt::Write;
-use libtock::console::Console;
use libtock::result::TockResult;
-use libtock::temperature;
+use libtock::Drivers;
#[libtock::main]
async fn main() -> TockResult<()> {
- let mut console = Console::default();
- let temperature = temperature::measure_temperature().await?;
+ let Drivers {
+ console_driver,
+ mut temperature_driver,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let mut console = console_driver.create_console();
+ let temperature = temperature_driver.measure_temperature().await?;
writeln!(console, "Temperature: {}", temperature).map_err(Into::into)
}
diff --git a/examples/timer_parallel.rs b/examples/timer_parallel.rs
index c19e583..389727a 100644
--- a/examples/timer_parallel.rs
+++ b/examples/timer_parallel.rs
@@ -1,19 +1,19 @@
#![no_std]
use futures::future;
-use libtock::led;
+use libtock::led::Led;
use libtock::result::TockResult;
-use libtock::timer;
use libtock::timer::Duration;
use libtock::timer::ParallelSleepDriver;
+use libtock::Drivers;
async fn blink<'a>(
timer_driver: &'a ParallelSleepDriver<'a>,
duration: Duration<usize>,
- led_number: usize,
+ led: &'a mut Led<'a>,
) -> TockResult<()> {
loop {
- led::get(led_number).unwrap().toggle()?;
+ led.toggle()?;
timer_driver.sleep(duration).await?;
}
@@ -21,13 +21,24 @@
#[libtock::main]
async fn main() -> TockResult<()> {
- let context = timer::DriverContext::create()?;
- let mut driver = context.create_timer_driver()?;
+ let Drivers {
+ led_driver_factory,
+ timer_context,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let led_driver = led_driver_factory.create_driver()?;
+
+ 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 mut driver = timer_context.create_timer_driver();
let timer_driver = driver.activate()?;
- let fut_1 = blink(&timer_driver, Duration::from_ms(500), 0);
- let fut_2 = blink(&timer_driver, Duration::from_ms(333), 1);
- let fut_3 = blink(&timer_driver, Duration::from_ms(250), 2);
+ let fut_1 = blink(&timer_driver, Duration::from_ms(500), &mut led_1);
+ let fut_2 = blink(&timer_driver, Duration::from_ms(333), &mut led_2);
+ let fut_3 = blink(&timer_driver, Duration::from_ms(250), &mut led_3);
future::try_join3(fut_1, fut_2, fut_3).await?;
Ok(())
diff --git a/examples/timer_subscribe.rs b/examples/timer_subscribe.rs
index 11afdfd..f7e158c 100644
--- a/examples/timer_subscribe.rs
+++ b/examples/timer_subscribe.rs
@@ -2,16 +2,19 @@
use core::fmt::Write;
use futures::future;
-use libtock::console::Console;
use libtock::result::TockResult;
-use libtock::timer;
use libtock::timer::Duration;
+use libtock::Drivers;
#[libtock::main]
async fn main() -> TockResult<()> {
- let mut console = Console::default();
-
- let mut with_callback = timer::with_callback(|_, _| {
+ let Drivers {
+ console_driver,
+ mut timer_context,
+ ..
+ } = libtock::retrieve_drivers()?;
+ let mut console = console_driver.create_console();
+ let mut with_callback = timer_context.with_callback(|_, _| {
writeln!(
console,
"This line is printed 2 seconds after the start of the program.",
diff --git a/run_all_checks.sh b/run_all_checks.sh
new file mode 100755
index 0000000..7d96180
--- /dev/null
+++ b/run_all_checks.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+set -eux
+
+cargo fmt --all -- --check
+cargo test --workspace
+cargo clippy --workspace --all-targets
+./build_examples.sh
diff --git a/src/adc.rs b/src/adc.rs
index ecb18df..7a18cce 100644
--- a/src/adc.rs
+++ b/src/adc.rs
@@ -6,7 +6,7 @@
pub const DRIVER_NUM: usize = 0x0005;
pub const BUFFER_SIZE: usize = 128;
-mod command {
+mod command_nr {
pub const COUNT: usize = 0;
pub const START: usize = 1;
pub const START_REPEAT: usize = 2;
@@ -15,15 +15,24 @@
pub const STOP: usize = 5;
}
-mod subscribe {
+mod subscribe_nr {
pub const SUBSCRIBE_CALLBACK: usize = 0;
}
-mod allow {
+mod allow_nr {
pub const BUFFER: usize = 0;
pub const BUFFER_ALT: usize = 1;
}
+#[non_exhaustive]
+pub struct AdcDriver;
+
+impl AdcDriver {
+ pub fn with_callback<CB>(self, callback: CB) -> WithCallback<CB> {
+ WithCallback { callback }
+ }
+}
+
pub struct AdcBuffer {
// TODO: make this generic if possible with the driver impl
buffer: [u8; BUFFER_SIZE],
@@ -43,10 +52,6 @@
subscription: CallbackSubscription<'a>,
}
-pub fn with_callback<CB>(callback: CB) -> WithCallback<CB> {
- WithCallback { callback }
-}
-
pub struct WithCallback<CB> {
callback: CB,
}
@@ -63,8 +68,8 @@
{
pub fn init(&mut self) -> TockResult<Adc> {
let adc = Adc {
- count: syscalls::command(DRIVER_NUM, command::COUNT, 0, 0)?,
- subscription: syscalls::subscribe(DRIVER_NUM, subscribe::SUBSCRIBE_CALLBACK, self)?,
+ count: syscalls::command(DRIVER_NUM, command_nr::COUNT, 0, 0)?,
+ subscription: syscalls::subscribe(DRIVER_NUM, subscribe_nr::SUBSCRIBE_CALLBACK, self)?,
};
Ok(adc)
}
@@ -72,11 +77,12 @@
impl<'a> Adc<'a> {
pub fn init_buffer(buffer: &'a mut AdcBuffer) -> TockResult<SharedMemory> {
- syscalls::allow(DRIVER_NUM, allow::BUFFER, &mut buffer.buffer).map_err(Into::into)
+ syscalls::allow(DRIVER_NUM, allow_nr::BUFFER, &mut buffer.buffer).map_err(Into::into)
}
pub fn init_alt_buffer(alt_buffer: &'a mut AdcBuffer) -> TockResult<SharedMemory> {
- syscalls::allow(DRIVER_NUM, allow::BUFFER_ALT, &mut alt_buffer.buffer).map_err(Into::into)
+ syscalls::allow(DRIVER_NUM, allow_nr::BUFFER_ALT, &mut alt_buffer.buffer)
+ .map_err(Into::into)
}
/// Return the number of available channels
@@ -86,19 +92,24 @@
/// Start a single sample of channel
pub fn sample(&self, channel: usize) -> TockResult<()> {
- syscalls::command(DRIVER_NUM, command::START, channel, 0)?;
+ syscalls::command(DRIVER_NUM, command_nr::START, channel, 0)?;
Ok(())
}
/// Start continuous sampling of channel
pub fn sample_continuous(&self, channel: usize) -> TockResult<()> {
- syscalls::command(DRIVER_NUM, command::START_REPEAT, channel, 0)?;
+ syscalls::command(DRIVER_NUM, command_nr::START_REPEAT, channel, 0)?;
Ok(())
}
/// Start continuous sampling to first buffer
pub fn sample_continuous_buffered(&self, channel: usize, frequency: usize) -> TockResult<()> {
- syscalls::command(DRIVER_NUM, command::START_REPEAT_BUFFER, channel, frequency)?;
+ syscalls::command(
+ DRIVER_NUM,
+ command_nr::START_REPEAT_BUFFER,
+ channel,
+ frequency,
+ )?;
Ok(())
}
@@ -110,7 +121,7 @@
) -> TockResult<()> {
syscalls::command(
DRIVER_NUM,
- command::START_REPEAT_BUFFER_ALT,
+ command_nr::START_REPEAT_BUFFER_ALT,
channel,
frequency,
)?;
@@ -119,7 +130,7 @@
/// Stop any started sampling operation
pub fn stop(&self) -> TockResult<()> {
- syscalls::command(DRIVER_NUM, command::STOP, 0, 0)?;
+ syscalls::command(DRIVER_NUM, command_nr::STOP, 0, 0)?;
Ok(())
}
}
diff --git a/src/buttons.rs b/src/buttons.rs
index c360f7a..7004cd8 100644
--- a/src/buttons.rs
+++ b/src/buttons.rs
@@ -17,8 +17,13 @@
pub const SUBSCRIBE_CALLBACK: usize = 0;
}
-pub fn with_callback<CB>(callback: CB) -> WithCallback<CB> {
- WithCallback { callback }
+#[non_exhaustive]
+pub struct ButtonDriver;
+
+impl ButtonDriver {
+ pub fn with_callback<CB>(self, callback: CB) -> WithCallback<CB> {
+ WithCallback { callback }
+ }
}
pub struct WithCallback<CB> {
diff --git a/src/console.rs b/src/console.rs
index bfcd6d7..b4f2c51 100644
--- a/src/console.rs
+++ b/src/console.rs
@@ -20,6 +20,17 @@
pub const SHARE_BUFFER: usize = 1;
}
+#[non_exhaustive]
+pub struct ConsoleDriver;
+
+impl ConsoleDriver {
+ pub fn create_console(self) -> Console {
+ Console {
+ allow_buffer: [0; 64],
+ }
+ }
+}
+
pub struct Console {
allow_buffer: [u8; 64],
}
@@ -63,14 +74,6 @@
}
}
-impl Default for Console {
- fn default() -> Self {
- Console {
- allow_buffer: [0; 64],
- }
- }
-}
-
impl fmt::Write for Console {
fn write_str(&mut self, string: &str) -> Result<(), fmt::Error> {
self.write(string).map_err(|_| fmt::Error)
diff --git a/src/debug/mod.rs b/src/debug/mod.rs
index f67ae9b..1e55bb3 100644
--- a/src/debug/mod.rs
+++ b/src/debug/mod.rs
@@ -1,20 +1,23 @@
//! Heapless debugging functions for Tock troubleshooting
mod low_level_debug;
+use crate::drivers::Drivers;
pub use low_level_debug::*;
-use crate::console::Console;
+use crate::retrieve_drivers_unsafe;
pub fn println() {
let buffer = [b'\n'];
- let mut console = Console::default();
+ let Drivers { console_driver, .. } = unsafe { retrieve_drivers_unsafe() };
+ let mut console = console_driver.create_console();
let _ = console.write(&buffer);
}
pub fn print_as_hex(value: usize) {
let mut buffer = [b'\n'; 11];
write_as_hex(&mut buffer, value);
- let mut console = Console::default();
+ let Drivers { console_driver, .. } = unsafe { retrieve_drivers_unsafe() };
+ let mut console = console_driver.create_console();
let _ = console.write(buffer);
}
@@ -26,7 +29,8 @@
let mut buffer = [b'\n'; 15];
buffer[0..4].clone_from_slice(b"SP: ");
write_as_hex(&mut buffer[4..15], stack_pointer);
- let mut console = Console::default();
+ let Drivers { console_driver, .. } = unsafe { retrieve_drivers_unsafe() };
+ let mut console = console_driver.create_console();
let _ = console.write(buffer);
}
@@ -50,7 +54,8 @@
}
}
buffer[27] = b'\n';
- let mut console = Console::default();
+ let Drivers { console_driver, .. } = retrieve_drivers_unsafe();
+ let mut console = console_driver.create_console();
let _ = console.write(&buffer);
}
diff --git a/src/drivers.rs b/src/drivers.rs
new file mode 100644
index 0000000..814f61b
--- /dev/null
+++ b/src/drivers.rs
@@ -0,0 +1,97 @@
+use crate::adc::AdcDriver;
+use crate::buttons::ButtonDriver;
+use crate::console::ConsoleDriver;
+use crate::gpio::GpioDriver;
+use crate::led::LedDriverFactory;
+use crate::result::OtherError;
+use crate::result::TockError;
+use crate::result::TockResult;
+use crate::rng::RngDriver;
+use crate::sensors::ninedof::NinedofDriver;
+use crate::sensors::AmbientLightSensor;
+use crate::sensors::HumiditySensor;
+use crate::sensors::TemperatureSensor;
+use crate::simple_ble::BleAdvertisingDriver;
+use crate::simple_ble::BleScanningDriver;
+use crate::temperature::TemperatureDriver;
+use crate::timer::DriverContext;
+use core::cell::Cell;
+
+/// Struct containing all drivers constructible through [retrieve_drivers()]
+#[non_exhaustive]
+pub struct Drivers {
+ pub console_driver: ConsoleDriver,
+ pub led_driver_factory: LedDriverFactory,
+ pub timer_context: DriverContext,
+ pub gpio_driver: GpioDriver,
+ pub temperature_driver: TemperatureDriver,
+ pub button_driver: ButtonDriver,
+ pub adc_driver: AdcDriver,
+ pub rng_driver: RngDriver,
+ pub ble_advertising_driver: BleAdvertisingDriver,
+ pub ble_scanning_driver: BleScanningDriver,
+ pub ambient_light_sensor: AmbientLightSensor,
+ pub temperature_sensor: TemperatureSensor,
+ pub humidity_sensor: HumiditySensor,
+ pub ninedof_driver: NinedofDriver,
+}
+
+/// Retrieve [Drivers] struct. Returns struct only once.
+pub fn retrieve_drivers() -> TockResult<Drivers> {
+ match unsafe { DRIVERS_SINGLETON.take() } {
+ Some(drivers) => Ok(drivers),
+ None => Err(TockError::Other(OtherError::DriverAlreadyTaken)),
+ }
+}
+
+/// Retrieve [Drivers] struct without check whether it has already been taken
+/// at a different point.
+/// # Safety
+/// This shall only used in special situations where drivers cannot be passed as arguments
+/// as in the panic handler. Otherwise global mutable state (as shared buffers) may be exposed
+/// in an unsafe manner.
+pub unsafe fn retrieve_drivers_unsafe() -> Drivers {
+ DRIVERS
+}
+
+#[allow(clippy::declare_interior_mutable_const)]
+const DRIVERS: Drivers = Drivers {
+ adc_driver: AdcDriver,
+ ble_advertising_driver: BleAdvertisingDriver,
+ ble_scanning_driver: BleScanningDriver,
+ button_driver: ButtonDriver,
+ console_driver: ConsoleDriver,
+ led_driver_factory: LedDriverFactory,
+ timer_context: DriverContext {
+ active_timer: Cell::new(None),
+ },
+ gpio_driver: GpioDriver,
+ temperature_driver: TemperatureDriver,
+ rng_driver: RngDriver,
+ ambient_light_sensor: AmbientLightSensor,
+ temperature_sensor: TemperatureSensor,
+ humidity_sensor: HumiditySensor,
+ ninedof_driver: NinedofDriver,
+};
+
+static mut DRIVERS_SINGLETON: Option<Drivers> = Some(DRIVERS);
+
+#[cfg(test)]
+mod test {
+ use super::DRIVERS;
+ use super::DRIVERS_SINGLETON;
+ use crate::retrieve_drivers;
+ #[test]
+ pub fn can_be_retrieved_once() {
+ reset_drivers_singleton();
+
+ assert!(retrieve_drivers().is_ok());
+ assert!(retrieve_drivers().is_err());
+ }
+
+ fn reset_drivers_singleton() {
+ unsafe {
+ DRIVERS_SINGLETON = Some(DRIVERS);
+ };
+ }
+}
diff --git a/src/electronics/shift_register.rs b/src/electronics/shift_register.rs
index f170225..10eac0d 100644
--- a/src/electronics/shift_register.rs
+++ b/src/electronics/shift_register.rs
@@ -1,18 +1,18 @@
use crate::gpio::GpioPinWrite;
use crate::result::TockResult;
-pub struct ShiftRegister {
- data_pin: GpioPinWrite,
- clock_pin: GpioPinWrite,
- latch_pin: GpioPinWrite,
+pub struct ShiftRegister<'a> {
+ data_pin: GpioPinWrite<'a>,
+ clock_pin: GpioPinWrite<'a>,
+ latch_pin: GpioPinWrite<'a>,
}
-impl ShiftRegister {
+impl<'a> ShiftRegister<'a> {
pub fn new(
- data_pin: GpioPinWrite,
- clock_pin: GpioPinWrite,
- latch_pin: GpioPinWrite,
- ) -> ShiftRegister {
+ data_pin: GpioPinWrite<'a>,
+ clock_pin: GpioPinWrite<'a>,
+ latch_pin: GpioPinWrite<'a>,
+ ) -> ShiftRegister<'a> {
ShiftRegister {
data_pin,
clock_pin,
@@ -20,14 +20,14 @@
}
}
- pub fn write_bits(&self, values: &[bool]) -> TockResult<()> {
+ pub fn write_bits(&mut self, values: &[bool]) -> TockResult<()> {
for i in values {
self.push_bit(*i)?;
}
self.display()
}
- fn push_bit(&self, value: bool) -> TockResult<()> {
+ fn push_bit(&mut self, value: bool) -> TockResult<()> {
if value {
self.data_pin.set_high()
} else {
@@ -37,7 +37,7 @@
self.clock_pin.set_low()
}
- fn display(&self) -> TockResult<()> {
+ fn display(&mut self) -> TockResult<()> {
self.latch_pin.set_high()?;
self.latch_pin.set_low()
}
diff --git a/src/gpio.rs b/src/gpio.rs
index d416632..6f87e44 100644
--- a/src/gpio.rs
+++ b/src/gpio.rs
@@ -1,9 +1,12 @@
+use crate::result::OtherError;
+use crate::result::TockError;
use crate::result::TockResult;
use crate::syscalls;
+use core::marker::PhantomData;
const DRIVER_NUMBER: usize = 0x00004;
-mod gpio_commands {
- pub const SUBSCRIBE_CALLBACK: usize = 0;
+mod command_nr {
+ pub const NUMBER_PINS: usize = 0;
pub const ENABLE_OUTPUT: usize = 1;
pub const SET_HIGH: usize = 2;
pub const SET_LOW: usize = 3;
@@ -15,6 +18,64 @@
pub const DISABLE: usize = 9;
}
+mod subscribe_nr {
+ pub const SUBSCRIBE_CALLBACK: usize = 0;
+}
+
+#[non_exhaustive]
+pub struct GpioDriver;
+
+impl GpioDriver {
+ pub fn all_pins<'a>(&'a self) -> TockResult<GpioIter<'a>> {
+ let number = self.number_of_pins()?;
+ Ok(GpioIter {
+ curr_gpio: 0,
+ gpio_count: number,
+ phantom: PhantomData,
+ })
+ }
+
+ pub fn pin<'a>(&'a self, pin: usize) -> TockResult<GpioPinUnitialized<'a>> {
+ let number = self.number_of_pins()?;
+ if pin < number {
+ Ok(GpioPinUnitialized {
+ number: pin,
+ phantom: PhantomData,
+ })
+ } else {
+ Err(TockError::Other(OtherError::NotEnoughGpioPins))
+ }
+ }
+
+ fn number_of_pins(&self) -> TockResult<usize> {
+ syscalls::command(DRIVER_NUMBER, command_nr::NUMBER_PINS, 0, 0).map_err(Into::into)
+ }
+}
+
+#[derive(Copy, Clone)]
+pub struct GpioIter<'a> {
+ curr_gpio: usize,
+ gpio_count: usize,
+ phantom: PhantomData<&'a mut ()>,
+}
+
+impl<'a> Iterator for GpioIter<'a> {
+ type Item = GpioPinUnitialized<'a>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.curr_gpio < self.gpio_count {
+ let item = GpioPinUnitialized {
+ number: self.curr_gpio,
+ phantom: PhantomData,
+ };
+ self.curr_gpio += 1;
+ Some(item)
+ } else {
+ None
+ }
+ }
+}
+
pub enum InputMode {
PullUp,
PullDown,
@@ -47,27 +108,27 @@
}
}
-pub struct GpioPinUnitialized {
+pub struct GpioPinUnitialized<'a> {
number: usize,
+ phantom: PhantomData<&'a mut ()>,
}
-pub struct GpioPinWrite {
+pub struct GpioPinWrite<'a> {
number: usize,
+ phantom: PhantomData<&'a mut ()>,
}
-pub struct GpioPinRead {
+pub struct GpioPinRead<'a> {
number: usize,
+ phantom: PhantomData<&'a mut ()>,
}
-impl GpioPinUnitialized {
- pub fn new(number: usize) -> GpioPinUnitialized {
- GpioPinUnitialized { number }
- }
-
- pub fn open_for_write(self) -> TockResult<GpioPinWrite> {
- syscalls::command(DRIVER_NUMBER, gpio_commands::ENABLE_OUTPUT, self.number, 0)?;
+impl<'a> GpioPinUnitialized<'a> {
+ pub fn open_for_write(self) -> TockResult<GpioPinWrite<'a>> {
+ syscalls::command(DRIVER_NUMBER, command_nr::ENABLE_OUTPUT, self.number, 0)?;
Ok(GpioPinWrite {
number: self.number,
+ phantom: PhantomData,
})
}
@@ -75,85 +136,81 @@
self,
callback: Option<(extern "C" fn(usize, usize, usize, usize), IrqMode)>,
input_mode: InputMode,
- ) -> TockResult<GpioPinRead> {
+ ) -> TockResult<GpioPinRead<'a>> {
let (callback, irq_mode) = callback.unwrap_or((noop_callback, IrqMode::EitherEdge));
self.enable_input(input_mode)
.and_then(|pin| pin.subscribe_callback(callback))
- .and_then(|pin| pin.enable_callback(irq_mode))
+ .and_then(move |pin| pin.enable_callback(irq_mode))
}
fn subscribe_callback(
self,
callback: extern "C" fn(usize, usize, usize, usize),
- ) -> TockResult<GpioPinUnitialized> {
+ ) -> TockResult<GpioPinUnitialized<'a>> {
syscalls::subscribe_fn(
DRIVER_NUMBER,
- gpio_commands::SUBSCRIBE_CALLBACK,
+ subscribe_nr::SUBSCRIBE_CALLBACK,
callback,
self.number,
)?;
Ok(self)
}
- fn enable_input(self, mode: InputMode) -> TockResult<GpioPinUnitialized> {
+ fn enable_input(self, mode: InputMode) -> TockResult<GpioPinUnitialized<'a>> {
syscalls::command(
DRIVER_NUMBER,
- gpio_commands::ENABLE_INPUT,
+ command_nr::ENABLE_INPUT,
self.number,
mode.to_num(),
)?;
Ok(self)
}
- fn enable_callback(self, irq_mode: IrqMode) -> TockResult<GpioPinRead> {
+ fn enable_callback(self, irq_mode: IrqMode) -> TockResult<GpioPinRead<'a>> {
syscalls::command(
DRIVER_NUMBER,
- gpio_commands::ENABLE_INTERRUPT,
+ command_nr::ENABLE_INTERRUPT,
self.number,
irq_mode.to_num(),
)?;
Ok(GpioPinRead {
number: self.number,
+ phantom: PhantomData,
})
}
}
-impl GpioPinWrite {
+impl<'a> GpioPinWrite<'a> {
pub fn set_low(&self) -> TockResult<()> {
- syscalls::command(DRIVER_NUMBER, gpio_commands::SET_LOW, self.number, 0)?;
+ syscalls::command(DRIVER_NUMBER, command_nr::SET_LOW, self.number, 0)?;
Ok(())
}
pub fn set_high(&self) -> TockResult<()> {
- syscalls::command(DRIVER_NUMBER, gpio_commands::SET_HIGH, self.number, 0)?;
+ syscalls::command(DRIVER_NUMBER, command_nr::SET_HIGH, self.number, 0)?;
Ok(())
}
pub fn toggle(&self) -> TockResult<()> {
- syscalls::command(DRIVER_NUMBER, gpio_commands::TOGGLE, self.number, 0)?;
+ syscalls::command(DRIVER_NUMBER, command_nr::TOGGLE, self.number, 0)?;
Ok(())
}
}
-impl GpioPinRead {
- pub fn read(&self) -> bool {
- syscalls::command(DRIVER_NUMBER, gpio_commands::READ, self.number, 0).ok() == Some(1)
+impl<'a> GpioPinRead<'a> {
+ pub fn read(&'a self) -> bool {
+ syscalls::command(DRIVER_NUMBER, command_nr::READ, self.number, 0).ok() == Some(1)
}
}
-impl Drop for GpioPinWrite {
+impl<'a> Drop for GpioPinWrite<'a> {
fn drop(&mut self) {
- let _ = syscalls::command(DRIVER_NUMBER, gpio_commands::DISABLE, self.number, 0);
+ let _ = syscalls::command(DRIVER_NUMBER, command_nr::DISABLE, self.number, 0);
}
}
-impl Drop for GpioPinRead {
+impl<'a> Drop for GpioPinRead<'a> {
fn drop(&mut self) {
- let _ = syscalls::command(
- DRIVER_NUMBER,
- gpio_commands::DISABLE_INTERRUPT,
- self.number,
- 0,
- );
- let _ = syscalls::command(DRIVER_NUMBER, gpio_commands::DISABLE, self.number, 0);
+ let _ = syscalls::command(DRIVER_NUMBER, command_nr::DISABLE_INTERRUPT, self.number, 0);
+ let _ = syscalls::command(DRIVER_NUMBER, command_nr::DISABLE, self.number, 0);
}
}
diff --git a/src/lang_items.rs b/src/lang_items.rs
index 197de47..6ff7529 100644
--- a/src/lang_items.rs
+++ b/src/lang_items.rs
@@ -18,9 +18,10 @@
//! `rustc_main`. That's covered by the `_start` function in the root of this
//! crate.
-use crate::led;
-use crate::timer;
+use crate::led::LedDriver;
use crate::timer::Duration;
+use crate::timer::ParallelSleepDriver;
+use crate::Drivers;
use core::alloc::Layout;
use core::executor;
use core::panic::PanicInfo;
@@ -47,49 +48,63 @@
// 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());
- loop {
- for led in led::all() {
- let _ = led.on();
- }
- if let Some(ref timer_driver) = timer_driver {
- let _ = timer_driver.sleep(Duration::from_ms(100)).await;
- }
- for led in led::all() {
- let _ = led.off();
- }
- if let Some(ref timer_driver) = timer_driver {
- let _ = timer_driver.sleep(Duration::from_ms(100)).await;
- }
+ let Drivers {
+ led_driver_factory,
+ timer_context,
+ ..
+ } = crate::retrieve_drivers_unsafe();
+ let mut driver = timer_context.create_timer_driver();
+ let timer_driver = driver.activate().ok();
+ let led_driver = led_driver_factory.create_driver().ok();
+ if let (Some(ref led_driver), Some(ref timer_driver)) = (led_driver, timer_driver) {
+ blink_all_leds(timer_driver, led_driver).await;
}
+ loop {}
});
// Never type is not supported for T in Future
unreachable!()
}
-#[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());
- loop {
- for led in led::all() {
- let _ = led.on();
- }
- if let Some(ref timer_driver) = timer_driver {
- let _ = timer_driver.sleep(Duration::from_ms(100)).await;
- }
- for led in led::all() {
- let _ = led.off();
- }
- if let Some(ref timer_driver) = timer_driver {
- let _ = timer_driver.sleep(Duration::from_ms(100)).await;
- }
+async fn blink_all_leds(timer_driver: &ParallelSleepDriver<'_>, led_driver: &LedDriver) {
+ loop {
+ for led in led_driver.all() {
+ let _ = led.on();
}
+ let _ = timer_driver.sleep(Duration::from_ms(100)).await;
+ for led in led_driver.all() {
+ let _ = led.off();
+ }
+ let _ = timer_driver.sleep(Duration::from_ms(100)).await;
+ }
+}
+
+#[alloc_error_handler]
+unsafe fn alloc_error_handler(_: Layout) -> ! {
+ executor::block_on(async {
+ let Drivers {
+ led_driver_factory,
+ timer_context,
+ ..
+ } = crate::retrieve_drivers_unsafe();
+ let mut driver = timer_context.create_timer_driver();
+ let timer_driver = driver.activate().ok();
+ let led_driver = led_driver_factory.create_driver().ok();
+
+ if let (Some(led_driver), Some(timer_driver)) = (led_driver, timer_driver) {
+ cycle_all_leds(&timer_driver, &led_driver).await;
+ }
+ loop {}
});
// Never type is not supported for T in Future
unreachable!()
}
+
+async fn cycle_all_leds(timer_driver: &ParallelSleepDriver<'_>, led_driver: &LedDriver) {
+ loop {
+ for led in led_driver.all() {
+ let _ = led.on();
+ let _ = timer_driver.sleep(Duration::from_ms(100)).await;
+ let _ = led.off();
+ }
+ }
+}
diff --git a/src/led.rs b/src/led.rs
index d7aac8f..6e69944 100644
--- a/src/led.rs
+++ b/src/led.rs
@@ -1,5 +1,6 @@
use crate::result::TockResult;
use crate::syscalls::command;
+use core::marker::PhantomData;
const DRIVER_NUMBER: usize = 0x00002;
@@ -10,32 +11,53 @@
pub const TOGGLE: usize = 3;
}
-pub struct Led {
+#[non_exhaustive]
+pub struct LedDriverFactory;
+
+impl LedDriverFactory {
+ pub fn create_driver(self) -> TockResult<LedDriver> {
+ command(DRIVER_NUMBER, command_nr::COUNT, 0, 0)?;
+ Ok(LedDriver)
+ }
+}
+
+#[non_exhaustive]
+pub struct LedDriver;
+
+pub struct Led<'a> {
led_num: usize,
+ phantom: PhantomData<&'a mut ()>,
}
-pub fn count() -> TockResult<usize> {
- command(DRIVER_NUMBER, command_nr::COUNT, 0, 0).map_err(Into::into)
-}
+impl LedDriver {
+ pub fn get(&self, led_num: usize) -> Option<Led> {
+ if led_num < self.count().ok().unwrap() {
+ Some(Led {
+ led_num,
+ phantom: PhantomData,
+ })
+ } else {
+ None
+ }
+ }
-pub fn get(led_num: usize) -> Option<Led> {
- if led_num < count().ok().unwrap() {
- Some(Led { led_num })
- } else {
- None
+ pub fn count(&self) -> TockResult<usize> {
+ command(DRIVER_NUMBER, command_nr::COUNT, 0, 0).map_err(Into::into)
+ }
+
+ pub fn all(&self) -> LedIter {
+ LedIter {
+ curr_led: 0,
+ led_count: self.count().unwrap_or(0),
+ phantom: PhantomData,
+ }
}
}
/// Returns an iterator over all available LEDs. If the LED driver is not
/// present, the iterator will be empty.
-pub fn all() -> LedIter {
- LedIter {
- curr_led: 0,
- led_count: count().unwrap_or(0),
- }
-}
-impl Led {
+impl<'a> Led<'a> {
pub fn set_state(&self, state: bool) -> TockResult<()> {
if state {
self.on()
@@ -58,21 +80,27 @@
command(DRIVER_NUMBER, command_nr::TOGGLE, self.led_num, 0)?;
Ok(())
}
+
+ pub fn number(&self) -> usize {
+ self.led_num
+ }
}
#[derive(Copy, Clone)]
-pub struct LedIter {
+pub struct LedIter<'a> {
curr_led: usize,
led_count: usize,
+ phantom: PhantomData<&'a mut ()>,
}
-impl Iterator for LedIter {
- type Item = Led;
+impl<'a> Iterator for LedIter<'a> {
+ type Item = Led<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.curr_led < self.led_count {
let item = Led {
led_num: self.curr_led,
+ phantom: PhantomData,
};
self.curr_led += 1;
Some(item)
diff --git a/src/lib.rs b/src/lib.rs
index 8873c33..1c1ecf0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -33,6 +33,9 @@
pub use libtock_codegen::main;
-// Dummy structure to force importing the panic_handler and other no_std elements when nothing else
-// is imported.
+pub(crate) mod drivers;
+pub use drivers::*;
+
+/// Dummy structure to force importing the panic_handler and other no_std elements when nothing else
+/// is imported.
pub struct LibTock;
diff --git a/src/result.rs b/src/result.rs
index 4eaec21..f3929ca 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -70,6 +70,7 @@
TimerDriverDurationOutOfRange,
TimerDriverErroneousClockFrequency,
DriverAlreadyTaken,
+ NotEnoughGpioPins,
}
impl From<OtherError> for TockError {
diff --git a/src/rng.rs b/src/rng.rs
index 2134fb2..e04500f 100644
--- a/src/rng.rs
+++ b/src/rng.rs
@@ -18,25 +18,24 @@
pub const SHARE_BUFFER: usize = 0;
}
-pub async fn fill_buffer(buf: &mut [u8]) -> TockResult<()> {
- let buf_len = buf.len();
+#[non_exhaustive]
+pub struct RngDriver;
- let shared_memory = syscalls::allow(DRIVER_NUMBER, allow_nr::SHARE_BUFFER, buf)?;
-
- let is_filled = Cell::new(false);
- let mut is_filled_alarm = |_, _, _| is_filled.set(true);
- let subscription = syscalls::subscribe(
- DRIVER_NUMBER,
- subscribe_nr::BUFFER_FILLED,
- &mut is_filled_alarm,
- )?;
-
- syscalls::command(DRIVER_NUMBER, command_nr::REQUEST_RNG, buf_len, 0)?;
-
- futures::wait_until(|| is_filled.get()).await;
-
- mem::drop(subscription);
- mem::drop(shared_memory);
-
- Ok(())
+impl RngDriver {
+ pub async fn fill_buffer(&mut self, buf: &mut [u8]) -> TockResult<()> {
+ let buf_len = buf.len();
+ let shared_memory = syscalls::allow(DRIVER_NUMBER, allow_nr::SHARE_BUFFER, buf)?;
+ let is_filled = Cell::new(false);
+ let mut is_filled_alarm = |_, _, _| is_filled.set(true);
+ let subscription = syscalls::subscribe(
+ DRIVER_NUMBER,
+ subscribe_nr::BUFFER_FILLED,
+ &mut is_filled_alarm,
+ )?;
+ syscalls::command(DRIVER_NUMBER, command_nr::REQUEST_RNG, buf_len, 0)?;
+ futures::wait_until(|| is_filled.get()).await;
+ mem::drop(subscription);
+ mem::drop(shared_memory);
+ Ok(())
+ }
}
diff --git a/src/sensors/mod.rs b/src/sensors/mod.rs
index af7e00f..c4b962f 100644
--- a/src/sensors/mod.rs
+++ b/src/sensors/mod.rs
@@ -7,9 +7,7 @@
use core::fmt;
use core::mem;
-mod ninedof;
-
-pub use self::ninedof::*;
+pub mod ninedof;
extern "C" fn cb<Reading>(x: usize, y: usize, z: usize, ptr: usize)
where
@@ -36,20 +34,25 @@
macro_rules! single_value_sensor {
($sensor_name:ident, $type_name:ident, $driver_num:expr) => {
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
- pub struct $type_name(i32);
+ pub struct $type_name {
+ value: i32,
+ }
impl From<(usize, usize, usize)> for $type_name {
fn from(tuple: (usize, usize, usize)) -> $type_name {
- $type_name(tuple.0 as i32)
+ $type_name {
+ value: (tuple.0 as i32),
+ }
}
}
impl Into<i32> for $type_name {
fn into(self) -> i32 {
- self.0
+ self.value
}
}
+ #[non_exhaustive]
pub struct $sensor_name;
impl Sensor<$type_name> for $sensor_name {
@@ -66,18 +69,18 @@
impl fmt::Display for AmbientLight {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(f, "{} lx", self.0)
+ write!(f, "{} lx", self.value)
}
}
impl fmt::Display for Humidity {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(f, "{}.{}%", self.0 / 100, self.0 % 100)
+ write!(f, "{}.{}%", self.value / 100, self.value % 100)
}
}
impl fmt::Display for Temperature {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(f, "{}.{}\u{00B0}C", self.0 / 100, self.0 % 100)
+ write!(f, "{}.{}\u{00B0}C", self.value / 100, self.value % 100)
}
}
diff --git a/src/sensors/ninedof.rs b/src/sensors/ninedof.rs
index 7986a40..e468690 100644
--- a/src/sensors/ninedof.rs
+++ b/src/sensors/ninedof.rs
@@ -8,7 +8,8 @@
const DRIVER_NUM: usize = 0x60004;
-pub struct Ninedof;
+#[non_exhaustive]
+pub struct NinedofDriver;
#[derive(Copy, Clone, Default, Debug)]
pub struct NinedofReading {
@@ -29,7 +30,7 @@
ready: Cell<bool>,
}
-impl Ninedof {
+impl NinedofDriver {
pub fn read_acceleration(&mut self) -> TockResult<NinedofReading> {
let res: CbData = Default::default();
subscribe(Self::cb, unsafe { mem::transmute(&res) })?;
@@ -57,12 +58,6 @@
}
}
-impl Default for Ninedof {
- fn default() -> Self {
- Ninedof
- }
-}
-
pub fn subscribe(cb: extern "C" fn(usize, usize, usize, usize), ud: usize) -> TockResult<()> {
syscalls::subscribe_fn(DRIVER_NUM, 0, cb, ud)?;
Ok(())
diff --git a/src/simple_ble.rs b/src/simple_ble.rs
index 113de2d..f700385 100644
--- a/src/simple_ble.rs
+++ b/src/simple_ble.rs
@@ -10,14 +10,20 @@
pub const BUFFER_SIZE_ADVERTISE: usize = 39;
pub const BUFFER_SIZE_SCAN: usize = 39;
-mod ble_commands {
+mod command_nr {
pub const START_ADVERTISING: usize = 0;
- pub const ALLOW_ADVERTISMENT_BUFFER: usize = 0;
- pub const BLE_PASSIVE_SCAN_SUB: usize = 0;
- pub const ALLOW_SCAN_BUFFER: usize = 1;
pub const PASSIVE_SCAN: usize = 5;
}
+mod subscribe_nr {
+ pub const BLE_PASSIVE_SCAN_SUB: usize = 0;
+}
+
+mod allow_nr {
+ pub const ALLOW_ADVERTISMENT_BUFFER: usize = 0;
+ pub const ALLOW_SCAN_BUFFER: usize = 1;
+}
+
mod gap_flags {
pub const BLE_DISCOVERABLE: usize = 0x02;
}
@@ -29,6 +35,7 @@
pub const SERVICE_DATA: usize = 0x16;
}
+#[non_exhaustive]
pub struct BleAdvertisingDriver;
impl BleAdvertisingDriver {
@@ -36,13 +43,14 @@
[0; BUFFER_SIZE_ADVERTISE]
}
pub fn initialize<'a>(
+ &'a mut self,
interval: usize,
service_payload: &BlePayload,
advertising_buffer: &'a mut [u8; BUFFER_SIZE_ADVERTISE],
) -> TockResult<SharedMemory<'a>> {
let mut shared_memory = syscalls::allow(
DRIVER_NUMBER,
- ble_commands::ALLOW_ADVERTISMENT_BUFFER,
+ allow_nr::ALLOW_ADVERTISMENT_BUFFER,
advertising_buffer,
)?;
shared_memory.write_bytes(service_payload);
@@ -53,7 +61,7 @@
fn start_advertising(pdu_type: usize, interval: usize) -> TockResult<()> {
syscalls::command(
DRIVER_NUMBER,
- ble_commands::START_ADVERTISING,
+ command_nr::START_ADVERTISING,
pdu_type,
interval,
)?;
@@ -77,25 +85,31 @@
}
}
-pub struct BleDriver;
+#[non_exhaustive]
+pub struct BleScanningDriver;
-impl BleDriver {
+impl BleScanningDriver {
pub fn create_scan_buffer() -> [u8; BUFFER_SIZE_SCAN] {
[0; BUFFER_SIZE_SCAN]
}
- pub fn share_memory(scan_buffer: &mut [u8; BUFFER_SIZE_SCAN]) -> TockResult<SharedMemory> {
- syscalls::allow(DRIVER_NUMBER, ble_commands::ALLOW_SCAN_BUFFER, scan_buffer)
- .map_err(Into::into)
+ pub fn share_memory<'a, 'b>(
+ &'a mut self,
+ scan_buffer: &'b mut [u8; BUFFER_SIZE_SCAN],
+ ) -> TockResult<SharedMemory<'b>> {
+ syscalls::allow(DRIVER_NUMBER, allow_nr::ALLOW_SCAN_BUFFER, scan_buffer).map_err(Into::into)
}
- pub fn start<CB>(callback: &mut BleCallback<CB>) -> TockResult<CallbackSubscription>
+ pub fn start<'a, CB>(
+ &'a mut self,
+ callback: &'a mut BleCallback<CB>,
+ ) -> TockResult<CallbackSubscription>
where
BleCallback<CB>: SubscribableCallback,
{
let subscription =
- syscalls::subscribe(DRIVER_NUMBER, ble_commands::BLE_PASSIVE_SCAN_SUB, callback)?;
- syscalls::command(DRIVER_NUMBER, ble_commands::PASSIVE_SCAN, 1, 0)?;
+ syscalls::subscribe(DRIVER_NUMBER, subscribe_nr::BLE_PASSIVE_SCAN_SUB, callback)?;
+ syscalls::command(DRIVER_NUMBER, command_nr::PASSIVE_SCAN, 1, 0)?;
Ok(subscription)
}
}
diff --git a/src/temperature.rs b/src/temperature.rs
index 28e366f..4420791 100644
--- a/src/temperature.rs
+++ b/src/temperature.rs
@@ -7,21 +7,35 @@
use core::mem;
const DRIVER_NUMBER: usize = 0x60000;
-const SUBSCRIBE_CALLBACK: usize = 0;
-const START_MEASUREMENT: usize = 1;
-pub async fn measure_temperature() -> Result<Temperature, TockError> {
- let temperature = Cell::<Option<isize>>::new(None);
- let mut callback = |arg1, _, _| temperature.set(Some(arg1 as isize));
- let subscription = syscalls::subscribe(DRIVER_NUMBER, SUBSCRIBE_CALLBACK, &mut callback)?;
- syscalls::command(DRIVER_NUMBER, START_MEASUREMENT, 0, 0)?;
- let temperatur = Temperature {
- centi_celsius: futures::wait_for_value(|| temperature.get()).await,
- };
- mem::drop(subscription);
- Ok(temperatur)
+mod command_nr {
+ pub const START_MEASUREMENT: usize = 1;
}
+mod subscribe_nr {
+ pub const SUBSCRIBE_CALLBACK: usize = 0;
+}
+
+#[non_exhaustive]
+pub struct TemperatureDriver;
+
+impl TemperatureDriver {
+ pub async fn measure_temperature(&mut self) -> Result<Temperature, TockError> {
+ let temperature = Cell::<Option<isize>>::new(None);
+ let mut callback = |arg1, _, _| temperature.set(Some(arg1 as isize));
+ let subscription = syscalls::subscribe(
+ DRIVER_NUMBER,
+ subscribe_nr::SUBSCRIBE_CALLBACK,
+ &mut callback,
+ )?;
+ syscalls::command(DRIVER_NUMBER, command_nr::START_MEASUREMENT, 0, 0)?;
+ let temperatur = Temperature {
+ centi_celsius: futures::wait_for_value(|| temperature.get()).await,
+ };
+ mem::drop(subscription);
+ Ok(temperatur)
+ }
+}
#[derive(Copy, Clone)]
pub struct Temperature {
centi_celsius: isize,
diff --git a/src/timer.rs b/src/timer.rs
index a0172b0..80adc1a 100644
--- a/src/timer.rs
+++ b/src/timer.rs
@@ -10,6 +10,7 @@
use crate::syscalls;
use core::cell::Cell;
use core::isize;
+use core::marker::PhantomData;
use core::ops::{Add, AddAssign, Sub};
const DRIVER_NUMBER: usize = 0x00000;
@@ -26,19 +27,13 @@
pub const SUBSCRIBE_CALLBACK: usize = 0;
}
-pub fn with_callback<CB>(callback: CB) -> WithCallback<CB> {
- WithCallback {
- callback,
- clock_frequency: ClockFrequency { hz: 0 },
- }
-}
-
-pub struct WithCallback<CB> {
+pub struct WithCallback<'a, CB> {
callback: CB,
clock_frequency: ClockFrequency,
+ phantom: PhantomData<&'a mut ()>,
}
-impl<CB: FnMut(ClockValue, Alarm)> SubscribableCallback for WithCallback<CB> {
+impl<CB: FnMut(ClockValue, Alarm)> SubscribableCallback for WithCallback<'_, CB> {
fn call_rust(&mut self, clock_value: usize, alarm_id: usize, _: usize) {
(self.callback)(
ClockValue {
@@ -50,11 +45,11 @@
}
}
-impl<CB> WithCallback<CB>
+impl<'a, CB> WithCallback<'a, CB>
where
Self: SubscribableCallback,
{
- pub fn init(&mut self) -> TockResult<Timer> {
+ pub fn init(&'a mut self) -> TockResult<Timer<'a>> {
let num_notifications =
syscalls::command(DRIVER_NUMBER, command_nr::IS_DRIVER_AVAILABLE, 0, 0)?;
@@ -282,10 +277,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,55 +288,32 @@
/// ```no_run
/// # use libtock::timer::DriverContext;
/// # use libtock::result::TockResult;
+/// # use libtock::Drivers;
/// # #[libtock::main]
/// # async fn main() -> TockResult<()> {
-/// let context = DriverContext::create();
+/// let Drivers { timer_context, .. } = libtock::retrieve_drivers()?;
/// # Ok(())
/// # }
/// ```
+#[non_exhaustive]
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 driver timer from a context.
+ pub fn create_timer_driver(&self) -> TimerDriver<'_> {
+ TimerDriver {
+ callback: Callback,
+ context: &self,
}
}
- /// 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<'_> {
- TimerDriver {
- callback: Callback {
- now: &self.current_time,
- },
- context: &self,
+ pub fn with_callback<CB>(&mut self, callback: CB) -> WithCallback<CB> {
+ WithCallback {
+ callback,
+ clock_frequency: ClockFrequency { hz: 0 },
+ phantom: PhantomData,
}
}
}
@@ -352,26 +322,24 @@
/// ```no_run
/// # use libtock::timer::DriverContext;
/// # use libtock::result::TockResult;
+/// # use libtock::Drivers;
/// # #[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 Drivers { timer_context,.. } = libtock::retrieve_drivers()?;
+/// # 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 +349,11 @@
/// # use libtock::timer::DriverContext;
/// # use libtock::result::TockResult;
/// # use libtock::timer::Duration;
+/// # use libtock::Drivers;
/// # #[libtock::main]
/// # async fn main() -> TockResult<()> {
-/// let context = DriverContext::create()?;
-/// let mut driver = context.create_timer_driver().unwrap();
+/// # let Drivers { timer_context,.. } = libtock::retrieve_drivers()?;
+/// # let mut driver = timer_context.create_timer_driver();
/// let timer_driver = driver.activate()?;
/// timer_driver.sleep(Duration::from_ms(1000)).await?;
/// # Ok(())
@@ -416,7 +385,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 {