diff --git a/Cargo.toml b/Cargo.toml index aefbca93..07812f01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,8 @@ libtock_console = { path = "apis/console" } libtock_debug_panic = { path = "panic_handlers/debug_panic" } libtock_gpio = { path = "apis/gpio" } libtock_leds = { path = "apis/leds" } +libtock_proximity = { path = "apis/proximity" } +libtock_sound_pressure = { path = "apis/sound_pressure" } libtock_low_level_debug = { path = "apis/low_level_debug" } libtock_platform = { path = "platform" } libtock_runtime = { path = "runtime" } @@ -50,4 +52,6 @@ members = [ "tools/print_sizes", "ufmt", "unittest", + "apis/sound_pressure", + "apis/proximity" ] diff --git a/Makefile b/Makefile index 08425a7e..b8b099ec 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ release=--release endif .PHONY: setup -setup: setup-qemu +setup: #setup-qemu cargo install elf2tab cargo miri setup rustup target add --toolchain stable thumbv7em-none-eabi diff --git a/apis/proximity/Cargo.toml b/apis/proximity/Cargo.toml new file mode 100644 index 00000000..989c4722 --- /dev/null +++ b/apis/proximity/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "libtock_proximity" +version = "0.1.0" +authors = [ + "Tock Project Developers ", + "dcz ", +] +license = "MIT/Apache-2.0" +edition = "2018" +repository = "https://www.github.com/tock/libtock-rs" +description = "libtock alarm driver" + +[dependencies] +libtock_platform = { path = "../../platform" } + +[dev-dependencies] +libtock_unittest = { path = "../../unittest" } diff --git a/apis/proximity/src/lib.rs b/apis/proximity/src/lib.rs new file mode 100644 index 00000000..c9ab4c8b --- /dev/null +++ b/apis/proximity/src/lib.rs @@ -0,0 +1,58 @@ +#![no_std] + +use core::cell::Cell; +use libtock_platform::{ + share, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall, +}; + +pub struct Proximity(S); + +impl Proximity { + /// Returns Ok() if the driver was present.This does not necessarily mean + /// that the driver is working. + pub fn exists() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, EXISTS, 0, 0).to_result() + } + + pub fn read_proximity() -> Result { + S::command(DRIVER_NUM, 1, 0, 0).to_result() + } + + pub fn read_proximity_on_interrupt() -> Result { + S::command(DRIVER_NUM, 2, 0, 0).to_result() + } + + /// Register an events listener + pub fn register_listener<'share, F: Fn(i32)>( + listener: &'share ProximityListener, + subscribe: share::Handle>, + ) -> Result<(), ErrorCode> { + S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener) + } + + /// Unregister the events listener + pub fn unregister_listener() { + S::unsubscribe(DRIVER_NUM, 0) + } +} + +pub struct ProximityListener(pub F); +impl Upcall> for ProximityListener { + fn upcall(&self, prox_val: u32, _arg1: u32, _arg2: u32) { + self.0(prox_val as i32) + } +} + +#[cfg(test)] +mod tests; + +// ----------------------------------------------------------------------------- +// Driver number and command IDs +// ----------------------------------------------------------------------------- + +const DRIVER_NUM: u32 = 0x60005; + +// Command IDs + +const EXISTS: u32 = 0; +const READ_TEMP: u32 = 1; \ No newline at end of file diff --git a/apis/proximity/src/tests.rs b/apis/proximity/src/tests.rs new file mode 100644 index 00000000..e3497fe7 --- /dev/null +++ b/apis/proximity/src/tests.rs @@ -0,0 +1,81 @@ +use core::cell::Cell; +use libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn}; +use libtock_unittest::fake; + +type Temperature = super::Temperature; + +#[test] +fn no_driver() { + let _kernel = fake::Kernel::new(); + assert_eq!(Temperature::exists(), Err(ErrorCode::NoDevice)); +} + +#[test] +fn driver_check() { + let kernel = fake::Kernel::new(); + let driver = fake::Temperature::new(); + kernel.add_driver(&driver); + + assert_eq!(Temperature::exists(), Ok(())); +} + +#[test] +fn read_temperature() { + let kernel = fake::Kernel::new(); + let driver = fake::Temperature::new(); + kernel.add_driver(&driver); + + assert_eq!(Temperature::read_temperature(), Ok(())); + assert!(driver.is_busy()); + + assert_eq!(Temperature::read_temperature(), Err(ErrorCode::Busy)); + assert_eq!(Temperature::read_temperature_sync(), Err(ErrorCode::Busy)); +} + +#[test] +fn register_unregister_listener() { + let kernel = fake::Kernel::new(); + let driver = fake::Temperature::new(); + kernel.add_driver(&driver); + + let temperature_cell: Cell> = Cell::new(None); + let listener = crate::TemperatureListener(|temp_val| { + temperature_cell.set(Some(temp_val)); + }); + share::scope(|subscribe| { + assert_eq!(Temperature::read_temperature(), Ok(())); + driver.set_value(100); + assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall); + + assert_eq!(Temperature::register_listener(&listener, subscribe), Ok(())); + assert_eq!(Temperature::read_temperature(), Ok(())); + driver.set_value(100); + assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall); + assert_eq!(temperature_cell.get(), Some(100)); + + Temperature::unregister_listener(); + assert_eq!(Temperature::read_temperature(), Ok(())); + driver.set_value(100); + assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall); + }); +} + +#[test] +fn read_temperature_sync() { + let kernel = fake::Kernel::new(); + let driver = fake::Temperature::new(); + kernel.add_driver(&driver); + + driver.set_value_sync(1000); + assert_eq!(Temperature::read_temperature_sync(), Ok(1000)); +} + +#[test] +fn negative_value() { + let kernel = fake::Kernel::new(); + let driver = fake::Temperature::new(); + kernel.add_driver(&driver); + + driver.set_value_sync(-1000); + assert_eq!(Temperature::read_temperature_sync(), Ok(-1000)); +} \ No newline at end of file diff --git a/apis/sound_pressure/Cargo.toml b/apis/sound_pressure/Cargo.toml new file mode 100644 index 00000000..ff0b7242 --- /dev/null +++ b/apis/sound_pressure/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "libtock_sound_pressure" +version = "0.1.0" +authors = [ + "Tock Project Developers ", + "dcz ", +] +license = "MIT/Apache-2.0" +edition = "2018" +repository = "https://www.github.com/tock/libtock-rs" +description = "libtock alarm driver" + +[dependencies] +libtock_platform = { path = "../../platform" } + +[dev-dependencies] +libtock_unittest = { path = "../../unittest" } diff --git a/apis/sound_pressure/src/lib.rs b/apis/sound_pressure/src/lib.rs new file mode 100644 index 00000000..d81abc93 --- /dev/null +++ b/apis/sound_pressure/src/lib.rs @@ -0,0 +1,81 @@ +#![no_std] + +use core::cell::Cell; +use libtock_platform::{ + share, subscribe::OneId, DefaultConfig, ErrorCode, Subscribe, Syscalls, Upcall, +}; + +pub struct SoundPressure(S); + +impl SoundPressure { + /// Returns Ok() if the driver was present.This does not necessarily mean + /// that the driver is working. + pub fn exists() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, EXISTS, 0, 0).to_result() + } + + /// Initiate a SoundPressure measurement. + /// + /// This function is used both for synchronous and asynchronous readings + pub fn read_sound_pressure() -> Result<(), ErrorCode> { + S::command(DRIVER_NUM, READ_TEMP, 0, 0).to_result() + } + + /// Register an events listener + pub fn register_listener<'share, F: Fn(i32)>( + listener: &'share SoundPressureListener, + subscribe: share::Handle>, + ) -> Result<(), ErrorCode> { + S::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, listener) + } + + /// Unregister the events listener + pub fn unregister_listener() { + S::unsubscribe(DRIVER_NUM, 0) + } + + /// Initiate a synchronous SoundPressure measurement. + /// Returns Ok(SoundPressure_value) if the operation was successful + /// SoundPressure_value is returned in hundreds of centigrades + pub fn read_sound_pressure_sync() -> Result { + let SoundPressure_cell: Cell> = Cell::new(None); + let listener = SoundPressureListener(|temp_val| { + SoundPressure_cell.set(Some(temp_val)); + }); + share::scope(|subscribe| { + if let Ok(()) = Self::register_listener(&listener, subscribe) { + if let Ok(()) = Self::read_sound_pressure() { + while SoundPressure_cell.get() == None { + S::yield_wait(); + } + } + } + }); + + match SoundPressure_cell.get() { + None => Err(ErrorCode::Busy), + Some(temp_val) => Ok(temp_val), + } + } +} + +pub struct SoundPressureListener(pub F); +impl Upcall> for SoundPressureListener { + fn upcall(&self, temp_val: u32, _arg1: u32, _arg2: u32) { + self.0(temp_val as i32) + } +} + +#[cfg(test)] +mod tests; + +// ----------------------------------------------------------------------------- +// Driver number and command IDs +// ----------------------------------------------------------------------------- + +const DRIVER_NUM: u32 = 0x60006; + +// Command IDs + +const EXISTS: u32 = 0; +const READ_TEMP: u32 = 1; diff --git a/apis/sound_pressure/src/tests.rs b/apis/sound_pressure/src/tests.rs new file mode 100644 index 00000000..e3497fe7 --- /dev/null +++ b/apis/sound_pressure/src/tests.rs @@ -0,0 +1,81 @@ +use core::cell::Cell; +use libtock_platform::{share, ErrorCode, Syscalls, YieldNoWaitReturn}; +use libtock_unittest::fake; + +type Temperature = super::Temperature; + +#[test] +fn no_driver() { + let _kernel = fake::Kernel::new(); + assert_eq!(Temperature::exists(), Err(ErrorCode::NoDevice)); +} + +#[test] +fn driver_check() { + let kernel = fake::Kernel::new(); + let driver = fake::Temperature::new(); + kernel.add_driver(&driver); + + assert_eq!(Temperature::exists(), Ok(())); +} + +#[test] +fn read_temperature() { + let kernel = fake::Kernel::new(); + let driver = fake::Temperature::new(); + kernel.add_driver(&driver); + + assert_eq!(Temperature::read_temperature(), Ok(())); + assert!(driver.is_busy()); + + assert_eq!(Temperature::read_temperature(), Err(ErrorCode::Busy)); + assert_eq!(Temperature::read_temperature_sync(), Err(ErrorCode::Busy)); +} + +#[test] +fn register_unregister_listener() { + let kernel = fake::Kernel::new(); + let driver = fake::Temperature::new(); + kernel.add_driver(&driver); + + let temperature_cell: Cell> = Cell::new(None); + let listener = crate::TemperatureListener(|temp_val| { + temperature_cell.set(Some(temp_val)); + }); + share::scope(|subscribe| { + assert_eq!(Temperature::read_temperature(), Ok(())); + driver.set_value(100); + assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall); + + assert_eq!(Temperature::register_listener(&listener, subscribe), Ok(())); + assert_eq!(Temperature::read_temperature(), Ok(())); + driver.set_value(100); + assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall); + assert_eq!(temperature_cell.get(), Some(100)); + + Temperature::unregister_listener(); + assert_eq!(Temperature::read_temperature(), Ok(())); + driver.set_value(100); + assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall); + }); +} + +#[test] +fn read_temperature_sync() { + let kernel = fake::Kernel::new(); + let driver = fake::Temperature::new(); + kernel.add_driver(&driver); + + driver.set_value_sync(1000); + assert_eq!(Temperature::read_temperature_sync(), Ok(1000)); +} + +#[test] +fn negative_value() { + let kernel = fake::Kernel::new(); + let driver = fake::Temperature::new(); + kernel.add_driver(&driver); + + driver.set_value_sync(-1000); + assert_eq!(Temperature::read_temperature_sync(), Ok(-1000)); +} \ No newline at end of file diff --git a/examples/proximity.rs b/examples/proximity.rs new file mode 100644 index 00000000..137b5f8c --- /dev/null +++ b/examples/proximity.rs @@ -0,0 +1,38 @@ + +#![no_main] +#![no_std] + +use core::fmt::Write; +use libtock::console::Console; + +use libtock::alarm::{Alarm, Milliseconds}; +use libtock::runtime::{set_main, stack_size}; +use libtock::proximity::Proximity; + +set_main! {main} +stack_size! {0x200} + +fn main() { + match Proximity::exists() { + Ok(()) => writeln!(Console::writer(), "proxi driver available").unwrap(), + Err(_) => { + writeln!(Console::writer(), "proxi driver unavailable").unwrap(); + return; + } + } + + loop { + match Proximity::read_proximity() { + Ok(temp_val) => writeln!( + Console::writer(), + "Proxi: {}\n", + (temp_val), + ) + .unwrap(), + Err(_) => writeln!(Console::writer(), "error while reading proxi",).unwrap(), + + } + + Alarm::sleep_for(Milliseconds(2000)).unwrap(); + } +} \ No newline at end of file diff --git a/examples/soundpressure.rs b/examples/soundpressure.rs new file mode 100644 index 00000000..858b65d0 --- /dev/null +++ b/examples/soundpressure.rs @@ -0,0 +1,38 @@ + +#![no_main] +#![no_std] + +use core::fmt::Write; +use libtock::console::Console; + +use libtock::alarm::{Alarm, Milliseconds}; +use libtock::runtime::{set_main, stack_size}; +use libtock::sound_pressure::SoundPressure; + +set_main! {main} +stack_size! {0x200} + +fn main() { + match SoundPressure::exists() { + Ok(()) => writeln!(Console::writer(), "proxi driver available").unwrap(), + Err(_) => { + writeln!(Console::writer(), "proxi driver unavailable").unwrap(); + return; + } + } + + loop { + match SoundPressure::read_sound_pressure_sync() { + Ok(temp_val) => writeln!( + Console::writer(), + "Pressure: {}\n", + temp_val + ) + .unwrap(), + Err(a) => writeln!(Console::writer(), "error while reading proxi {:?}", a).unwrap(), + + } + + Alarm::sleep_for(Milliseconds(2000)).unwrap(); + } +} \ No newline at end of file diff --git a/runner/src/tockloader.rs b/runner/src/tockloader.rs index bc4fe829..c274bdfb 100644 --- a/runner/src/tockloader.rs +++ b/runner/src/tockloader.rs @@ -11,7 +11,7 @@ pub fn deploy(cli: &Cli, platform: String, tab_path: PathBuf) -> Child { let flags: &[_] = match platform.as_str() { "clue_nrf52840" => &[], "hail" => &[], - "microbit_v2" => &["--bundle-apps"], + "microbit_v2" => &[], "nrf52" | "nrf52840" => &[ "--jlink", "--arch", diff --git a/runtime/layouts/microbit_v2.ld b/runtime/layouts/microbit_v2.ld index 684810e2..ec337a76 100644 --- a/runtime/layouts/microbit_v2.ld +++ b/runtime/layouts/microbit_v2.ld @@ -2,7 +2,7 @@ MEMORY { FLASH (X) : ORIGIN = 0x00040000, LENGTH = 256K - RAM (W) : ORIGIN = 0x20004000, LENGTH = 112K + RAM (W) : ORIGIN = 0x20005000, LENGTH = 112K } TBF_HEADER_SIZE = 0x60; diff --git a/src/lib.rs b/src/lib.rs index c13b39db..f532c29b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,3 +44,13 @@ pub mod temperature { pub type Temperature = temperature::Temperature; pub use temperature::TemperatureListener; } + +pub mod proximity { + use libtock_proximity as proximity; + pub type Proximity = proximity::Proximity; +} + +pub mod sound_pressure { + use libtock_sound_pressure as sound_pressure; + pub type SoundPressure = sound_pressure::SoundPressure; +} \ No newline at end of file