From 6b6ec1af71392fb980516f45100c028a27f4ee02 Mon Sep 17 00:00:00 2001 From: Boris Vinogradov Date: Tue, 26 Nov 2019 14:35:11 +0300 Subject: [PATCH] Switch async code to use core futures --- Cargo.toml | 5 +- src/adc.rs | 9 ++-- src/lib.rs | 134 ++++++++++++++++++++++++++++---------------------- src/rng.rs | 4 +- src/serial.rs | 8 +-- src/spi.rs | 6 +-- src/timer.rs | 13 +++-- 7 files changed, 96 insertions(+), 83 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0fc6ab3f7..b8d602286 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,15 +14,12 @@ readme = "README.md" repository = "https://github.com/rust-embedded/embedded-hal" version = "0.2.3" -[dependencies.nb] -version = "0.1.1" - [dev-dependencies] stm32f3 = { version = "0.8", features = ["stm32f303", "rt"] } futures = "0.1.17" [features] -unproven = ["nb/unstable"] +unproven = [] [package.metadata.docs.rs] features = ["unproven"] diff --git a/src/adc.rs b/src/adc.rs index cb7d7363f..c1bcdcab0 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1,7 +1,7 @@ //! Analog-digital conversion traits #[cfg(feature = "unproven")] -use nb; +use core::task::Poll; /// A marker trait to identify MCU pins that can be used as inputs to an ADC channel. /// @@ -61,6 +61,7 @@ pub trait Channel { /// /// ``` /// use embedded_hal::adc::{Channel, OneShot}; +/// use core::task::Poll::{self, Ready, Pending}; /// /// struct MyAdc; // 10-bit ADC, with 5 channels /// # impl MyAdc { @@ -76,12 +77,12 @@ pub trait Channel { /// { /// type Error = (); /// -/// fn read(&mut self, _pin: &mut PIN) -> nb::Result { +/// fn read(&mut self, _pin: &mut PIN) -> Poll> { /// let chan = 1 << PIN::channel(); /// self.power_up(); /// let result = self.do_conversion(chan); /// self.power_down(); -/// Ok(result.into()) +/// Ready(Ok(result.into())) /// } /// } /// ``` @@ -94,5 +95,5 @@ pub trait OneShot> { /// /// This method takes a `Pin` reference, as it is expected that the ADC will be able to sample /// whatever channel underlies the pin. - fn read(&mut self, pin: &mut Pin) -> nb::Result; + fn read(&mut self, pin: &mut Pin) -> Poll>; } diff --git a/src/lib.rs b/src/lib.rs index 13c0d8bd7..e9e83c3ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,7 +67,7 @@ //! Here's how a HAL trait may look like: //! //! ``` -//! extern crate nb; +//! use core::task::Poll::{self, Ready, Pending}; //! //! /// A serial interface //! pub trait Serial { @@ -75,10 +75,10 @@ //! type Error; //! //! /// Reads a single byte -//! fn read(&mut self) -> nb::Result; +//! fn read(&mut self) -> Poll>; //! //! /// Writes a single byte -//! fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error>; +//! fn write(&mut self, byte: u8) -> Poll>; //! } //! ``` //! @@ -93,7 +93,7 @@ //! those cases `nb::Result<_, Infallible>` is used. //! //! ``` -//! extern crate nb; +//! use ::core::task::Poll::{self, Ready, Pending}; //! //! # use std as core; //! use ::core::convert::Infallible; @@ -103,7 +103,7 @@ //! // .. //! //! /// "waits" until the count down is over -//! fn wait(&mut self) -> nb::Result<(), Infallible>; +//! fn wait(&mut self) -> Poll>; //! } //! //! # fn main() {} @@ -125,8 +125,8 @@ //! // crate: stm32f3xx-hal //! // An implementation of the `embedded-hal` traits for STM32F3xx microcontrollers //! -//! extern crate embedded_hal as hal; -//! extern crate nb; +//! use embedded_hal as hal; +//! use core::task::Poll::{self, Ready, Pending}; //! //! // device crate //! extern crate stm32f3; @@ -150,21 +150,21 @@ //! impl hal::serial::Read for Serial { //! type Error = Error; //! -//! fn read(&mut self) -> nb::Result { +//! fn read(&mut self) -> Poll> { //! // read the status register //! let isr = self.usart.isr.read(); //! //! if isr.ore().bit_is_set() { //! // Error: Buffer overrun -//! Err(nb::Error::Other(Error::Overrun)) +//! Ready(Err(Error::Overrun)) //! } //! // omitted: checks for other errors //! else if isr.rxne().bit_is_set() { //! // Data available: read the data register -//! Ok(self.usart.rdr.read().bits() as u8) +//! Ready(Ok(self.usart.rdr.read().bits() as u8)) //! } else { //! // No data available yet -//! Err(nb::Error::WouldBlock) +//! Pending //! } //! } //! } @@ -172,14 +172,14 @@ //! impl hal::serial::Write for Serial { //! type Error = Error; //! -//! fn write(&mut self, byte: u8) -> nb::Result<(), Error> { +//! fn write(&mut self, byte: u8) -> Poll> { //! // Similar to the `read` implementation -//! # Ok(()) +//! # Ready(Ok(())) //! } //! -//! fn flush(&mut self) -> nb::Result<(), Error> { +//! fn flush(&mut self) -> Poll> { //! // Similar to the `read` implementation -//! # Ok(()) +//! # Ready(Ok(())) //! } //! } //! @@ -202,9 +202,9 @@ //! fashion: //! //! ``` +//! #[macro_use] //! extern crate embedded_hal; -//! #[macro_use(block)] -//! extern crate nb; +//! use futures::Poll; //! //! use stm32f30x_hal::Serial1; //! use embedded_hal::serial::Write; @@ -224,10 +224,11 @@ //! //! # mod stm32f30x_hal { //! # use std::convert::Infallible; +//! # use core::task::Poll::{self, Ready, Pending}; //! # pub struct Serial1; //! # impl Serial1 { -//! # pub fn write(&mut self, _: u8) -> ::nb::Result<(), Infallible> { -//! # Ok(()) +//! # pub fn write(&mut self, _: u8) -> Poll> { +//! # Ready(Ok(())) //! # } //! # } //! # } @@ -244,9 +245,6 @@ //! extern crate embedded_hal as hal; //! extern crate futures; //! -//! #[macro_use(try_nb)] -//! extern crate nb; -//! //! use hal::prelude::*; //! use futures::{ //! future, @@ -389,9 +387,6 @@ //! //! extern crate embedded_hal as hal; //! -//! #[macro_use(r#await)] -//! extern crate nb; -//! //! use std::ops::Generator; //! use std::pin::Pin; //! @@ -481,11 +476,9 @@ //! - Write a whole buffer to a serial device in blocking a fashion. //! //! ``` -//! extern crate embedded_hal as hal; -//! #[macro_use(block)] -//! extern crate nb; +//! use embedded_hal as hal; //! -//! use hal::prelude::*; +//! use hal::{block, prelude::*}; //! //! fn write_all(serial: &mut S, buffer: &[u8]) -> Result<(), S::Error> //! where @@ -504,8 +497,8 @@ //! - Blocking serial read with timeout //! //! ``` -//! extern crate embedded_hal as hal; -//! extern crate nb; +//! use embedded_hal as hal; +//! use core::task::Poll::{self, Ready, Pending}; //! //! use hal::prelude::*; //! @@ -529,23 +522,23 @@ //! loop { //! match serial.read() { //! // raise error -//! Err(nb::Error::Other(e)) => return Err(Error::Serial(e)), -//! Err(nb::Error::WouldBlock) => { +//! Ready(Err(e)) => return Err(Error::Serial(e)), +//! NotReady => { //! // no data available yet, check the timer below //! }, -//! Ok(byte) => return Ok(byte), +//! Ready(Ok(byte)) => return Ok(byte), //! } //! //! match timer.wait() { -//! Err(nb::Error::Other(e)) => { +//! Ready(Err(e)) => { //! // The error type specified by `timer.wait()` is `!`, which //! // means no error can actually occur. The Rust compiler //! // still forces us to provide this match arm, though. //! unreachable!() //! }, //! // no timeout yet, try again -//! Err(nb::Error::WouldBlock) => continue, -//! Ok(()) => return Err(Error::TimedOut), +//! NotReady => continue, +//! Ready(Ok(())) => return Err(Error::TimedOut), //! } //! } //! } @@ -595,8 +588,8 @@ //! //! ``` //! # use std as core; -//! extern crate embedded_hal as hal; -//! extern crate nb; +//! use embedded_hal as hal; +//! use ::core::task::Poll::{self, Ready, Pending}; //! //! use hal::prelude::*; //! use ::core::convert::Infallible; @@ -608,9 +601,9 @@ //! loop { //! if let Some(byte) = cb.peek() { //! match serial.write(*byte) { -//! Err(nb::Error::Other(_)) => unreachable!(), -//! Err(nb::Error::WouldBlock) => return, -//! Ok(()) => {}, // keep flushing data +//! Ready(Err(_)) => unreachable!(), +//! NotReady => return, +//! Ready(Ok(())) => {}, // keep flushing data //! } //! } //! @@ -667,10 +660,10 @@ //! # fn deref_mut(&mut self) -> &mut T { self.0 } //! # } //! # struct Serial1; -//! # impl ::hal::serial::Write for Serial1 { +//! # impl hal::serial::Write for Serial1 { //! # type Error = Infallible; -//! # fn write(&mut self, _: u8) -> nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) } -//! # fn flush(&mut self) -> nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) } +//! # fn write(&mut self, _: u8) -> Poll> { Pending } +//! # fn flush(&mut self) -> Poll> { Pending } //! # } //! # struct CircularBuffer; //! # impl CircularBuffer { @@ -685,8 +678,33 @@ #![deny(missing_docs)] #![no_std] -#[macro_use] -extern crate nb; +#[cfg(feature = "unproven")] +use core::task::Poll; + +/// Turns the non-blocking expression `$e` into a blocking operation. +/// +/// # Input +/// +/// An expression `$e` that evaluates to `Poll>` +/// +/// # Output +/// +/// - `Ok(t)` if `$e` evaluates to `Ok(t)` +/// - `Err(e)` if `$e` evaluates to `Err(e)` +#[macro_export] +macro_rules! block { + ($e:expr) => { + loop { + use core::task::Poll; + + match $e { + Poll::Ready(Err(e)) => break Err(e), + Poll::Ready(Ok(t)) => break Ok(t), + Poll::Pending => {} + } + } + }; +} pub mod adc; pub mod blocking; @@ -709,11 +727,10 @@ pub mod watchdog; /// / events /// /// ``` -/// extern crate embedded_hal as hal; -/// #[macro_use(block)] -/// extern crate nb; +/// use embedded_hal as hal; +/// use core::task::Poll::{self, Ready, Pending}; /// -/// use hal::prelude::*; +/// use hal::{block, prelude::*}; /// /// fn main() { /// let mut capture: Capture1 = { @@ -742,7 +759,7 @@ pub mod watchdog; /// # type Channel = Channel; /// # type Error = Infallible; /// # type Time = MilliSeconds; -/// # fn capture(&mut self, _: Channel) -> ::nb::Result { Ok(0) } +/// # fn capture(&mut self, _: Channel) -> Poll> { Ready(Ok(0)) } /// # fn disable(&mut self, _: Channel) { unimplemented!() } /// # fn enable(&mut self, _: Channel) { unimplemented!() } /// # fn get_resolution(&self) -> MilliSeconds { unimplemented!() } @@ -778,7 +795,7 @@ pub trait Capture { /// /// NOTE that you must multiply the returned value by the *resolution* of /// this `Capture` interface to get a human time unit (e.g. seconds) - fn capture(&mut self, channel: Self::Channel) -> nb::Result; + fn capture(&mut self, channel: Self::Channel) -> Poll>; /// Disables a capture `channel` fn disable(&mut self, channel: Self::Channel); @@ -921,11 +938,10 @@ pub trait PwmPin { /// You can use this interface to measure the speed of a motor /// /// ``` -/// extern crate embedded_hal as hal; -/// #[macro_use(block)] -/// extern crate nb; +/// use embedded_hal as hal; +/// use core::task::Poll::{self, Ready, Pending}; /// -/// use hal::prelude::*; +/// use hal::{block, prelude::*}; /// /// fn main() { /// let mut qei: Qei1 = { @@ -955,13 +971,13 @@ pub trait PwmPin { /// # impl hal::Qei for Qei1 { /// # type Count = u16; /// # fn count(&self) -> u16 { 0 } -/// # fn direction(&self) -> ::hal::Direction { unimplemented!() } +/// # fn direction(&self) -> hal::Direction { unimplemented!() } /// # } /// # struct Timer6; /// # impl hal::timer::CountDown for Timer6 { /// # type Time = Seconds; /// # fn start(&mut self, _: T) where T: Into {} -/// # fn wait(&mut self) -> ::nb::Result<(), Infallible> { Ok(()) } +/// # fn wait(&mut self) -> Poll> { Ready(Ok(())) } /// # } /// ``` #[cfg(feature = "unproven")] diff --git a/src/rng.rs b/src/rng.rs index d662ff545..066ff0309 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -1,7 +1,7 @@ //! Random Number Generator Interface #[cfg(feature = "unproven")] -use nb; +use core::task::Poll; /// Nonblocking stream of random bytes. #[cfg(feature = "unproven")] @@ -13,5 +13,5 @@ pub trait Read { type Error; /// Get a number of bytes from the RNG. - fn read(&mut self, buf: &mut [u8]) -> nb::Result; + fn read(&mut self, buf: &mut [u8]) -> Poll>; } diff --git a/src/serial.rs b/src/serial.rs index 484bb2967..3671b795a 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -1,6 +1,6 @@ //! Serial interface -use nb; +use core::task::Poll; /// Read half of a serial interface /// @@ -11,7 +11,7 @@ pub trait Read { type Error; /// Reads a single word from the serial interface - fn read(&mut self) -> nb::Result; + fn read(&mut self) -> Poll>; } /// Write half of a serial interface @@ -20,8 +20,8 @@ pub trait Write { type Error; /// Writes a single word to the serial interface - fn write(&mut self, word: Word) -> nb::Result<(), Self::Error>; + fn write(&mut self, word: Word) -> Poll>; /// Ensures that none of the previously written words are still buffered - fn flush(&mut self) -> nb::Result<(), Self::Error>; + fn flush(&mut self) -> Poll>; } diff --git a/src/spi.rs b/src/spi.rs index 20d8538cd..1f8657420 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -1,6 +1,6 @@ //! Serial Peripheral Interface -use nb; +use core::task::Poll; /// Full duplex (master mode) /// @@ -20,10 +20,10 @@ pub trait FullDuplex { /// /// **NOTE** A word must be sent to the slave before attempting to call this /// method. - fn read(&mut self) -> nb::Result; + fn read(&mut self) -> Poll>; /// Sends a word to the slave - fn send(&mut self, word: Word) -> nb::Result<(), Self::Error>; + fn send(&mut self, word: Word) -> Poll>; } /// Clock polarity diff --git a/src/timer.rs b/src/timer.rs index cdde65398..a132e8c02 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1,7 +1,7 @@ //! Timers use core::convert::Infallible; -use nb; +use core::task::Poll; /// A count down timer /// @@ -18,11 +18,10 @@ use nb; /// You can use this timer to create delays /// /// ``` -/// extern crate embedded_hal as hal; -/// #[macro_use(block)] -/// extern crate nb; +/// use embedded_hal as hal; +/// use core::task::Poll::{self, Ready, Pending}; /// -/// use hal::prelude::*; +/// use hal::{block, prelude::*}; /// /// fn main() { /// let mut led: Led = { @@ -53,7 +52,7 @@ use nb; /// # impl hal::timer::CountDown for Timer6 { /// # type Time = Seconds; /// # fn start(&mut self, _: T) where T: Into {} -/// # fn wait(&mut self) -> ::nb::Result<(), Infallible> { Ok(()) } +/// # fn wait(&mut self) -> Poll> { Ready(Ok(())) } /// # } /// ``` pub trait CountDown { @@ -73,7 +72,7 @@ pub trait CountDown { /// finishes. /// - Otherwise the behavior of calling `wait` after the last call returned `Ok` is UNSPECIFIED. /// Implementers are suggested to panic on this scenario to signal a programmer error. - fn wait(&mut self) -> nb::Result<(), Infallible>; + fn wait(&mut self) -> Poll>; } /// Marker trait that indicates that a timer is periodic