From f39300326ce33665487cb19a611327a6cc552b0c Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Tue, 19 Nov 2019 20:56:19 +0000 Subject: [PATCH 01/10] Re-organising repo - starting with digital and SPI. --- Cargo.toml | 32 +- README.md | 49 +--- embedded-hal-digital/Cargo.toml | 14 + .../v2.rs => embedded-hal-digital/src/lib.rs | 15 +- embedded-hal-spi/Cargo.toml | 15 + src/spi.rs => embedded-hal-spi/src/lib.rs | 0 embedded-hal/Cargo.toml | 20 ++ embedded-hal/README.md | 86 ++++++ embedded-hal/src/lib.rs | 11 + src/adc.rs | 98 ------- src/blocking/delay.rs | 26 -- src/blocking/i2c.rs | 129 -------- src/blocking/mod.rs | 11 - src/blocking/rng.rs | 19 -- src/digital/mod.rs | 25 -- src/digital/v1.rs | 142 --------- src/digital/v1_compat.rs | 276 ------------------ src/rng.rs | 17 -- src/serial.rs | 27 -- src/timer.rs | 94 ------ src/watchdog.rs | 32 -- 21 files changed, 160 insertions(+), 978 deletions(-) create mode 100644 embedded-hal-digital/Cargo.toml rename src/digital/v2.rs => embedded-hal-digital/src/lib.rs (90%) create mode 100644 embedded-hal-spi/Cargo.toml rename src/spi.rs => embedded-hal-spi/src/lib.rs (100%) create mode 100644 embedded-hal/Cargo.toml create mode 100644 embedded-hal/README.md create mode 100644 embedded-hal/src/lib.rs delete mode 100644 src/adc.rs delete mode 100644 src/blocking/delay.rs delete mode 100644 src/blocking/i2c.rs delete mode 100644 src/blocking/mod.rs delete mode 100644 src/blocking/rng.rs delete mode 100644 src/digital/mod.rs delete mode 100644 src/digital/v1.rs delete mode 100644 src/digital/v1_compat.rs delete mode 100644 src/rng.rs delete mode 100644 src/serial.rs delete mode 100644 src/timer.rs delete mode 100644 src/watchdog.rs diff --git a/Cargo.toml b/Cargo.toml index 0fc6ab3f7..a95193d8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,28 +1,6 @@ -[package] -authors = [ - "Jorge Aparicio ", - "Jonathan 'theJPster' Pallant " +[workspace] +members = [ + "embedded-hal", + "embedded-hal-digital", + "embedded-hal-spi", ] -categories = ["asynchronous", "embedded", "hardware-support", "no-std"] -description = " A Hardware Abstraction Layer (HAL) for embedded systems " -documentation = "https://docs.rs/embedded-hal" -edition = "2018" -keywords = ["hal", "IO"] -license = "MIT OR Apache-2.0" -name = "embedded-hal" -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"] - -[package.metadata.docs.rs] -features = ["unproven"] diff --git a/README.md b/README.md index 66d9a33b8..35c1f8932 100644 --- a/README.md +++ b/README.md @@ -4,54 +4,9 @@ This project is developed and maintained by the [HAL team][team]. -## [API reference] +## Repository Layout -[API reference]: https://docs.rs/embedded-hal - -## How-to: add a new trait - -This is the suggested approach to adding a new trait to `embedded-hal` - -### Discussion - -Ideally, before proposing a new trait, or set of traits, you should create an issue where the use -cases and requirements of the trait(s) are discussed. - -These issues will be labeled as `discussion`s in the issue tracker. - -### Proposing a trait - -Once there's consensus on the requirements of the trait(s) a new issue, or a PR, with a proposal -should be opened. The proposal should include the actual trait definitions as well as a link to the -issue with previous discussion, if there was one. - -If the proposal includes more than one alternative then there should be further discussion to try to -single out the best alternative. - -These issues / PRs will be labeled as `proposal`s in the issue tracker. - -### Testing period - -If there are no objections to the proposal the new trait(s) will land behind the "unproven" Cargo -feature and an issue about the new trait(s) will be created. If the proposal includes several -alternatives and a single one couldn't be chosen as the best then each alternative will land behind -a different Cargo feature, e.g. "alt1" or "alt2". - -The traits will undergo a testing period before they move into the set of proven traits. During -this period users are encouraged to try to implement the unproven traits for their platforms and to -build drivers on top of them. Problems implementing the trait(s) as well as successful -implementations should be reported on the corresponding issue. - -To leave the unproven state at least *two* implementations of the trait(s) for different platforms -(ideally, the two platforms should be from different vendors) and *one* generic driver built on top -of the trait(s), or alternatively one demo program that exercises the trait (via generic function / -trait object), *should* be demonstrated. If, instead, reports indicate that the proposed trait(s) -can't be implemented for a certain platform then the trait(s) will be removed and we'll go back to -the drawing board. - -Issues used to track unproven APIs will be labeled as `unproven-api`s in the issue tracker and they -may also include the labels `needs-impl` and `needs-driver` to signal what's required for them to -move to the set of proven traits. +This repository is a workspace containing multiple crates. The top-level crate is [`embedded-hal`](./embedded-hal), which pulls in the various other HAL crates at stable revisions. If you want the bleeding-edge, you can depend on one of the other HAL crates separately. ## Implementations and drivers diff --git a/embedded-hal-digital/Cargo.toml b/embedded-hal-digital/Cargo.toml new file mode 100644 index 000000000..dc52b36e0 --- /dev/null +++ b/embedded-hal-digital/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "embedded-hal-digital" +version = "1.0.0-rc1" +authors = ["Rust Embedded Working Group "] +edition = "2018" +categories = ["gpio", "embedded", "hardware-support", "no-std"] +description = " A digital GPIO pin Hardware Abstraction Layer (HAL) for embedded systems " +documentation = "https://docs.rs/embedded-hal-digital" +keywords = ["hal", "IO", "gpio"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-embedded/embedded-hal" + +[dependencies] diff --git a/src/digital/v2.rs b/embedded-hal-digital/src/lib.rs similarity index 90% rename from src/digital/v2.rs rename to embedded-hal-digital/src/lib.rs index b8ccf2740..1c229ab08 100644 --- a/src/digital/v2.rs +++ b/embedded-hal-digital/src/lib.rs @@ -1,6 +1,8 @@ -//! Digital I/O +//! # embedded-hal-digital //! -//! Version 2 / fallible traits. Infallible implementations should set Error to `!`. +//! Contains digital GPIO pin traits. You should use the +//! [`embedded-hal`](https://crates.io/crates/embedded-hal) crate if you want +//! a stable version. /// Single digital push-pull output pin pub trait OutputPin { @@ -23,8 +25,7 @@ pub trait OutputPin { /// Push-pull output pin that can read its output state /// /// *This trait is available if embedded-hal is built with the `"unproven"` feature.* -#[cfg(feature = "unproven")] -pub trait StatefulOutputPin : OutputPin { +pub trait StatefulOutputPin: OutputPin { /// Is the pin in drive high mode? /// /// *NOTE* this does *not* read the electrical state of the pin @@ -44,7 +45,6 @@ pub trait StatefulOutputPin : OutputPin { /// both [OutputPin](trait.OutputPin.html) and /// [StatefulOutputPin](trait.StatefulOutputPin.html) are /// implemented. Otherwise, implement this using hardware mechanisms. -#[cfg(feature = "unproven")] pub trait ToggleableOutputPin { /// Error type type Error; @@ -57,8 +57,8 @@ pub trait ToggleableOutputPin { /// toggleable by software. /// /// ``` -/// use embedded_hal::digital::v2::{OutputPin, StatefulOutputPin, ToggleableOutputPin}; -/// use embedded_hal::digital::v2::toggleable; +/// use embedded_hal_digital::{OutputPin, StatefulOutputPin, ToggleableOutputPin}; +/// use embedded_hal_digital::toggleable; /// use std::convert::Infallible; /// /// /// A virtual output pin that exists purely in software @@ -97,7 +97,6 @@ pub trait ToggleableOutputPin { /// pin.toggle().unwrap(); /// assert!(pin.is_set_low().unwrap()); /// ``` -#[cfg(feature = "unproven")] pub mod toggleable { use super::{OutputPin, StatefulOutputPin, ToggleableOutputPin}; diff --git a/embedded-hal-spi/Cargo.toml b/embedded-hal-spi/Cargo.toml new file mode 100644 index 000000000..0e6d1a8f8 --- /dev/null +++ b/embedded-hal-spi/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "embedded-hal-spi" +version = "1.0.0-rc1" +authors = ["Rust Embedded Working Group "] +edition = "2018" +categories = ["gpio", "embedded", "hardware-support", "no-std"] +description = " A Serial Peripheral Interface (SPI) Hardware Abstraction Layer (HAL) for embedded systems " +documentation = "https://docs.rs/embedded-hal-spi" +keywords = ["hal", "IO", "gpio"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-embedded/embedded-hal" + +[dependencies] +nb = "0.1" diff --git a/src/spi.rs b/embedded-hal-spi/src/lib.rs similarity index 100% rename from src/spi.rs rename to embedded-hal-spi/src/lib.rs diff --git a/embedded-hal/Cargo.toml b/embedded-hal/Cargo.toml new file mode 100644 index 000000000..15e0d3b71 --- /dev/null +++ b/embedded-hal/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "embedded-hal" +version = "1.0.0-rc1" +authors = ["Rust Embedded Working Group "] +edition = "2018" +categories = ["asynchronous", "embedded", "hardware-support", "no-std"] +description = " A Hardware Abstraction Layer (HAL) for embedded systems " +documentation = "https://docs.rs/embedded-hal" +keywords = ["hal", "IO"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-embedded/embedded-hal" + +[dependencies.embedded-hal-digital] +path = "../embedded-hal-digital" +# version = "1.0" + +[dependencies.embedded-hal-spi] +path = "../embedded-hal-spi" +# version = "1.0" diff --git a/embedded-hal/README.md b/embedded-hal/README.md new file mode 100644 index 000000000..66d9a33b8 --- /dev/null +++ b/embedded-hal/README.md @@ -0,0 +1,86 @@ +# `embedded-hal` + +> A Hardware Abstraction Layer (HAL) for embedded systems + +This project is developed and maintained by the [HAL team][team]. + +## [API reference] + +[API reference]: https://docs.rs/embedded-hal + +## How-to: add a new trait + +This is the suggested approach to adding a new trait to `embedded-hal` + +### Discussion + +Ideally, before proposing a new trait, or set of traits, you should create an issue where the use +cases and requirements of the trait(s) are discussed. + +These issues will be labeled as `discussion`s in the issue tracker. + +### Proposing a trait + +Once there's consensus on the requirements of the trait(s) a new issue, or a PR, with a proposal +should be opened. The proposal should include the actual trait definitions as well as a link to the +issue with previous discussion, if there was one. + +If the proposal includes more than one alternative then there should be further discussion to try to +single out the best alternative. + +These issues / PRs will be labeled as `proposal`s in the issue tracker. + +### Testing period + +If there are no objections to the proposal the new trait(s) will land behind the "unproven" Cargo +feature and an issue about the new trait(s) will be created. If the proposal includes several +alternatives and a single one couldn't be chosen as the best then each alternative will land behind +a different Cargo feature, e.g. "alt1" or "alt2". + +The traits will undergo a testing period before they move into the set of proven traits. During +this period users are encouraged to try to implement the unproven traits for their platforms and to +build drivers on top of them. Problems implementing the trait(s) as well as successful +implementations should be reported on the corresponding issue. + +To leave the unproven state at least *two* implementations of the trait(s) for different platforms +(ideally, the two platforms should be from different vendors) and *one* generic driver built on top +of the trait(s), or alternatively one demo program that exercises the trait (via generic function / +trait object), *should* be demonstrated. If, instead, reports indicate that the proposed trait(s) +can't be implemented for a certain platform then the trait(s) will be removed and we'll go back to +the drawing board. + +Issues used to track unproven APIs will be labeled as `unproven-api`s in the issue tracker and they +may also include the labels `needs-impl` and `needs-driver` to signal what's required for them to +move to the set of proven traits. + +## Implementations and drivers + +For a list of `embedded-hal` implementations and driver crates check the [awesome-embedded-rust] +list. + +[awesome-embedded-rust]: https://github.com/rust-embedded/awesome-embedded-rust#driver-crates + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +## Code of Conduct + +Contribution to this crate is organized under the terms of the [Rust Code of +Conduct][CoC], the maintainer of this crate, the [HAL team][team], promises +to intervene to uphold that code of conduct. + +[CoC]: CODE_OF_CONDUCT.md +[team]: https://github.com/rust-embedded/wg#the-hal-team diff --git a/embedded-hal/src/lib.rs b/embedded-hal/src/lib.rs new file mode 100644 index 000000000..7a0176fca --- /dev/null +++ b/embedded-hal/src/lib.rs @@ -0,0 +1,11 @@ +//! # embedded-hal +//! +//! See README.md. + +pub mod digital { + pub use embedded_hal_digital::{InputPin, OutputPin, StatefulOutputPin}; +} + +pub mod spi { + pub use embedded_hal_spi::{FullDuplex, Polarity, Phase, Mode, MODE_0, MODE_1, MODE_2, MODE_3}; +} diff --git a/src/adc.rs b/src/adc.rs deleted file mode 100644 index cb7d7363f..000000000 --- a/src/adc.rs +++ /dev/null @@ -1,98 +0,0 @@ -//! Analog-digital conversion traits - -#[cfg(feature = "unproven")] -use nb; - -/// A marker trait to identify MCU pins that can be used as inputs to an ADC channel. -/// -/// This marker trait denotes an object, i.e. a GPIO pin, that is ready for use as an input to the -/// ADC. As ADCs channels can be supplied by multiple pins, this trait defines the relationship -/// between the physical interface and the ADC sampling buffer. -/// -/// ``` -/// # use std::marker::PhantomData; -/// # use embedded_hal::adc::Channel; -/// -/// struct Adc1; // Example ADC with single bank of 8 channels -/// struct Gpio1Pin1(PhantomData); -/// struct Analog(()); // marker type to denote a pin in "analog" mode -/// -/// // GPIO 1 pin 1 can supply an ADC channel when it is configured in Analog mode -/// impl Channel for Gpio1Pin1 { -/// type ID = u8; // ADC channels are identified numerically -/// -/// fn channel() -> u8 { 7_u8 } // GPIO pin 1 is connected to ADC channel 7 -/// } -/// -/// struct Adc2; // ADC with two banks of 16 channels -/// struct Gpio2PinA(PhantomData); -/// struct AltFun(()); // marker type to denote some alternate function mode for the pin -/// -/// // GPIO 2 pin A can supply an ADC channel when it's configured in some alternate function mode -/// impl Channel for Gpio2PinA { -/// type ID = (u8, u8); // ADC channels are identified by bank number and channel number -/// -/// fn channel() -> (u8, u8) { (0, 3) } // bank 0 channel 3 -/// } -/// ``` -#[cfg(feature = "unproven")] -pub trait Channel { - /// Channel ID type - /// - /// A type used to identify this ADC channel. For example, if the ADC has eight channels, this - /// might be a `u8`. If the ADC has multiple banks of channels, it could be a tuple, like - /// `(u8: bank_id, u8: channel_id)`. - type ID; - - /// Get the specific ID that identifies this channel, for example `0_u8` for the first ADC - /// channel, if Self::ID is u8. - fn channel() -> Self::ID; - - // `channel` is a function due to [this reported - // issue](https://github.com/rust-lang/rust/issues/54973). Something about blanket impls - // combined with `type ID; const CHANNEL: Self::ID;` causes problems. - //const CHANNEL: Self::ID; -} - -/// ADCs that sample on single channels per request, and do so at the time of the request. -/// -/// This trait is the interface to an ADC that is configured to read a specific channel at the time -/// of the request (in contrast to continuous asynchronous sampling). -/// -/// ``` -/// use embedded_hal::adc::{Channel, OneShot}; -/// -/// struct MyAdc; // 10-bit ADC, with 5 channels -/// # impl MyAdc { -/// # pub fn power_up(&mut self) {} -/// # pub fn power_down(&mut self) {} -/// # pub fn do_conversion(&mut self, chan: u8) -> u16 { 0xAA55_u16 } -/// # } -/// -/// impl OneShot for MyAdc -/// where -/// WORD: From, -/// PIN: Channel, -/// { -/// type Error = (); -/// -/// fn read(&mut self, _pin: &mut PIN) -> nb::Result { -/// let chan = 1 << PIN::channel(); -/// self.power_up(); -/// let result = self.do_conversion(chan); -/// self.power_down(); -/// Ok(result.into()) -/// } -/// } -/// ``` -#[cfg(feature = "unproven")] -pub trait OneShot> { - /// Error type returned by ADC methods - type Error; - - /// Request that the ADC begin a conversion on the specified pin - /// - /// 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; -} diff --git a/src/blocking/delay.rs b/src/blocking/delay.rs deleted file mode 100644 index 177c29ccd..000000000 --- a/src/blocking/delay.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Delays -//! -//! # What's the difference between these traits and the `timer::CountDown` trait? -//! -//! The `Timer` trait provides a *non-blocking* timer abstraction and it's meant to be used to build -//! higher level abstractions like I/O operations with timeouts. OTOH, these delays traits only -//! provide *blocking* functionality. Note that you can also use the `timer::CountDown` trait to -//! implement blocking delays. - -/// Millisecond delay -/// -/// `UXX` denotes the range type of the delay time. `UXX` can be `u8`, `u16`, etc. A single type can -/// implement this trait for different types of `UXX`. -pub trait DelayMs { - /// Pauses execution for `ms` milliseconds - fn delay_ms(&mut self, ms: UXX); -} - -/// Microsecond delay -/// -/// `UXX` denotes the range type of the delay time. `UXX` can be `u8`, `u16`, etc. A single type can -/// implement this trait for different types of `UXX`. -pub trait DelayUs { - /// Pauses execution for `us` microseconds - fn delay_us(&mut self, us: UXX); -} diff --git a/src/blocking/i2c.rs b/src/blocking/i2c.rs deleted file mode 100644 index 1c654f770..000000000 --- a/src/blocking/i2c.rs +++ /dev/null @@ -1,129 +0,0 @@ -//! Blocking I2C API -//! -//! Slave addresses used by this API are 7-bit I2C addresses ranging from 0 to 127. -//! -//! Operations on 10-bit slave addresses are not supported by the API yet (but applications might -//! be able to emulate some operations). - -/// Blocking read -pub trait Read { - /// Error type - type Error; - - /// Reads enough bytes from slave with `address` to fill `buffer` - /// - /// # I2C Events (contract) - /// - /// ``` text - /// Master: ST SAD+R MAK MAK ... NMAK SP - /// Slave: SAK B0 B1 ... BN - /// ``` - /// - /// Where - /// - /// - `ST` = start condition - /// - `SAD+R` = slave address followed by bit 1 to indicate reading - /// - `SAK` = slave acknowledge - /// - `Bi` = ith byte of data - /// - `MAK` = master acknowledge - /// - `NMAK` = master no acknowledge - /// - `SP` = stop condition - fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error>; -} - -/// Blocking write -pub trait Write { - /// Error type - type Error; - - /// Sends bytes to slave with address `addr` - /// - /// # I2C Events (contract) - /// - /// ``` text - /// Master: ST SAD+W B0 B1 ... BN SP - /// Slave: SAK SAK SAK ... SAK - /// ``` - /// - /// Where - /// - /// - `ST` = start condition - /// - `SAD+W` = slave address followed by bit 0 to indicate writing - /// - `SAK` = slave acknowledge - /// - `Bi` = ith byte of data - /// - `SP` = stop condition - fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error>; -} - -/// Blocking write (iterator version) -#[cfg(feature = "unproven")] -pub trait WriteIter { - /// Error type - type Error; - - /// Sends bytes to slave with address `addr` - /// - /// # I2C Events (contract) - /// - /// Same as `Write` - fn write(&mut self, addr: u8, bytes: B) -> Result<(), Self::Error> - where - B: IntoIterator; -} - -/// Blocking write + read -pub trait WriteRead { - /// Error type - type Error; - - /// Sends bytes to slave with address `addr` and then reads enough bytes to fill `buffer` *in a - /// single transaction* - /// - /// # I2C Events (contract) - /// - /// ``` text - /// Master: ST SAD+W O0 O1 ... OM SR SAD+R MAK MAK ... NMAK SP - /// Slave: SAK SAK SAK ... SAK SAK I0 I1 ... IN - /// ``` - /// - /// Where - /// - /// - `ST` = start condition - /// - `SAD+W` = slave address followed by bit 0 to indicate writing - /// - `SAK` = slave acknowledge - /// - `Oi` = ith outgoing byte of data - /// - `SR` = repeated start condition - /// - `SAD+R` = slave address followed by bit 1 to indicate reading - /// - `Ii` = ith incoming byte of data - /// - `MAK` = master acknowledge - /// - `NMAK` = master no acknowledge - /// - `SP` = stop condition - fn write_read( - &mut self, - address: u8, - bytes: &[u8], - buffer: &mut [u8], - ) -> Result<(), Self::Error>; -} - -/// Blocking write (iterator version) + read -#[cfg(feature = "unproven")] -pub trait WriteIterRead { - /// Error type - type Error; - - /// Sends bytes to slave with address `addr` and then reads enough bytes to fill `buffer` *in a - /// single transaction* - /// - /// # I2C Events (contract) - /// - /// Same as the `WriteRead` trait - fn write_iter_read( - &mut self, - address: u8, - bytes: B, - buffer: &mut [u8], - ) -> Result<(), Self::Error> - where - B: IntoIterator; -} diff --git a/src/blocking/mod.rs b/src/blocking/mod.rs deleted file mode 100644 index 3a050f6d2..000000000 --- a/src/blocking/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Blocking API -//! -//! In some cases it's possible to implement these blocking traits on top of one of the core HAL -//! traits. To save boilerplate when that's the case a `Default` marker trait may be provided. -//! Implementing that marker trait will opt in your type into a blanket implementation. - -pub mod delay; -pub mod i2c; -pub mod rng; -pub mod serial; -pub mod spi; diff --git a/src/blocking/rng.rs b/src/blocking/rng.rs deleted file mode 100644 index cd8a543b6..000000000 --- a/src/blocking/rng.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! Blocking hardware random number generator - -/// Blocking read -/// -/// *This trait is available if embedded-hal is built with the `"unproven"` feature.* -#[cfg(feature = "unproven")] -pub trait Read { - /// Error type - type Error; - - /// Reads enough bytes from hardware random number generator to fill `buffer` - /// - /// If any error is encountered then this function immediately returns. The contents of buf are - /// unspecified in this case. - /// - /// If this function returns an error, it is unspecified how many bytes it has read, but it - /// will never read more than would be necessary to completely fill the buffer. - fn read(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error>; -} diff --git a/src/digital/mod.rs b/src/digital/mod.rs deleted file mode 100644 index 4e67f9851..000000000 --- a/src/digital/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -//! Digital I/O -//! -//! -//! - -// Deprecated / infallible traits -#[deprecated(since = "0.2.2", note = "Deprecated because the methods cannot return errors. \ - Users should use the traits in digital::v2.")] -pub mod v1; - -// New / fallible traits -pub mod v2; - -// v2 -> v1 compatibility wrappers -// These require explicit casts from v2 -> v1 -pub mod v1_compat; - -// v1 -> v2 compatibility shims -// These are implicit over v1 implementations -pub mod v2_compat; - -// Re-export old traits so this isn't a breaking change -#[allow(deprecated)] -pub use self::v1::*; - diff --git a/src/digital/v1.rs b/src/digital/v1.rs deleted file mode 100644 index 9c0678b10..000000000 --- a/src/digital/v1.rs +++ /dev/null @@ -1,142 +0,0 @@ -//! Digital I/O -//! -//! The traits in this module are now deprecated. Please use the new versions included -//! in `digital::v2`. - -#![allow(deprecated)] - -/// Single digital push-pull output pin -/// -/// *This version of the trait is now deprecated. Please use the new `OutputPin` trait in -/// `digital::v2::OutputPin`*. - -pub trait OutputPin { - /// Drives the pin low - /// - /// *NOTE* the actual electrical state of the pin may not actually be low, e.g. due to external - /// electrical sources - fn set_low(&mut self); - - /// Drives the pin high - /// - /// *NOTE* the actual electrical state of the pin may not actually be high, e.g. due to external - /// electrical sources - fn set_high(&mut self); -} - -/// Push-pull output pin that can read its output state -/// -/// *This trait is available if embedded-hal is built with the `"unproven"` feature.* -/// -/// *This version of the trait is now deprecated. Please use the new `StatefulOutputPin` trait in -/// `digital::v2::StatefulOutputPin`*. -#[cfg(feature = "unproven")] -pub trait StatefulOutputPin { - /// Is the pin in drive high mode? - /// - /// *NOTE* this does *not* read the electrical state of the pin - fn is_set_high(&self) -> bool; - - /// Is the pin in drive low mode? - /// - /// *NOTE* this does *not* read the electrical state of the pin - fn is_set_low(&self) -> bool; -} - -/// Output pin that can be toggled -/// -/// *This trait is available if embedded-hal is built with the `"unproven"` feature.* -/// -/// *This version of the trait is now deprecated. Please use the new `ToggleableOutputPin` -/// trait in `digital::v2::ToggleableOutputPin`*. -/// -/// See [toggleable](toggleable) to use a software implementation if -/// both [OutputPin](trait.OutputPin.html) and -/// [StatefulOutputPin](trait.StatefulOutputPin.html) are -/// implemented. Otherwise, implement this using hardware mechanisms. -#[cfg(feature = "unproven")] -pub trait ToggleableOutputPin { - /// Toggle pin output. - fn toggle(&mut self); -} - -/// If you can read **and** write the output state, a pin is -/// toggleable by software. -/// -/// *This version of the module is now deprecated. Please use the new `toggleable` module in -/// `digital::v2::toggleable`*. -/// -/// ``` -/// use embedded_hal::digital::{OutputPin, StatefulOutputPin, ToggleableOutputPin}; -/// use embedded_hal::digital::toggleable; -/// -/// /// A virtual output pin that exists purely in software -/// struct MyPin { -/// state: bool -/// } -/// -/// impl OutputPin for MyPin { -/// fn set_low(&mut self) { -/// self.state = false; -/// } -/// fn set_high(&mut self) { -/// self.state = true; -/// } -/// } -/// -/// impl StatefulOutputPin for MyPin { -/// fn is_set_low(&self) -> bool { -/// !self.state -/// } -/// fn is_set_high(&self) -> bool { -/// self.state -/// } -/// } -/// -/// /// Opt-in to the software implementation. -/// impl toggleable::Default for MyPin {} -/// -/// let mut pin = MyPin { state: false }; -/// pin.toggle(); -/// assert!(pin.is_set_high()); -/// pin.toggle(); -/// assert!(pin.is_set_low()); -/// ``` -#[cfg(feature = "unproven")] -pub mod toggleable { - #[allow(deprecated)] - use super::{OutputPin, StatefulOutputPin, ToggleableOutputPin}; - - /// Software-driven `toggle()` implementation. - /// - /// *This trait is available if embedded-hal is built with the `"unproven"` feature.* - #[allow(deprecated)] - pub trait Default: OutputPin + StatefulOutputPin {} - - #[allow(deprecated)] - impl

ToggleableOutputPin for P - where - P: Default, - { - /// Toggle pin output - fn toggle(&mut self) { - if self.is_set_low() { - self.set_high(); - } else { - self.set_low(); - } - } - } -} - -/// Single digital input pin -/// -/// *This version of the trait is now deprecated. Please use the new `InputPin` trait in -/// `digital::v2::InputPin`*. -pub trait InputPin { - /// Is the input pin high? - fn is_high(&self) -> bool; - - /// Is the input pin low? - fn is_low(&self) -> bool; -} diff --git a/src/digital/v1_compat.rs b/src/digital/v1_compat.rs deleted file mode 100644 index a6689186c..000000000 --- a/src/digital/v1_compat.rs +++ /dev/null @@ -1,276 +0,0 @@ -//! v1 compatibility wrappers -//! -//! This module provides wrappers to support use of v2 implementations with -//! v1 consumers. v2 traits must be explicitly cast to the v1 version using -//! `.into()`, and will panic on internal errors -//! -//! ``` -//! extern crate embedded_hal; -//! use embedded_hal::digital::{v1, v2, v1_compat::OldOutputPin}; -//! -//! struct NewOutputPinImpl {} -//! -//! impl v2::OutputPin for NewOutputPinImpl { -//! type Error = (); -//! fn set_low(&mut self) -> Result<(), Self::Error> { Ok(()) } -//! fn set_high(&mut self) -> Result<(), Self::Error>{ Ok(()) } -//! } -//! -//! struct OldOutputPinConsumer { -//! _pin: T, -//! } -//! -//! impl OldOutputPinConsumer -//! where T: v1::OutputPin { -//! pub fn new(pin: T) -> OldOutputPinConsumer { -//! OldOutputPinConsumer{ _pin: pin } -//! } -//! } -//! -//! fn main() { -//! let pin = NewOutputPinImpl{}; -//! let _consumer: OldOutputPinConsumer> = OldOutputPinConsumer::new(pin.into()); -//! } -//! ``` -//! - - -#[allow(deprecated)] -use super::v1; -use super::v2; - -/// Wrapper to allow fallible `v2::OutputPin` traits to be converted to `v1::OutputPin` traits -pub struct OldOutputPin { - pin: T, -} - -impl OldOutputPin -where - T: v2::OutputPin, - E: core::fmt::Debug, -{ - /// Create a new OldOutputPin wrapper around a `v2::OutputPin` - pub fn new(pin: T) -> Self { - Self{pin} - } - - /// Fetch a reference to the inner `v2::OutputPin` impl - #[cfg(test)] - fn inner(&self) -> &T { - &self.pin - } -} - -impl From for OldOutputPin -where - T: v2::OutputPin, - E: core::fmt::Debug, -{ - fn from(pin: T) -> Self { - OldOutputPin{pin} - } -} - -/// Implementation of `v1::OutputPin` trait for fallible `v2::OutputPin` output pins -/// where errors will panic. -#[allow(deprecated)] -impl v1::OutputPin for OldOutputPin -where - T: v2::OutputPin, - E: core::fmt::Debug, -{ - fn set_low(&mut self) { - self.pin.set_low().unwrap() - } - - fn set_high(&mut self) { - self.pin.set_high().unwrap() - } -} - -/// Implementation of `v1::StatefulOutputPin` trait for `v2::StatefulOutputPin` fallible pins -/// where errors will panic. -#[cfg(feature = "unproven")] -#[allow(deprecated)] -impl v1::StatefulOutputPin for OldOutputPin -where - T: v2::StatefulOutputPin, - E: core::fmt::Debug, -{ - fn is_set_low(&self) -> bool { - self.pin.is_set_low().unwrap() - } - - fn is_set_high(&self) -> bool { - self.pin.is_set_high().unwrap() - } -} - -/// Wrapper to allow fallible `v2::InputPin` traits to be converted to `v1::InputPin` traits -/// where errors will panic. -pub struct OldInputPin { - pin: T, -} - -impl OldInputPin -where - T: v2::OutputPin, - E: core::fmt::Debug, -{ - /// Create an `OldInputPin` wrapper around a `v2::InputPin`. - pub fn new(pin: T) -> Self { - Self{pin} - } - -} - -impl From for OldInputPin -where - T: v2::InputPin, - E: core::fmt::Debug, -{ - fn from(pin: T) -> Self { - OldInputPin{pin} - } -} - -/// Implementation of `v1::InputPin` trait for `v2::InputPin` fallible pins -/// where errors will panic. -#[allow(deprecated)] -impl v1::InputPin for OldInputPin -where - T: v2::InputPin, - E: core::fmt::Debug, -{ - fn is_low(&self) -> bool { - self.pin.is_low().unwrap() - } - - fn is_high(&self) -> bool { - self.pin.is_high().unwrap() - } -} - -#[cfg(test)] -#[allow(deprecated)] -mod tests { - use super::*; - - #[allow(deprecated)] - use crate::digital::v1; - use crate::digital::v2; - - use crate::digital::v1::OutputPin; - - #[derive(Clone)] - struct NewOutputPinImpl { - state: bool, - res: Result<(), ()> - } - - impl v2::OutputPin for NewOutputPinImpl { - type Error = (); - - fn set_low(&mut self) -> Result<(), Self::Error> { - self.state = false; - self.res - } - fn set_high(&mut self) -> Result<(), Self::Error>{ - self.state = true; - self.res - } - } - - #[allow(deprecated)] - struct OldOutputPinConsumer { - _pin: T, - } - - #[allow(deprecated)] - impl OldOutputPinConsumer - where T: v1::OutputPin - { - pub fn new(pin: T) -> OldOutputPinConsumer { - OldOutputPinConsumer{ _pin: pin } - } - } - - #[test] - fn v1_v2_output_explicit() { - let i = NewOutputPinImpl{state: false, res: Ok(())}; - let _c: OldOutputPinConsumer> = OldOutputPinConsumer::new(i.into()); - } - - #[test] - fn v1_v2_output_state() { - let mut o: OldOutputPin<_> = NewOutputPinImpl{state: false, res: Ok(())}.into(); - - o.set_high(); - assert_eq!(o.inner().state, true); - - o.set_low(); - assert_eq!(o.inner().state, false); - } - - #[test] - #[should_panic] - fn v1_v2_output_panic() { - let mut o: OldOutputPin<_> = NewOutputPinImpl{state: false, res: Err(())}.into(); - - o.set_high(); - } - - use crate::digital::v1::InputPin; - - struct NewInputPinImpl { - state: Result, - } - - impl v2::InputPin for NewInputPinImpl { - type Error = (); - - fn is_low(&self) -> Result { - self.state.map(|v| v == false) - } - fn is_high(&self) -> Result{ - self.state.map(|v| v == true) - } - } - - #[allow(deprecated)] - struct OldInputPinConsumer { - _pin: T, - } - - #[allow(deprecated)] - impl OldInputPinConsumer - where T: v1::InputPin - { - pub fn new(pin: T) -> OldInputPinConsumer { - OldInputPinConsumer{ _pin: pin } - } - } - - #[test] - fn v1_v2_input_explicit() { - let i = NewInputPinImpl{state: Ok(false)}; - let _c: OldInputPinConsumer> = OldInputPinConsumer::new(i.into()); - } - - #[test] - fn v1_v2_input_state() { - let i: OldInputPin<_> = NewInputPinImpl{state: Ok(false)}.into(); - - assert_eq!(i.is_low(), true); - assert_eq!(i.is_high(), false); - } - - #[test] - #[should_panic] - fn v1_v2_input_panic() { - let i: OldInputPin<_> = NewInputPinImpl{state: Err(())}.into(); - - i.is_low(); - } - -} diff --git a/src/rng.rs b/src/rng.rs deleted file mode 100644 index d662ff545..000000000 --- a/src/rng.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Random Number Generator Interface - -#[cfg(feature = "unproven")] -use nb; - -/// Nonblocking stream of random bytes. -#[cfg(feature = "unproven")] -// reason: No implementation or users yet -pub trait Read { - /// An enumeration of RNG errors. - /// - /// For infallible implementations, will be `Infallible` - type Error; - - /// Get a number of bytes from the RNG. - fn read(&mut self, buf: &mut [u8]) -> nb::Result; -} diff --git a/src/serial.rs b/src/serial.rs deleted file mode 100644 index 484bb2967..000000000 --- a/src/serial.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! Serial interface - -use nb; - -/// Read half of a serial interface -/// -/// Some serial interfaces support different data sizes (8 bits, 9 bits, etc.); -/// This can be encoded in this trait via the `Word` type parameter. -pub trait Read { - /// Read error - type Error; - - /// Reads a single word from the serial interface - fn read(&mut self) -> nb::Result; -} - -/// Write half of a serial interface -pub trait Write { - /// Write error - type Error; - - /// Writes a single word to the serial interface - fn write(&mut self, word: Word) -> nb::Result<(), Self::Error>; - - /// Ensures that none of the previously written words are still buffered - fn flush(&mut self) -> nb::Result<(), Self::Error>; -} diff --git a/src/timer.rs b/src/timer.rs deleted file mode 100644 index 78a4c4f6c..000000000 --- a/src/timer.rs +++ /dev/null @@ -1,94 +0,0 @@ -//! Timers - -use nb; -use core::convert::Infallible; - -/// A count down timer -/// -/// # Contract -/// -/// - `self.start(count); block!(self.wait());` MUST block for AT LEAST the time specified by -/// `count`. -/// -/// *Note* that the implementer doesn't necessarily have to be a *downcounting* timer; it could also -/// be an *upcounting* timer as long as the above contract is upheld. -/// -/// # Examples -/// -/// You can use this timer to create delays -/// -/// ``` -/// extern crate embedded_hal as hal; -/// #[macro_use(block)] -/// extern crate nb; -/// -/// use hal::prelude::*; -/// -/// fn main() { -/// let mut led: Led = { -/// // .. -/// # Led -/// }; -/// let mut timer: Timer6 = { -/// // .. -/// # Timer6 -/// }; -/// -/// Led.on(); -/// timer.start(1.s()); -/// block!(timer.wait()); // blocks for 1 second -/// Led.off(); -/// } -/// -/// # use std::convert::Infallible; -/// # struct Seconds(u32); -/// # trait U32Ext { fn s(self) -> Seconds; } -/// # impl U32Ext for u32 { fn s(self) -> Seconds { Seconds(self) } } -/// # struct Led; -/// # impl Led { -/// # pub fn off(&mut self) {} -/// # pub fn on(&mut self) {} -/// # } -/// # 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(()) } -/// # } -/// ``` -pub trait CountDown { - /// The unit of time used by this timer - type Time; - - /// Starts a new count down - fn start(&mut self, count: T) - where - T: Into; - - /// Non-blockingly "waits" until the count down finishes - /// - /// # Contract - /// - /// - If `Self: Periodic`, the timer will start a new count down right after the last one - /// 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>; -} - -/// Marker trait that indicates that a timer is periodic -pub trait Periodic {} - -/// Trait for cancelable countdowns. -pub trait Cancel : CountDown { - /// Error returned when a countdown can't be canceled. - type Error; - - /// Tries to cancel this countdown. - /// - /// # Errors - /// - /// An error will be returned if the countdown has already been canceled or was never started. - /// An error is also returned if the countdown is not `Periodic` and has already expired. - fn cancel(&mut self) -> Result<(), Self::Error>; -} diff --git a/src/watchdog.rs b/src/watchdog.rs deleted file mode 100644 index ee8cefc32..000000000 --- a/src/watchdog.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! Traits for interactions with a processors watchdog timer. - - - -/// Feeds an existing watchdog to ensure the processor isn't reset. Sometimes -/// commonly referred to as "kicking" or "refreshing". -#[cfg(feature = "unproven")] -pub trait Watchdog { - /// Triggers the watchdog. This must be done once the watchdog is started - /// to prevent the processor being reset. - fn feed(&mut self); -} - - -/// Enables A watchdog timer to reset the processor if software is frozen or -/// stalled. -#[cfg(feature = "unproven")] -pub trait WatchdogEnable { - /// Unit of time used by the watchdog - type Time; - /// Starts the watchdog with a given period, typically once this is done - /// the watchdog needs to be kicked periodically or the processor is reset. - fn start(&mut self, period: T) where T: Into; -} - - -/// Disables a running watchdog timer so the processor won't be reset. -#[cfg(feature = "unproven")] -pub trait WatchdogDisable { - /// Disables the watchdog - fn disable(&mut self); -} From 6c7ca9452cc96328196d4e9f352040092ee7a817 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Tue, 19 Nov 2019 22:38:16 +0000 Subject: [PATCH 02/10] Moved over more HAL stuff. Tests also now pass. --- Cargo.toml | 4 + embedded-hal-delay/Cargo.toml | 15 ++++ embedded-hal-delay/src/lib.rs | 29 +++++++ embedded-hal-i2c/Cargo.toml | 15 ++++ embedded-hal-i2c/src/lib.rs | 135 +++++++++++++++++++++++++++++++++ embedded-hal-serial/Cargo.toml | 15 ++++ embedded-hal-serial/src/lib.rs | 84 ++++++++++++++++++++ embedded-hal-spi/src/lib.rs | 113 ++++++++++++++++++++++++++- embedded-hal-timer/Cargo.toml | 15 ++++ embedded-hal-timer/src/lib.rs | 92 ++++++++++++++++++++++ embedded-hal/Cargo.toml | 17 +++++ embedded-hal/src/lib.rs | 61 ++++++++++++++- rustfmt.toml | 2 + 13 files changed, 595 insertions(+), 2 deletions(-) create mode 100644 embedded-hal-delay/Cargo.toml create mode 100644 embedded-hal-delay/src/lib.rs create mode 100644 embedded-hal-i2c/Cargo.toml create mode 100644 embedded-hal-i2c/src/lib.rs create mode 100644 embedded-hal-serial/Cargo.toml create mode 100644 embedded-hal-serial/src/lib.rs create mode 100644 embedded-hal-timer/Cargo.toml create mode 100644 embedded-hal-timer/src/lib.rs create mode 100644 rustfmt.toml diff --git a/Cargo.toml b/Cargo.toml index a95193d8a..ded5aebea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,10 @@ [workspace] members = [ "embedded-hal", + "embedded-hal-delay", "embedded-hal-digital", + "embedded-hal-i2c", + "embedded-hal-serial", "embedded-hal-spi", + "embedded-hal-timer", ] diff --git a/embedded-hal-delay/Cargo.toml b/embedded-hal-delay/Cargo.toml new file mode 100644 index 000000000..0b41f2d6a --- /dev/null +++ b/embedded-hal-delay/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "embedded-hal-delay" +version = "1.0.0-rc1" +authors = ["Rust Embedded Working Group "] +edition = "2018" +categories = ["gpio", "embedded", "hardware-support", "no-std"] +description = " A busy-waiting delay Hardware Abstraction Layer (HAL) for embedded systems " +documentation = "https://docs.rs/embedded-hal-delay" +keywords = ["hal", "delay", "busy-wait"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-embedded/embedded-hal" + +[dependencies] +nb = "0.1" diff --git a/embedded-hal-delay/src/lib.rs b/embedded-hal-delay/src/lib.rs new file mode 100644 index 000000000..9c9fd4b10 --- /dev/null +++ b/embedded-hal-delay/src/lib.rs @@ -0,0 +1,29 @@ +//! Delays +//! +//! # What's the difference between these traits and the `timer::CountDown` trait? +//! +//! The `Timer` trait provides a *non-blocking* timer abstraction and it's meant to be used to build +//! higher level abstractions like I/O operations with timeouts. OTOH, these delays traits only +//! provide *blocking* functionality. Note that you can also use the `timer::CountDown` trait to +//! implement blocking delays. + +pub mod blocking { + + /// Millisecond delay + /// + /// `UXX` denotes the range type of the delay time. `UXX` can be `u8`, `u16`, etc. A single type can + /// implement this trait for different types of `UXX`. + pub trait DelayMs { + /// Pauses execution for `ms` milliseconds + fn delay_ms(&mut self, ms: UXX); + } + + /// Microsecond delay + /// + /// `UXX` denotes the range type of the delay time. `UXX` can be `u8`, `u16`, etc. A single type can + /// implement this trait for different types of `UXX`. + pub trait DelayUs { + /// Pauses execution for `us` microseconds + fn delay_us(&mut self, us: UXX); + } +} diff --git a/embedded-hal-i2c/Cargo.toml b/embedded-hal-i2c/Cargo.toml new file mode 100644 index 000000000..baf7d4626 --- /dev/null +++ b/embedded-hal-i2c/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "embedded-hal-i2c" +version = "1.0.0-rc1" +authors = ["Rust Embedded Working Group "] +edition = "2018" +categories = ["gpio", "embedded", "hardware-support", "no-std"] +description = " A Inter-IC (I2C) Interface Hardware Abstration Layer (HAL) for embedded systems " +documentation = "https://docs.rs/embedded-hal-i2c" +keywords = ["hal", "i2c"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-embedded/embedded-hal" + +[dependencies] +nb = "0.1" diff --git a/embedded-hal-i2c/src/lib.rs b/embedded-hal-i2c/src/lib.rs new file mode 100644 index 000000000..f1750a428 --- /dev/null +++ b/embedded-hal-i2c/src/lib.rs @@ -0,0 +1,135 @@ +//! # embedded-hal-i2c +//! +//! Traits for I2C (Inter-IC) Interface Masters + +/// Blocking I2C API +/// +/// Slave addresses used by this API are 7-bit I2C addresses ranging from 0 to 127. +/// +/// Operations on 10-bit slave addresses are not supported by the API yet (but applications might +/// be able to emulate some operations). +pub mod blocking { + + /// Blocking read + pub trait Read { + /// Error type + type Error; + + /// Reads enough bytes from slave with `address` to fill `buffer` + /// + /// # I2C Events (contract) + /// + /// ``` text + /// Master: ST SAD+R MAK MAK ... NMAK SP + /// Slave: SAK B0 B1 ... BN + /// ``` + /// + /// Where + /// + /// - `ST` = start condition + /// - `SAD+R` = slave address followed by bit 1 to indicate reading + /// - `SAK` = slave acknowledge + /// - `Bi` = ith byte of data + /// - `MAK` = master acknowledge + /// - `NMAK` = master no acknowledge + /// - `SP` = stop condition + fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error>; + } + + /// Blocking write + pub trait Write { + /// Error type + type Error; + + /// Sends bytes to slave with address `addr` + /// + /// # I2C Events (contract) + /// + /// ``` text + /// Master: ST SAD+W B0 B1 ... BN SP + /// Slave: SAK SAK SAK ... SAK + /// ``` + /// + /// Where + /// + /// - `ST` = start condition + /// - `SAD+W` = slave address followed by bit 0 to indicate writing + /// - `SAK` = slave acknowledge + /// - `Bi` = ith byte of data + /// - `SP` = stop condition + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error>; + } + + /// Blocking write (iterator version) + #[cfg(feature = "unproven")] + pub trait WriteIter { + /// Error type + type Error; + + /// Sends bytes to slave with address `addr` + /// + /// # I2C Events (contract) + /// + /// Same as `Write` + fn write(&mut self, addr: u8, bytes: B) -> Result<(), Self::Error> + where + B: IntoIterator; + } + + /// Blocking write + read + pub trait WriteRead { + /// Error type + type Error; + + /// Sends bytes to slave with address `addr` and then reads enough bytes to fill `buffer` *in a + /// single transaction* + /// + /// # I2C Events (contract) + /// + /// ``` text + /// Master: ST SAD+W O0 O1 ... OM SR SAD+R MAK MAK ... NMAK SP + /// Slave: SAK SAK SAK ... SAK SAK I0 I1 ... IN + /// ``` + /// + /// Where + /// + /// - `ST` = start condition + /// - `SAD+W` = slave address followed by bit 0 to indicate writing + /// - `SAK` = slave acknowledge + /// - `Oi` = ith outgoing byte of data + /// - `SR` = repeated start condition + /// - `SAD+R` = slave address followed by bit 1 to indicate reading + /// - `Ii` = ith incoming byte of data + /// - `MAK` = master acknowledge + /// - `NMAK` = master no acknowledge + /// - `SP` = stop condition + fn write_read( + &mut self, + address: u8, + bytes: &[u8], + buffer: &mut [u8], + ) -> Result<(), Self::Error>; + } + + /// Blocking write (iterator version) + read + #[cfg(feature = "unproven")] + pub trait WriteIterRead { + /// Error type + type Error; + + /// Sends bytes to slave with address `addr` and then reads enough bytes to fill `buffer` *in a + /// single transaction* + /// + /// # I2C Events (contract) + /// + /// Same as the `WriteRead` trait + fn write_iter_read( + &mut self, + address: u8, + bytes: B, + buffer: &mut [u8], + ) -> Result<(), Self::Error> + where + B: IntoIterator; + } +} diff --git a/embedded-hal-serial/Cargo.toml b/embedded-hal-serial/Cargo.toml new file mode 100644 index 000000000..0f2c34c53 --- /dev/null +++ b/embedded-hal-serial/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "embedded-hal-serial" +version = "1.0.0-rc1" +authors = ["Rust Embedded Working Group "] +edition = "2018" +categories = ["gpio", "embedded", "hardware-support", "no-std"] +description = " A Serial/UART Hardware Abstraction Layer (HAL) for embedded systems " +documentation = "https://docs.rs/embedded-hal-serial" +keywords = ["hal", "serial"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-embedded/embedded-hal" + +[dependencies] +nb = "0.1" diff --git a/embedded-hal-serial/src/lib.rs b/embedded-hal-serial/src/lib.rs new file mode 100644 index 000000000..e2ac4b390 --- /dev/null +++ b/embedded-hal-serial/src/lib.rs @@ -0,0 +1,84 @@ +//! Serial interface + +/// Read half of a serial interface +/// +/// Some serial interfaces support different data sizes (8 bits, 9 bits, etc.); +/// This can be encoded in this trait via the `Word` type parameter. +pub trait Read { + /// Read error + type Error; + + /// Reads a single word from the serial interface + fn read(&mut self) -> nb::Result; +} + +/// Write half of a serial interface +pub trait Write { + /// Write error + type Error; + + /// Writes a single word to the serial interface + fn write(&mut self, word: Word) -> nb::Result<(), Self::Error>; + + /// Ensures that none of the previously written words are still buffered + fn flush(&mut self) -> nb::Result<(), Self::Error>; +} + +/// Blocking serial API +pub mod blocking { + + /// Write half of a serial interface (blocking variant) + pub trait Write { + /// The type of error that can occur when writing + type Error; + + /// Writes a slice, blocking until everything has been written + /// + /// An implementation can choose to buffer the write, returning `Ok(())` + /// after the complete slice has been written to a buffer, but before all + /// words have been sent via the serial interface. To make sure that + /// everything has been sent, call [`bflush`] after this function returns. + /// + /// [`bflush`]: #tymethod.bflush + fn bwrite_all(&mut self, buffer: &[Word]) -> Result<(), Self::Error>; + + /// Block until the serial interface has sent all buffered words + fn bflush(&mut self) -> Result<(), Self::Error>; + } + + /// Blocking serial write + pub mod write { + /// Marker trait to opt into default blocking write implementation + /// + /// Implementers of [`crate::Write`] can implement this marker trait + /// for their type. Doing so will automatically provide the default + /// implementation of [`blocking::Write`] for the type. + /// + /// [`crate::Write`]: ../../serial/trait.Write.html + /// [`blocking::Write`]: ../trait.Write.html + pub trait Default: crate::Write {} + + impl crate::blocking::Write for S + where + S: Default, + Word: Clone, + { + type Error = S::Error; + + fn bwrite_all(&mut self, buffer: &[Word]) -> Result<(), Self::Error> { + use nb::block; + for word in buffer { + block!(self.write(word.clone()))?; + } + + Ok(()) + } + + fn bflush(&mut self) -> Result<(), Self::Error> { + use nb::block; + block!(self.flush())?; + Ok(()) + } + } + } +} diff --git a/embedded-hal-spi/src/lib.rs b/embedded-hal-spi/src/lib.rs index b91e6d68b..c3479502d 100644 --- a/embedded-hal-spi/src/lib.rs +++ b/embedded-hal-spi/src/lib.rs @@ -75,4 +75,115 @@ pub const MODE_2: Mode = Mode { pub const MODE_3: Mode = Mode { polarity: Polarity::IdleHigh, phase: Phase::CaptureOnSecondTransition, -}; \ No newline at end of file +}; + +/// Blocking traits +pub mod blocking { + //! Blocking SPI API + + /// Blocking transfer + pub trait Transfer { + /// Error type + type Error; + + /// Sends `words` to the slave. Returns the `words` received from the slave + fn transfer<'w>(&mut self, words: &'w mut [W]) -> Result<&'w [W], Self::Error>; + } + + /// Blocking write + pub trait Write { + /// Error type + type Error; + + /// Sends `words` to the slave, ignoring all the incoming words + fn write(&mut self, words: &[W]) -> Result<(), Self::Error>; + } + + /// Blocking write (iterator version) + pub trait WriteIter { + /// Error type + type Error; + + /// Sends `words` to the slave, ignoring all the incoming words + fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> + where + WI: IntoIterator; + } + + /// Blocking transfer + pub mod transfer { + /// Default implementation of `blocking::Transfer` for implementers of + /// `spi::FullDuplex` + pub trait Default: crate::FullDuplex {} + + impl crate::blocking::Transfer for S + where + S: Default, + W: Clone, + { + type Error = S::Error; + + fn transfer<'w>(&mut self, words: &'w mut [W]) -> Result<&'w [W], S::Error> { + use nb::block; + for word in words.iter_mut() { + block!(self.send(word.clone()))?; + *word = block!(self.read())?; + } + + Ok(words) + } + } + } + + /// Blocking write + pub mod write { + /// Default implementation of `blocking::Write` for implementers of `spi::FullDuplex` + pub trait Default: crate::FullDuplex {} + + impl crate::blocking::Write for S + where + S: Default, + W: Clone, + { + type Error = S::Error; + + fn write(&mut self, words: &[W]) -> Result<(), S::Error> { + use nb::block; + for word in words { + block!(self.send(word.clone()))?; + block!(self.read())?; + } + + Ok(()) + } + } + } + + /// Blocking write (iterator version) + pub mod write_iter { + /// Default implementation of `blocking::WriteIter` for implementers of + /// `spi::FullDuplex` + pub trait Default: crate::FullDuplex {} + + impl crate::blocking::WriteIter for S + where + S: Default, + W: Clone, + { + type Error = S::Error; + + fn write_iter(&mut self, words: WI) -> Result<(), S::Error> + where + WI: IntoIterator, + { + use nb::block; + for word in words.into_iter() { + block!(self.send(word.clone()))?; + block!(self.read())?; + } + + Ok(()) + } + } + } +} diff --git a/embedded-hal-timer/Cargo.toml b/embedded-hal-timer/Cargo.toml new file mode 100644 index 000000000..6b3d4cc9f --- /dev/null +++ b/embedded-hal-timer/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "embedded-hal-timer" +version = "1.0.0-rc1" +authors = ["Rust Embedded Working Group "] +edition = "2018" +categories = ["gpio", "embedded", "hardware-support", "no-std"] +description = " A Timer Hardware Abstraction Layer (HAL) for embedded systems " +documentation = "https://docs.rs/embedded-hal-timer" +keywords = ["hal", "timer"] +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/rust-embedded/embedded-hal" + +[dependencies] +nb = "0.1" diff --git a/embedded-hal-timer/src/lib.rs b/embedded-hal-timer/src/lib.rs new file mode 100644 index 000000000..71b3b734c --- /dev/null +++ b/embedded-hal-timer/src/lib.rs @@ -0,0 +1,92 @@ +//! Timers + +use core::convert::Infallible; +use nb; + +/// A count down timer +/// +/// # Contract +/// +/// - `self.start(count); block!(self.wait());` MUST block for AT LEAST the time specified by +/// `count`. +/// +/// *Note* that the implementer doesn't necessarily have to be a *downcounting* timer; it could also +/// be an *upcounting* timer as long as the above contract is upheld. +/// +/// # Examples +/// +/// You can use this timer to create delays +/// +/// ``` +/// use embedded_hal_timer as hal; +/// use nb::block; +/// use hal::CountDown; +/// +/// fn main() { +/// let mut led: Led = { +/// // .. +/// # Led +/// }; +/// let mut timer: Timer6 = { +/// // .. +/// # Timer6 +/// }; +/// +/// Led.on(); +/// timer.start(1.s()); +/// block!(timer.wait()); // blocks for 1 second +/// Led.off(); +/// } +/// +/// # use std::convert::Infallible; +/// # struct Seconds(u32); +/// # trait U32Ext { fn s(self) -> Seconds; } +/// # impl U32Ext for u32 { fn s(self) -> Seconds { Seconds(self) } } +/// # struct Led; +/// # impl Led { +/// # pub fn off(&mut self) {} +/// # pub fn on(&mut self) {} +/// # } +/// # struct Timer6; +/// # impl hal::CountDown for Timer6 { +/// # type Time = Seconds; +/// # fn start(&mut self, _: T) where T: Into {} +/// # fn wait(&mut self) -> ::nb::Result<(), Infallible> { Ok(()) } +/// # } +/// ``` +pub trait CountDown { + /// The unit of time used by this timer + type Time; + + /// Starts a new count down + fn start(&mut self, count: T) + where + T: Into; + + /// Non-blockingly "waits" until the count down finishes + /// + /// # Contract + /// + /// - If `Self: Periodic`, the timer will start a new count down right after the last one + /// 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>; +} + +/// Marker trait that indicates that a timer is periodic +pub trait Periodic {} + +/// Trait for cancelable countdowns. +pub trait Cancel: CountDown { + /// Error returned when a countdown can't be canceled. + type Error; + + /// Tries to cancel this countdown. + /// + /// # Errors + /// + /// An error will be returned if the countdown has already been canceled or was never started. + /// An error is also returned if the countdown is not `Periodic` and has already expired. + fn cancel(&mut self) -> Result<(), Self::Error>; +} diff --git a/embedded-hal/Cargo.toml b/embedded-hal/Cargo.toml index 15e0d3b71..a1976fd17 100644 --- a/embedded-hal/Cargo.toml +++ b/embedded-hal/Cargo.toml @@ -11,10 +11,27 @@ license = "MIT OR Apache-2.0" readme = "README.md" repository = "https://github.com/rust-embedded/embedded-hal" +[dependencies.embedded-hal-delay] +path = "../embedded-hal-delay" +# version = "1.0" + [dependencies.embedded-hal-digital] path = "../embedded-hal-digital" # version = "1.0" +[dependencies.embedded-hal-i2c] +path = "../embedded-hal-i2c" +# version = "1.0" + +[dependencies.embedded-hal-serial] +path = "../embedded-hal-serial" +# version = "1.0" + [dependencies.embedded-hal-spi] path = "../embedded-hal-spi" # version = "1.0" + +[dependencies.embedded-hal-timer] +path = "../embedded-hal-timer" +# version = "1.0" + diff --git a/embedded-hal/src/lib.rs b/embedded-hal/src/lib.rs index 7a0176fca..73548f1b7 100644 --- a/embedded-hal/src/lib.rs +++ b/embedded-hal/src/lib.rs @@ -2,10 +2,69 @@ //! //! See README.md. +/// A collection of items we expect most people to want to have in scope. +/// +/// We re-name items imported here to avoid collisions with any local items +/// users may have. +pub mod prelude { + pub use crate::blocking::delay::DelayMs as _embedded_hal_blocking_delay_DelayMs; + pub use crate::blocking::delay::DelayUs as _embedded_hal_blocking_delay_DelayUs; + pub use crate::blocking::i2c::{ + Read as _embedded_hal_blocking_i2c_Read, Write as _embedded_hal_blocking_i2c_Write, + WriteRead as _embedded_hal_blocking_i2c_WriteRead, + }; + pub use crate::blocking::serial::Write as _embedded_hal_blocking_serial_Write; + pub use crate::blocking::spi::{ + Transfer as _embedded_hal_blocking_spi_Transfer, Write as _embedded_hal_blocking_spi_Write, + }; + pub use crate::digital::InputPin as _embedded_hal_digital_InputPin; + pub use crate::digital::OutputPin as _embedded_hal_digital_OutputPin; + pub use crate::serial::Read as _embedded_hal_serial_Read; + pub use crate::serial::Write as _embedded_hal_serial_Write; + pub use crate::spi::FullDuplex as _embedded_hal_spi_FullDuplex; + pub use crate::timer::CountDown as _embedded_hal_timer_CountDown; +} + +/// A sub-set of traits which can block until the specific work is done. Blocking is usually +/// performed by busy-waiting, so this may not be ideal in a performance-sensitive system. +pub mod blocking { + pub mod delay { + pub use embedded_hal_delay::blocking::{DelayMs, DelayUs}; + } + + pub mod i2c { + pub use embedded_hal_i2c::blocking::{Read, Write, WriteRead}; + } + + pub mod serial { + pub use embedded_hal_serial::blocking::Write; + } + + pub mod spi { + pub use embedded_hal_spi::blocking::{Transfer, Write}; + } +} + +/// Traits for digital I/O pins. pub mod digital { pub use embedded_hal_digital::{InputPin, OutputPin, StatefulOutputPin}; } +/// Traits for hardware which implements the Serial Peripheral Interface as a +/// master. pub mod spi { - pub use embedded_hal_spi::{FullDuplex, Polarity, Phase, Mode, MODE_0, MODE_1, MODE_2, MODE_3}; + pub use embedded_hal_spi::{FullDuplex, Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; +} + +/// Traits for devices which can transmit and/or receive data one 'word' at a +/// time. Typically these are Universal Asynchronous Receiver/Transmitters +/// (UARTs). +pub mod serial { + pub use embedded_hal_serial::{Read, Write}; +} + +/// Traits for timers - objects that count time and raise interrupts at +/// specific times. +pub mod timer { + pub use embedded_hal_timer::CountDown; } diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 000000000..3fcde5a2d --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +hard_tabs = false + From df45f83ad3021688f86c7fe7f09dd3baed1b8a9c Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Tue, 19 Nov 2019 22:40:36 +0000 Subject: [PATCH 03/10] Fixup CI. --- ci/install.sh | 1 + ci/script.sh | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ci/install.sh b/ci/install.sh index 3c4192119..1243fd15d 100644 --- a/ci/install.sh +++ b/ci/install.sh @@ -4,6 +4,7 @@ main() { if [ $TARGET != x86_64-unknown-linux-gnu ]; then rustup target add $TARGET fi + rustup component add rustfmt } main diff --git a/ci/script.sh b/ci/script.sh index 12c05e27b..a115d519f 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -2,11 +2,8 @@ set -euxo pipefail main() { cargo check --target $TARGET - cargo check --target $TARGET --features unproven - - if [ $TRAVIS_RUST_VERSION = nightly ]; then - cargo test --target $TARGET --features unproven - fi + cargo test --target $TARGET + cargo fmt -- --check } main From 32dc627d10f3b6c9ddf34ffa55ae7239513e5915 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Tue, 19 Nov 2019 22:56:38 +0000 Subject: [PATCH 04/10] Make crates #![no_std] --- embedded-hal-delay/src/lib.rs | 4 ++++ embedded-hal-digital/src/lib.rs | 3 +++ embedded-hal-i2c/src/lib.rs | 3 +++ embedded-hal-serial/src/lib.rs | 3 +++ embedded-hal-spi/src/lib.rs | 3 +++ embedded-hal-timer/src/lib.rs | 3 +++ embedded-hal/src/lib.rs | 7 +++++++ 7 files changed, 26 insertions(+) diff --git a/embedded-hal-delay/src/lib.rs b/embedded-hal-delay/src/lib.rs index 9c9fd4b10..23a9bb5bd 100644 --- a/embedded-hal-delay/src/lib.rs +++ b/embedded-hal-delay/src/lib.rs @@ -7,6 +7,10 @@ //! provide *blocking* functionality. Note that you can also use the `timer::CountDown` trait to //! implement blocking delays. +#![deny(missing_docs)] +#![no_std] + +/// Blocking traits pub mod blocking { /// Millisecond delay diff --git a/embedded-hal-digital/src/lib.rs b/embedded-hal-digital/src/lib.rs index 1c229ab08..bd8695653 100644 --- a/embedded-hal-digital/src/lib.rs +++ b/embedded-hal-digital/src/lib.rs @@ -4,6 +4,9 @@ //! [`embedded-hal`](https://crates.io/crates/embedded-hal) crate if you want //! a stable version. +#![deny(missing_docs)] +#![no_std] + /// Single digital push-pull output pin pub trait OutputPin { /// Error type diff --git a/embedded-hal-i2c/src/lib.rs b/embedded-hal-i2c/src/lib.rs index f1750a428..0ea2ed330 100644 --- a/embedded-hal-i2c/src/lib.rs +++ b/embedded-hal-i2c/src/lib.rs @@ -2,6 +2,9 @@ //! //! Traits for I2C (Inter-IC) Interface Masters +#![deny(missing_docs)] +#![no_std] + /// Blocking I2C API /// /// Slave addresses used by this API are 7-bit I2C addresses ranging from 0 to 127. diff --git a/embedded-hal-serial/src/lib.rs b/embedded-hal-serial/src/lib.rs index e2ac4b390..c3fd11886 100644 --- a/embedded-hal-serial/src/lib.rs +++ b/embedded-hal-serial/src/lib.rs @@ -1,5 +1,8 @@ //! Serial interface +#![deny(missing_docs)] +#![no_std] + /// Read half of a serial interface /// /// Some serial interfaces support different data sizes (8 bits, 9 bits, etc.); diff --git a/embedded-hal-spi/src/lib.rs b/embedded-hal-spi/src/lib.rs index c3479502d..a93a63225 100644 --- a/embedded-hal-spi/src/lib.rs +++ b/embedded-hal-spi/src/lib.rs @@ -1,5 +1,8 @@ //! Serial Peripheral Interface +#![deny(missing_docs)] +#![no_std] + use nb; /// Full duplex (master mode) diff --git a/embedded-hal-timer/src/lib.rs b/embedded-hal-timer/src/lib.rs index 71b3b734c..fc1aed9c1 100644 --- a/embedded-hal-timer/src/lib.rs +++ b/embedded-hal-timer/src/lib.rs @@ -1,5 +1,8 @@ //! Timers +#![deny(missing_docs)] +#![no_std] + use core::convert::Infallible; use nb; diff --git a/embedded-hal/src/lib.rs b/embedded-hal/src/lib.rs index 73548f1b7..3679d3a86 100644 --- a/embedded-hal/src/lib.rs +++ b/embedded-hal/src/lib.rs @@ -2,6 +2,9 @@ //! //! See README.md. +#![deny(missing_docs)] +#![no_std] + /// A collection of items we expect most people to want to have in scope. /// /// We re-name items imported here to avoid collisions with any local items @@ -28,18 +31,22 @@ pub mod prelude { /// A sub-set of traits which can block until the specific work is done. Blocking is usually /// performed by busy-waiting, so this may not be ideal in a performance-sensitive system. pub mod blocking { + /// Busy-waiting for fixed time periods pub mod delay { pub use embedded_hal_delay::blocking::{DelayMs, DelayUs}; } + /// Busy-waiting I2C transactions pub mod i2c { pub use embedded_hal_i2c::blocking::{Read, Write, WriteRead}; } + /// Busy-waiting serial transactions pub mod serial { pub use embedded_hal_serial::blocking::Write; } + /// Busy-waiting SPI transactions pub mod spi { pub use embedded_hal_spi::blocking::{Transfer, Write}; } From 38c8deb1287e9a8ea3666c6d54909491a7c52100 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sun, 24 Nov 2019 15:55:51 +0000 Subject: [PATCH 05/10] Sorting out READMEs. --- embedded-hal-delay/README.md | 91 +++++++++++++++++++++++++++++++++ embedded-hal-digital/README.md | 92 ++++++++++++++++++++++++++++++++++ embedded-hal-i2c/README.md | 92 ++++++++++++++++++++++++++++++++++ embedded-hal-serial/README.md | 92 ++++++++++++++++++++++++++++++++++ embedded-hal-spi/README.md | 92 ++++++++++++++++++++++++++++++++++ embedded-hal-timer/README.md | 91 +++++++++++++++++++++++++++++++++ embedded-hal/README.md | 91 ++++++++++++++++++++------------- 7 files changed, 607 insertions(+), 34 deletions(-) create mode 100644 embedded-hal-delay/README.md create mode 100644 embedded-hal-digital/README.md create mode 100644 embedded-hal-i2c/README.md create mode 100644 embedded-hal-serial/README.md create mode 100644 embedded-hal-spi/README.md create mode 100644 embedded-hal-timer/README.md diff --git a/embedded-hal-delay/README.md b/embedded-hal-delay/README.md new file mode 100644 index 000000000..0e753596d --- /dev/null +++ b/embedded-hal-delay/README.md @@ -0,0 +1,91 @@ +# `embedded-hal-delay` + +> A Hardware Abstraction Layer (HAL) for busy-waiting on embedded systems + +This project is developed and maintained by the [HAL team][team]. This crate may contain unstable functionality - the stable API is exposed in the [`embedded-hal`](https://crates.io/crates/embedded-hal) crate. + +## [API reference] + +[API reference]: https://docs.rs/embedded-hal-delay + +## How-to: add a new trait + +This is the suggested approach to adding a new trait to `embedded-hal-delay` + +### Discussion + +Ideally, before proposing a new trait, or set of traits, you should create an +issue where the use cases and requirements of the trait(s) are discussed. + +These issues will be labeled as `discussion`s in the issue tracker. + +### Proposing a trait + +Once there's consensus on the requirements of the trait(s) a new issue, or a +PR, with a proposal should be opened. The proposal should include the actual +trait definitions as well as a link to the issue with previous discussion, if +there was one. + +If the proposal includes more than one alternative then there should be +further discussion to try to single out the best alternative. + +These issues / PRs will be labeled as `proposal`s in the issue tracker. + +### Testing period + +If there are no objections to the proposal the new trait(s) will land in this +crate and an issue about the new trait(s) will be created. If the proposal +includes several alternatives and a single one couldn't be chosen as the best +then each alternative will land behind a different Cargo feature, e.g. "alt1" +or "alt2". + +The traits will undergo a testing period before they are exported from the +top-level `embedded-hal` crate. During this period users are encouraged to try +to implement the unproven traits for their platforms and to build drivers on +top of them. Problems implementing the trait(s) as well as successful +implementations should be reported on the corresponding issue. + +To leave the unproven state at least *two* implementations of the trait(s) for +different platforms (ideally, the two platforms should be from different +vendors) and *one* generic driver built on top of the trait(s), or +alternatively one demo program that exercises the trait (via generic function +/ trait object), *should* be demonstrated. If, instead, reports indicate that +the proposed trait(s) can't be implemented for a certain platform then the +trait(s) will be removed and we'll go back to the drawing board. + +Issues used to track unproven APIs will be labeled as `unproven-api`s in the +issue tracker and they may also include the labels `needs-impl` and +`needs-driver` to signal what's required for them to move to the set of proven +traits. + +## Implementations and drivers + +For a list of `embedded-hal` implementations and driver crates check the +[awesome-embedded-rust] list. + +[awesome-embedded-rust]: https://github.com/rust-embedded/awesome-embedded-rust#driver-crates + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +## Code of Conduct + +Contribution to this crate is organized under the terms of the [Rust Code of +Conduct][CoC], the maintainer of this crate, the [HAL team][team], promises to +intervene to uphold that code of conduct. + +[CoC]: CODE_OF_CONDUCT.md +[team]: https://github.com/rust-embedded/wg#the-hal-team diff --git a/embedded-hal-digital/README.md b/embedded-hal-digital/README.md new file mode 100644 index 000000000..cd9783a19 --- /dev/null +++ b/embedded-hal-digital/README.md @@ -0,0 +1,92 @@ +# `embedded-hal-digital` + +> A Hardware Abstraction Layer (HAL) for driving a General-Purpose +> Input/Output (GPIO) peripheral on embedded systems + +This project is developed and maintained by the [HAL team][team]. This crate may contain unstable functionality - the stable API is exposed in the [`embedded-hal`](https://crates.io/crates/embedded-hal) crate. + +## [API reference] + +[API reference]: https://docs.rs/embedded-hal-digital + +## How-to: add a new trait + +This is the suggested approach to adding a new trait to `embedded-hal-digital` + +### Discussion + +Ideally, before proposing a new trait, or set of traits, you should create an +issue where the use cases and requirements of the trait(s) are discussed. + +These issues will be labeled as `discussion`s in the issue tracker. + +### Proposing a trait + +Once there's consensus on the requirements of the trait(s) a new issue, or a +PR, with a proposal should be opened. The proposal should include the actual +trait definitions as well as a link to the issue with previous discussion, if +there was one. + +If the proposal includes more than one alternative then there should be +further discussion to try to single out the best alternative. + +These issues / PRs will be labeled as `proposal`s in the issue tracker. + +### Testing period + +If there are no objections to the proposal the new trait(s) will land in this +crate and an issue about the new trait(s) will be created. If the proposal +includes several alternatives and a single one couldn't be chosen as the best +then each alternative will land behind a different Cargo feature, e.g. "alt1" +or "alt2". + +The traits will undergo a testing period before they are exported from the +top-level `embedded-hal` crate. During this period users are encouraged to try +to implement the unproven traits for their platforms and to build drivers on +top of them. Problems implementing the trait(s) as well as successful +implementations should be reported on the corresponding issue. + +To leave the unproven state at least *two* implementations of the trait(s) for +different platforms (ideally, the two platforms should be from different +vendors) and *one* generic driver built on top of the trait(s), or +alternatively one demo program that exercises the trait (via generic function +/ trait object), *should* be demonstrated. If, instead, reports indicate that +the proposed trait(s) can't be implemented for a certain platform then the +trait(s) will be removed and we'll go back to the drawing board. + +Issues used to track unproven APIs will be labeled as `unproven-api`s in the +issue tracker and they may also include the labels `needs-impl` and +`needs-driver` to signal what's required for them to move to the set of proven +traits. + +## Implementations and drivers + +For a list of `embedded-hal` implementations and driver crates check the +[awesome-embedded-rust] list. + +[awesome-embedded-rust]: https://github.com/rust-embedded/awesome-embedded-rust#driver-crates + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +## Code of Conduct + +Contribution to this crate is organized under the terms of the [Rust Code of +Conduct][CoC], the maintainer of this crate, the [HAL team][team], promises to +intervene to uphold that code of conduct. + +[CoC]: CODE_OF_CONDUCT.md +[team]: https://github.com/rust-embedded/wg#the-hal-team diff --git a/embedded-hal-i2c/README.md b/embedded-hal-i2c/README.md new file mode 100644 index 000000000..da17c775e --- /dev/null +++ b/embedded-hal-i2c/README.md @@ -0,0 +1,92 @@ +# `embedded-hal-i2c` + +> A Hardware Abstraction Layer (HAL) for driving an Inter-Integrated Circuit +> (I2C) bus peripheral on embedded systems + +This project is developed and maintained by the [HAL team][team]. This crate may contain unstable functionality - the stable API is exposed in the [`embedded-hal`](https://crates.io/crates/embedded-hal) crate. + +## [API reference] + +[API reference]: https://docs.rs/embedded-hal-i2c + +## How-to: add a new trait + +This is the suggested approach to adding a new trait to `embedded-hal-i2c` + +### Discussion + +Ideally, before proposing a new trait, or set of traits, you should create an +issue where the use cases and requirements of the trait(s) are discussed. + +These issues will be labeled as `discussion`s in the issue tracker. + +### Proposing a trait + +Once there's consensus on the requirements of the trait(s) a new issue, or a +PR, with a proposal should be opened. The proposal should include the actual +trait definitions as well as a link to the issue with previous discussion, if +there was one. + +If the proposal includes more than one alternative then there should be +further discussion to try to single out the best alternative. + +These issues / PRs will be labeled as `proposal`s in the issue tracker. + +### Testing period + +If there are no objections to the proposal the new trait(s) will land in this +crate and an issue about the new trait(s) will be created. If the proposal +includes several alternatives and a single one couldn't be chosen as the best +then each alternative will land behind a different Cargo feature, e.g. "alt1" +or "alt2". + +The traits will undergo a testing period before they are exported from the +top-level `embedded-hal` crate. During this period users are encouraged to try +to implement the unproven traits for their platforms and to build drivers on +top of them. Problems implementing the trait(s) as well as successful +implementations should be reported on the corresponding issue. + +To leave the unproven state at least *two* implementations of the trait(s) for +different platforms (ideally, the two platforms should be from different +vendors) and *one* generic driver built on top of the trait(s), or +alternatively one demo program that exercises the trait (via generic function +/ trait object), *should* be demonstrated. If, instead, reports indicate that +the proposed trait(s) can't be implemented for a certain platform then the +trait(s) will be removed and we'll go back to the drawing board. + +Issues used to track unproven APIs will be labeled as `unproven-api`s in the +issue tracker and they may also include the labels `needs-impl` and +`needs-driver` to signal what's required for them to move to the set of proven +traits. + +## Implementations and drivers + +For a list of `embedded-hal` implementations and driver crates check the +[awesome-embedded-rust] list. + +[awesome-embedded-rust]: https://github.com/rust-embedded/awesome-embedded-rust#driver-crates + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +## Code of Conduct + +Contribution to this crate is organized under the terms of the [Rust Code of +Conduct][CoC], the maintainer of this crate, the [HAL team][team], promises to +intervene to uphold that code of conduct. + +[CoC]: CODE_OF_CONDUCT.md +[team]: https://github.com/rust-embedded/wg#the-hal-team diff --git a/embedded-hal-serial/README.md b/embedded-hal-serial/README.md new file mode 100644 index 000000000..3a41b983b --- /dev/null +++ b/embedded-hal-serial/README.md @@ -0,0 +1,92 @@ +# `embedded-hal-serial` + +> A Hardware Abstraction Layer (HAL) for driving a Universal Asynchronous +> Receiver/Transmitter (UART) peripheral on embedded systems + +This project is developed and maintained by the [HAL team][team]. This crate may contain unstable functionality - the stable API is exposed in the [`embedded-hal`](https://crates.io/crates/embedded-hal) crate. + +## [API reference] + +[API reference]: https://docs.rs/embedded-hal-serial + +## How-to: add a new trait + +This is the suggested approach to adding a new trait to `embedded-hal-serial` + +### Discussion + +Ideally, before proposing a new trait, or set of traits, you should create an +issue where the use cases and requirements of the trait(s) are discussed. + +These issues will be labeled as `discussion`s in the issue tracker. + +### Proposing a trait + +Once there's consensus on the requirements of the trait(s) a new issue, or a +PR, with a proposal should be opened. The proposal should include the actual +trait definitions as well as a link to the issue with previous discussion, if +there was one. + +If the proposal includes more than one alternative then there should be +further discussion to try to single out the best alternative. + +These issues / PRs will be labeled as `proposal`s in the issue tracker. + +### Testing period + +If there are no objections to the proposal the new trait(s) will land in this +crate and an issue about the new trait(s) will be created. If the proposal +includes several alternatives and a single one couldn't be chosen as the best +then each alternative will land behind a different Cargo feature, e.g. "alt1" +or "alt2". + +The traits will undergo a testing period before they are exported from the +top-level `embedded-hal` crate. During this period users are encouraged to try +to implement the unproven traits for their platforms and to build drivers on +top of them. Problems implementing the trait(s) as well as successful +implementations should be reported on the corresponding issue. + +To leave the unproven state at least *two* implementations of the trait(s) for +different platforms (ideally, the two platforms should be from different +vendors) and *one* generic driver built on top of the trait(s), or +alternatively one demo program that exercises the trait (via generic function +/ trait object), *should* be demonstrated. If, instead, reports indicate that +the proposed trait(s) can't be implemented for a certain platform then the +trait(s) will be removed and we'll go back to the drawing board. + +Issues used to track unproven APIs will be labeled as `unproven-api`s in the +issue tracker and they may also include the labels `needs-impl` and +`needs-driver` to signal what's required for them to move to the set of proven +traits. + +## Implementations and drivers + +For a list of `embedded-hal` implementations and driver crates check the +[awesome-embedded-rust] list. + +[awesome-embedded-rust]: https://github.com/rust-embedded/awesome-embedded-rust#driver-crates + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +## Code of Conduct + +Contribution to this crate is organized under the terms of the [Rust Code of +Conduct][CoC], the maintainer of this crate, the [HAL team][team], promises to +intervene to uphold that code of conduct. + +[CoC]: CODE_OF_CONDUCT.md +[team]: https://github.com/rust-embedded/wg#the-hal-team diff --git a/embedded-hal-spi/README.md b/embedded-hal-spi/README.md new file mode 100644 index 000000000..e81fa00d1 --- /dev/null +++ b/embedded-hal-spi/README.md @@ -0,0 +1,92 @@ +# `embedded-hal-spi` + +> A Hardware Abstraction Layer (HAL) for driving a Serial Peripheral +> Interface (SPI) bus on embedded systems + +This project is developed and maintained by the [HAL team][team]. This crate may contain unstable functionality - the stable API is exposed in the [`embedded-hal`](https://crates.io/crates/embedded-hal) crate. + +## [API reference] + +[API reference]: https://docs.rs/embedded-hal-spi + +## How-to: add a new trait + +This is the suggested approach to adding a new trait to `embedded-hal-spi` + +### Discussion + +Ideally, before proposing a new trait, or set of traits, you should create an +issue where the use cases and requirements of the trait(s) are discussed. + +These issues will be labeled as `discussion`s in the issue tracker. + +### Proposing a trait + +Once there's consensus on the requirements of the trait(s) a new issue, or a +PR, with a proposal should be opened. The proposal should include the actual +trait definitions as well as a link to the issue with previous discussion, if +there was one. + +If the proposal includes more than one alternative then there should be +further discussion to try to single out the best alternative. + +These issues / PRs will be labeled as `proposal`s in the issue tracker. + +### Testing period + +If there are no objections to the proposal the new trait(s) will land in this +crate and an issue about the new trait(s) will be created. If the proposal +includes several alternatives and a single one couldn't be chosen as the best +then each alternative will land behind a different Cargo feature, e.g. "alt1" +or "alt2". + +The traits will undergo a testing period before they are exported from the +top-level `embedded-hal` crate. During this period users are encouraged to try +to implement the unproven traits for their platforms and to build drivers on +top of them. Problems implementing the trait(s) as well as successful +implementations should be reported on the corresponding issue. + +To leave the unproven state at least *two* implementations of the trait(s) for +different platforms (ideally, the two platforms should be from different +vendors) and *one* generic driver built on top of the trait(s), or +alternatively one demo program that exercises the trait (via generic function +/ trait object), *should* be demonstrated. If, instead, reports indicate that +the proposed trait(s) can't be implemented for a certain platform then the +trait(s) will be removed and we'll go back to the drawing board. + +Issues used to track unproven APIs will be labeled as `unproven-api`s in the +issue tracker and they may also include the labels `needs-impl` and +`needs-driver` to signal what's required for them to move to the set of proven +traits. + +## Implementations and drivers + +For a list of `embedded-hal` implementations and driver crates check the +[awesome-embedded-rust] list. + +[awesome-embedded-rust]: https://github.com/rust-embedded/awesome-embedded-rust#driver-crates + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +## Code of Conduct + +Contribution to this crate is organized under the terms of the [Rust Code of +Conduct][CoC], the maintainer of this crate, the [HAL team][team], promises to +intervene to uphold that code of conduct. + +[CoC]: CODE_OF_CONDUCT.md +[team]: https://github.com/rust-embedded/wg#the-hal-team diff --git a/embedded-hal-timer/README.md b/embedded-hal-timer/README.md new file mode 100644 index 000000000..9fa32101f --- /dev/null +++ b/embedded-hal-timer/README.md @@ -0,0 +1,91 @@ +# `embedded-hal-timer` + +> A Hardware Abstraction Layer (HAL) for measuring elapsed time on embedded systems + +This project is developed and maintained by the [HAL team][team]. This crate may contain unstable functionality - the stable API is exposed in the [`embedded-hal`](https://crates.io/crates/embedded-hal) crate. + +## [API reference] + +[API reference]: https://docs.rs/embedded-hal-timer + +## How-to: add a new trait + +This is the suggested approach to adding a new trait to `embedded-hal-timer` + +### Discussion + +Ideally, before proposing a new trait, or set of traits, you should create an +issue where the use cases and requirements of the trait(s) are discussed. + +These issues will be labeled as `discussion`s in the issue tracker. + +### Proposing a trait + +Once there's consensus on the requirements of the trait(s) a new issue, or a +PR, with a proposal should be opened. The proposal should include the actual +trait definitions as well as a link to the issue with previous discussion, if +there was one. + +If the proposal includes more than one alternative then there should be +further discussion to try to single out the best alternative. + +These issues / PRs will be labeled as `proposal`s in the issue tracker. + +### Testing period + +If there are no objections to the proposal the new trait(s) will land in this +crate and an issue about the new trait(s) will be created. If the proposal +includes several alternatives and a single one couldn't be chosen as the best +then each alternative will land behind a different Cargo feature, e.g. "alt1" +or "alt2". + +The traits will undergo a testing period before they are exported from the +top-level `embedded-hal` crate. During this period users are encouraged to try +to implement the unproven traits for their platforms and to build drivers on +top of them. Problems implementing the trait(s) as well as successful +implementations should be reported on the corresponding issue. + +To leave the unproven state at least *two* implementations of the trait(s) for +different platforms (ideally, the two platforms should be from different +vendors) and *one* generic driver built on top of the trait(s), or +alternatively one demo program that exercises the trait (via generic function +/ trait object), *should* be demonstrated. If, instead, reports indicate that +the proposed trait(s) can't be implemented for a certain platform then the +trait(s) will be removed and we'll go back to the drawing board. + +Issues used to track unproven APIs will be labeled as `unproven-api`s in the +issue tracker and they may also include the labels `needs-impl` and +`needs-driver` to signal what's required for them to move to the set of proven +traits. + +## Implementations and drivers + +For a list of `embedded-hal` implementations and driver crates check the +[awesome-embedded-rust] list. + +[awesome-embedded-rust]: https://github.com/rust-embedded/awesome-embedded-rust#driver-crates + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +## Code of Conduct + +Contribution to this crate is organized under the terms of the [Rust Code of +Conduct][CoC], the maintainer of this crate, the [HAL team][team], promises to +intervene to uphold that code of conduct. + +[CoC]: CODE_OF_CONDUCT.md +[team]: https://github.com/rust-embedded/wg#the-hal-team diff --git a/embedded-hal/README.md b/embedded-hal/README.md index 66d9a33b8..178140b68 100644 --- a/embedded-hal/README.md +++ b/embedded-hal/README.md @@ -14,49 +14,71 @@ This is the suggested approach to adding a new trait to `embedded-hal` ### Discussion -Ideally, before proposing a new trait, or set of traits, you should create an issue where the use -cases and requirements of the trait(s) are discussed. +Ideally, before proposing a new trait, or set of traits, you should create an +issue where the use cases and requirements of the trait(s) are discussed. These issues will be labeled as `discussion`s in the issue tracker. ### Proposing a trait -Once there's consensus on the requirements of the trait(s) a new issue, or a PR, with a proposal -should be opened. The proposal should include the actual trait definitions as well as a link to the -issue with previous discussion, if there was one. +Once there's consensus on the requirements of the trait(s) a new issue, or a +PR, with a proposal should be opened. The proposal should include the actual +trait definitions as well as a link to the issue with previous discussion, if +there was one. -If the proposal includes more than one alternative then there should be further discussion to try to -single out the best alternative. +If the proposal includes more than one alternative then there should be +further discussion to try to single out the best alternative. These issues / PRs will be labeled as `proposal`s in the issue tracker. ### Testing period -If there are no objections to the proposal the new trait(s) will land behind the "unproven" Cargo -feature and an issue about the new trait(s) will be created. If the proposal includes several -alternatives and a single one couldn't be chosen as the best then each alternative will land behind -a different Cargo feature, e.g. "alt1" or "alt2". - -The traits will undergo a testing period before they move into the set of proven traits. During -this period users are encouraged to try to implement the unproven traits for their platforms and to -build drivers on top of them. Problems implementing the trait(s) as well as successful -implementations should be reported on the corresponding issue. - -To leave the unproven state at least *two* implementations of the trait(s) for different platforms -(ideally, the two platforms should be from different vendors) and *one* generic driver built on top -of the trait(s), or alternatively one demo program that exercises the trait (via generic function / -trait object), *should* be demonstrated. If, instead, reports indicate that the proposed trait(s) -can't be implemented for a certain platform then the trait(s) will be removed and we'll go back to -the drawing board. - -Issues used to track unproven APIs will be labeled as `unproven-api`s in the issue tracker and they -may also include the labels `needs-impl` and `needs-driver` to signal what's required for them to -move to the set of proven traits. +If there are no objections to the proposal, the new trait(s) will land in one +of the upstream `embedded-hal-XXX` crates and an issue about the new trait(s) +will be created. If the proposal includes several alternatives and a single +one couldn't be chosen as the best then each alternative will land behind a +different Cargo feature, e.g. "alt1" or "alt2". + +The traits will undergo a testing period before they move into the set of +proven traits. During this period users are encouraged to try to implement the +unproven traits for their platforms and to build drivers on top of them. +Problems implementing the trait(s) as well as successful implementations +should be reported on the corresponding issue. + +To leave the unproven state at least *two* implementations of the trait(s) for +different platforms (ideally, the two platforms should be from different +vendors) and *one* generic driver built on top of the trait(s), or +alternatively one demo program that exercises the trait (via generic function +/ trait object), *should* be demonstrated. If, instead, reports indicate that +the proposed trait(s) can't be implemented for a certain platform then the +trait(s) will be removed and we'll go back to the drawing board. + +Issues used to track unproven APIs will be labeled as `unproven-api`s in the +issue tracker and they may also include the labels `needs-impl` and +`needs-driver` to signal what's required for them to move to the set of proven +traits exported by this crate. + +## Abstracted Interfaces + +The set of interfaces this crate currently supports is: + +* Delays/Busy-waiting - + [`embedded-hal-delay`](https://crates.io/crates/embedded-hal-delay) +* Digital GPIO pin interfaces - + [`embedded-hal-digital`](https://crates.io/crates/embedded-hal-digital) +* I2C bus interfaces - + [`embedded-hal-i2c`](https://crates.io/crates/embedded-hal-i2c) +* Serial (UART) interfaces - + [`embedded-hal-uart`](https://crates.io/crates/embedded-hal-uart) +* SPI bus interfaces - + [`embedded-hal-spi`](https://crates.io/crates/embedded-hal-spi) +* Timer devices (measuring elapsed time) - + [`embedded-hal-timer`](https://crates.io/crates/embedded-hal-timer) ## Implementations and drivers -For a list of `embedded-hal` implementations and driver crates check the [awesome-embedded-rust] -list. +For a list of `embedded-hal` implementations and driver crates check the +[awesome-embedded-rust] list. [awesome-embedded-rust]: https://github.com/rust-embedded/awesome-embedded-rust#driver-crates @@ -72,15 +94,16 @@ at your option. ### Contribution -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license, shall be -dual licensed as above, without any additional terms or conditions. +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. ## Code of Conduct Contribution to this crate is organized under the terms of the [Rust Code of -Conduct][CoC], the maintainer of this crate, the [HAL team][team], promises -to intervene to uphold that code of conduct. +Conduct][CoC], the maintainer of this crate, the [HAL team][team], promises to +intervene to uphold that code of conduct. [CoC]: CODE_OF_CONDUCT.md [team]: https://github.com/rust-embedded/wg#the-hal-team From 6ff6d0c90bfef2643d2fcb935289a280708b3977 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sun, 24 Nov 2019 16:11:03 +0000 Subject: [PATCH 06/10] Copy over the old documentation. --- embedded-hal/src/lib.rs | 685 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 683 insertions(+), 2 deletions(-) diff --git a/embedded-hal/src/lib.rs b/embedded-hal/src/lib.rs index 3679d3a86..e5afdc3a6 100644 --- a/embedded-hal/src/lib.rs +++ b/embedded-hal/src/lib.rs @@ -1,6 +1,687 @@ -//! # embedded-hal +//! A Hardware Abstraction Layer (HAL) for embedded systems //! -//! See README.md. +//! **NOTE** This HAL is still is active development. Expect the traits presented here to be +//! tweaked, split or be replaced wholesale before being stabilized, i.e. before hitting the 1.0.0 +//! release. That being said there's a part of the HAL that's currently considered unproven and is +//! hidden behind an "unproven" Cargo feature. This API is even more volatile and it's exempt from +//! semver rules: it can change in a non-backward compatible fashion or even disappear in between +//! patch releases. +//! +//! # Design goals +//! +//! The HAL +//! +//! - Must *erase* device specific details. Neither register, register blocks or magic values should +//! appear in the API. +//! +//! - Must be generic *within* a device and *across* devices. The API to use a serial interface must +//! be the same regardless of whether the implementation uses the USART1 or UART4 peripheral of a +//! device or the UART0 peripheral of another device. +//! +//! - Where possible must *not* be tied to a specific asynchronous model. The API should be usable +//! in blocking mode, with the `futures` model, with an async/await model or with a callback model. +//! (cf. the [`nb`] crate) +//! +//! - Must be minimal, and thus easy to implement and zero cost, yet highly composable. People that +//! want higher level abstraction should *prefer to use this HAL* rather than *re-implement* +//! register manipulation code. +//! +//! - Serve as a foundation for building an ecosystem of platform agnostic drivers. Here driver +//! means a library crate that lets a target platform interface an external device like a digital +//! sensor or a wireless transceiver. The advantage of this system is that by writing the driver as +//! a generic library on top of `embedded-hal` driver authors can support any number of target +//! platforms (e.g. Cortex-M microcontrollers, AVR microcontrollers, embedded Linux, etc.). The +//! advantage for application developers is that by adopting `embedded-hal` they can unlock all +//! these drivers for their platform. +//! +//! # Out of scope +//! +//! - Initialization and configuration stuff like "ensure this serial interface and that SPI +//! interface are not using the same pins". The HAL will focus on *doing I/O*. +//! +//! # Reference implementation +//! +//! The [`stm32f30x-hal`] crate contains a reference implementation of this HAL. +//! +//! [`stm32f30x-hal`]: https://crates.io/crates/stm32f30x-hal/0.1.0 +//! +//! # Platform agnostic drivers +//! +//! You can find platform agnostic drivers built on top of `embedded-hal` on crates.io by [searching +//! for the *embedded-hal* keyword](https://crates.io/keywords/embedded-hal). +//! +//! If you are writing a platform agnostic driver yourself you are highly encouraged to [add the +//! embedded-hal keyword](https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata) +//! to your crate before publishing it! +//! +//! # Detailed design +//! +//! ## Traits +//! +//! The HAL is specified as traits to allow generic programming. These traits make use of the +//! [`nb`][] crate (*please go read that crate documentation before continuing*) to abstract over +//! the asynchronous model and to also provide a blocking operation mode. +//! +//! [`nb`]: https://crates.io/crates/nb +//! +//! Here's what a HAL trait may look like: +//! +//! ``` +//! extern crate nb; +//! +//! /// A serial interface +//! pub trait Serial { +//! /// Error type associated to this serial interface +//! type Error; +//! +//! /// Reads a single byte +//! fn read(&mut self) -> nb::Result; +//! +//! /// Writes a single byte +//! fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error>; +//! } +//! ``` +//! +//! The `nb::Result` enum is used to add a [`WouldBlock`] variant to the errors +//! of the serial interface. As explained in the documentation of the `nb` crate this single API, +//! when paired with the macros in the `nb` crate, can operate in a blocking manner, or in a +//! non-blocking manner compatible with `futures` and with the `await!` operator. +//! +//! [`WouldBlock`]: https://docs.rs/nb/0.1.0/nb/enum.Error.html +//! +//! Some traits, like the one shown below, may expose possibly blocking APIs that can't fail. In +//! those cases `nb::Result<_, Infallible>` is used. +//! +//! ``` +//! extern crate nb; +//! +//! # use std as core; +//! use ::core::convert::Infallible; +//! +//! /// A count down timer +//! pub trait CountDown { +//! // .. +//! +//! /// "waits" until the count down is over +//! fn wait(&mut self) -> nb::Result<(), Infallible>; +//! } +//! +//! # fn main() {} +//! ``` +//! +//! ## Suggested implementation +//! +//! The HAL traits should be implemented for device crates generated via [`svd2rust`] to maximize +//! code reuse. +//! +//! [`svd2rust`]: https://crates.io/crates/svd2rust +//! +//! Shown below is an implementation of some of the HAL traits for the [`stm32f30x`] crate. This +//! single implementation will work for *any* microcontroller in the STM32F30x family. +//! +//! [`stm32f3`]: https://crates.io/crates/stm32f3 +//! +//! ``` +//! // crate: stm32f3xx-hal +//! // An implementation of the `embedded-hal` traits for STM32F3xx microcontrollers +//! +//! extern crate embedded_hal as hal; +//! extern crate nb; +//! +//! // device crate +//! extern crate stm32f3; +//! +//! use stm32f3::stm32f303::USART1; +//! +//! /// A serial interface +//! // NOTE generic over the USART peripheral +//! pub struct Serial { usart: USART } +//! +//! // convenience type alias +//! pub type Serial1 = Serial; +//! +//! /// Serial interface error +//! pub enum Error { +//! /// Buffer overrun +//! Overrun, +//! // omitted: other error variants +//! } +//! +//! impl hal::serial::Read for Serial { +//! type Error = Error; +//! +//! fn read(&mut self) -> nb::Result { +//! // 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)) +//! } +//! // 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) +//! } else { +//! // No data available yet +//! Err(nb::Error::WouldBlock) +//! } +//! } +//! } +//! +//! impl hal::serial::Write for Serial { +//! type Error = Error; +//! +//! fn write(&mut self, byte: u8) -> nb::Result<(), Error> { +//! // Similar to the `read` implementation +//! # Ok(()) +//! } +//! +//! fn flush(&mut self) -> nb::Result<(), Error> { +//! // Similar to the `read` implementation +//! # Ok(()) +//! } +//! } +//! +//! # fn main() {} +//! ``` +//! +//! ## Intended usage +//! +//! Thanks to the [`nb`] crate the HAL API can be used in a blocking manner, +//! with `futures` or with the `await` operator using the [`block!`], +//! [`try_nb!`] and [`await!`] macros respectively. +//! +//! [`block!`]: https://docs.rs/nb/0.1.0/nb/macro.block.html +//! [`try_nb!`]: https://docs.rs/nb/0.1.0/nb/index.html#how-to-use-this-crate +//! [`await!`]: https://docs.rs/nb/0.1.0/nb/index.html#how-to-use-this-crate +//! +//! ### Blocking mode +//! +//! An example of sending a string over the serial interface in a blocking +//! fashion: +//! +//! ``` +//! extern crate embedded_hal; +//! #[macro_use(block)] +//! extern crate nb; +//! +//! use stm32f30x_hal::Serial1; +//! use embedded_hal::serial::Write; +//! +//! # fn main() { +//! let mut serial: Serial1 = { +//! // .. +//! # Serial1 +//! }; +//! +//! for byte in b"Hello, world!" { +//! // NOTE `block!` keeps retrying `serial.write()` until it completes, then returns +//! // `Result<(), Error>` +//! block!(serial.write(*byte)).unwrap(); +//! } +//! # } +//! +//! # mod stm32f30x_hal { +//! # use std::convert::Infallible; +//! # pub struct Serial1; +//! # impl Serial1 { +//! # pub fn write(&mut self, _: u8) -> ::nb::Result<(), Infallible> { +//! # Ok(()) +//! # } +//! # } +//! # } +//! ``` +//! +//! ### `futures` +//! +//! An example of running two tasks concurrently. First task: blink a LED every +//! second. Second task: loop back data over the serial interface. The target +//! must provide the `libstd` in order to be able to use `futures`, which is not +//! the case for many embedded targets. +//! +//! ```not_run +//! extern crate embedded_hal as hal; +//! extern crate futures; +//! +//! #[macro_use(try_nb)] +//! extern crate nb; +//! +//! use hal::prelude::*; +//! use futures::{ +//! future, +//! Async, +//! Future, +//! }; +//! use futures::future::Loop; +//! use stm32f30x_hal::{Led, Serial1, Timer6}; +//! use std::convert::Infallible; +//! +//! /// `futures` version of `CountDown.wait` +//! /// +//! /// This returns a future that must be polled to completion +//! fn wait(mut timer: T) -> impl Future +//! where +//! T: hal::timer::CountDown, +//! { +//! let mut timer = Some(timer); +//! future::poll_fn(move || { +//! try_nb!(timer.as_mut().unwrap().wait()); +//! +//! Ok(Async::Ready(timer.take().unwrap())) +//! }) +//! } +//! +//! /// `futures` version of `Serial.read` +//! /// +//! /// This returns a future that must be polled to completion +//! fn read(mut serial: S) -> impl Future +//! where +//! S: hal::serial::Read, +//! { +//! let mut serial = Some(serial); +//! future::poll_fn(move || { +//! let byte = try_nb!(serial.as_mut().unwrap().read()); +//! +//! Ok(Async::Ready((serial.take().unwrap(), byte))) +//! }) +//! } +//! +//! /// `futures` version of `Serial.write` +//! /// +//! /// This returns a future that must be polled to completion +//! fn write(mut serial: S, byte: u8) -> impl Future +//! where +//! S: hal::serial::Write, +//! { +//! let mut serial = Some(serial); +//! future::poll_fn(move || { +//! try_nb!(serial.as_mut().unwrap().write(byte)); +//! +//! Ok(Async::Ready(serial.take().unwrap())) +//! }) +//! } +//! +//! fn main() { +//! // HAL implementers +//! let timer: Timer6 = { +//! // .. +//! # Timer6 +//! }; +//! let serial: Serial1 = { +//! // .. +//! # Serial1 +//! }; +//! let led: Led = { +//! // .. +//! # Led +//! }; +//! +//! // Tasks +//! let mut blinky = future::loop_fn::<_, (), _, _>( +//! (led, timer, true), +//! |(mut led, mut timer, state)| { +//! wait(timer).map(move |timer| { +//! if state { +//! led.on(); +//! } else { +//! led.off(); +//! } +//! +//! Loop::Continue((led, timer, !state)) +//! }) +//! }); +//! +//! let mut loopback = future::loop_fn::<_, (), _, _>(serial, |mut serial| { +//! read(serial).and_then(|(serial, byte)| { +//! write(serial, byte) +//! }).map(|serial| { +//! Loop::Continue(serial) +//! }) +//! }); +//! +//! // Event loop +//! loop { +//! blinky.poll().unwrap(); // NOTE(unwrap) E = Infallible +//! loopback.poll().unwrap(); +//! # break; +//! } +//! } +//! +//! # mod stm32f30x_hal { +//! # use std::convert::Infallible; +//! # pub struct Timer6; +//! # impl ::hal::timer::CountDown for Timer6 { +//! # type Time = (); +//! # +//! # fn start(&mut self, _: T) where T: Into<()> {} +//! # fn wait(&mut self) -> ::nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) } +//! # } +//! # +//! # pub struct Serial1; +//! # impl ::hal::serial::Read for Serial1 { +//! # type Error = Infallible; +//! # fn read(&mut self) -> ::nb::Result { Err(::nb::Error::WouldBlock) } +//! # } +//! # impl ::hal::serial::Write for Serial1 { +//! # type Error = Infallible; +//! # fn flush(&mut self) -> ::nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) } +//! # fn write(&mut self, _: u8) -> ::nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) } +//! # } +//! # +//! # pub struct Led; +//! # impl Led { +//! # pub fn off(&mut self) {} +//! # pub fn on(&mut self) {} +//! # } +//! # } +//! ``` +//! +//! ### `await` +//! +//! Same example as above but using `await!` instead of `futures` +//! (same remark concerning the availability of `libstd` on the +//! target). +//! +//! ```not_run +//! #![feature(generator_trait)] +//! #![feature(generators)] +//! +//! extern crate embedded_hal as hal; +//! +//! #[macro_use(r#await)] +//! extern crate nb; +//! +//! use std::ops::Generator; +//! use std::pin::Pin; +//! +//! use hal::prelude::*; +//! use stm32f30x_hal::{Led, Serial1, Timer6}; +//! +//! fn main() { +//! // HAL implementers +//! let mut timer: Timer6 = { +//! // .. +//! # Timer6 +//! }; +//! let mut serial: Serial1 = { +//! // .. +//! # Serial1 +//! }; +//! let mut led: Led = { +//! // .. +//! # Led +//! }; +//! +//! // Tasks +//! let mut blinky = (move || { +//! let mut state = false; +//! loop { +//! // `await!` means "suspend / yield here" instead of "block until +//! // completion" +//! nb::r#await!(timer.wait()).unwrap(); // NOTE(unwrap) E = Infallible +//! +//! state = !state; +//! +//! if state { +//! led.on(); +//! } else { +//! led.off(); +//! } +//! } +//! }); +//! +//! let mut loopback = (move || { +//! loop { +//! let byte = nb::r#await!(serial.read()).unwrap(); +//! nb::r#await!(serial.write(byte)).unwrap(); +//! } +//! }); +//! +//! // Event loop +//! loop { +//! Pin::new(&mut blinky).resume(); +//! Pin::new(&mut loopback).resume(); +//! # break; +//! } +//! } +//! +//! # mod stm32f30x_hal { +//! # use std::convert::Infallible; +//! # pub struct Serial1; +//! # impl Serial1 { +//! # pub fn read(&mut self) -> ::nb::Result { Err(::nb::Error::WouldBlock) } +//! # pub fn write(&mut self, _: u8) -> ::nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) } +//! # } +//! # pub struct Timer6; +//! # impl Timer6 { +//! # pub fn wait(&mut self) -> ::nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) } +//! # } +//! # pub struct Led; +//! # impl Led { +//! # pub fn off(&mut self) {} +//! # pub fn on(&mut self) {} +//! # } +//! # } +//! ``` +//! +//! ## Generic programming and higher level abstractions +//! +//! The core of the HAL has been kept minimal on purpose to encourage building **generic** higher +//! level abstractions on top of it. Some higher level abstractions that pick an asynchronous model +//! or that have blocking behavior and that are deemed useful to build other abstractions can be +//! found in the `blocking` module and, in the future, in the `futures` and `async` modules. +//! +//! Some examples: +//! +//! **NOTE** All the functions shown below could have been written as trait +//! methods with default implementation to allow specialization, but they have +//! been written as functions to keep things simple. +//! +//! - 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 hal::prelude::*; +//! +//! fn write_all(serial: &mut S, buffer: &[u8]) -> Result<(), S::Error> +//! where +//! S: hal::serial::Write +//! { +//! for &byte in buffer { +//! block!(serial.write(byte))?; +//! } +//! +//! Ok(()) +//! } +//! +//! # fn main() {} +//! ``` +//! +//! - Blocking serial read with timeout +//! +//! ``` +//! extern crate embedded_hal as hal; +//! extern crate nb; +//! +//! use hal::prelude::*; +//! +//! enum Error { +//! /// Serial interface error +//! Serial(E), +//! TimedOut, +//! } +//! +//! fn read_with_timeout( +//! serial: &mut S, +//! timer: &mut T, +//! timeout: T::Time, +//! ) -> Result> +//! where +//! T: hal::timer::CountDown, +//! S: hal::serial::Read, +//! { +//! timer.start(timeout); +//! +//! loop { +//! match serial.read() { +//! // raise error +//! Err(nb::Error::Other(e)) => return Err(Error::Serial(e)), +//! Err(nb::Error::WouldBlock) => { +//! // no data available yet, check the timer below +//! }, +//! Ok(byte) => return Ok(byte), +//! } +//! +//! match timer.wait() { +//! Err(nb::Error::Other(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), +//! } +//! } +//! } +//! +//! # fn main() {} +//! ``` +//! +//! - Asynchronous SPI transfer +//! +//! ```not_run +//! #![feature(conservative_impl_trait)] +//! #![feature(generators)] +//! #![feature(generator_trait)] +//! +//! extern crate embedded_hal as hal; +//! #[macro_use(r#await)] +//! extern crate nb; +//! +//! use std::ops::Generator; +//! +//! /// Transfers a byte buffer of size N +//! /// +//! /// Returns the same byte buffer but filled with the data received from the +//! /// slave device +//! fn transfer( +//! mut spi: S, +//! mut buffer: [u8; 16], // NOTE this should be generic over the size of the array +//! ) -> impl Generator, Yield = ()> +//! where +//! S: hal::spi::FullDuplex, +//! { +//! move || { +//! let n = buffer.len(); +//! for i in 0..n { +//! nb::r#await!(spi.send(buffer[i]))?; +//! buffer[i] = nb::r#await!(spi.read())?; +//! } +//! +//! Ok((spi, buffer)) +//! } +//! } +//! +//! # fn main() {} +//! ``` +//! +//! - Buffered serial interface with periodic flushing in interrupt handler +//! +//! ``` +//! # use std as core; +//! extern crate embedded_hal as hal; +//! extern crate nb; +//! +//! use hal::prelude::*; +//! use ::core::convert::Infallible; +//! +//! fn flush(serial: &mut S, cb: &mut CircularBuffer) +//! where +//! S: hal::serial::Write, +//! { +//! 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 +//! } +//! } +//! +//! cb.pop(); +//! } +//! } +//! +//! // The stuff below could be in some other crate +//! +//! /// Global singleton +//! pub struct BufferedSerial1; +//! +//! // NOTE private +//! static BUFFER1: Mutex = { +//! // .. +//! # Mutex(CircularBuffer) +//! }; +//! static SERIAL1: Mutex = { +//! // .. +//! # Mutex(Serial1) +//! }; +//! +//! impl BufferedSerial1 { +//! pub fn write(&self, byte: u8) { +//! self.write_all(&[byte]) +//! } +//! +//! pub fn write_all(&self, bytes: &[u8]) { +//! let mut buffer = BUFFER1.lock(); +//! for byte in bytes { +//! buffer.push(*byte).expect("buffer overrun"); +//! } +//! // omitted: pend / enable interrupt_handler +//! } +//! } +//! +//! fn interrupt_handler() { +//! let mut serial = SERIAL1.lock(); +//! let mut buffer = BUFFER1.lock(); +//! +//! flush(&mut *serial, &mut buffer); +//! } +//! +//! # struct Mutex(T); +//! # impl Mutex { +//! # fn lock(&self) -> RefMut { unimplemented!() } +//! # } +//! # struct RefMut<'a, T>(&'a mut T) where T: 'a; +//! # impl<'a, T> ::std::ops::Deref for RefMut<'a, T> { +//! # type Target = T; +//! # fn deref(&self) -> &T { self.0 } +//! # } +//! # impl<'a, T> ::std::ops::DerefMut for RefMut<'a, T> { +//! # fn deref_mut(&mut self) -> &mut T { self.0 } +//! # } +//! # struct 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) } +//! # } +//! # struct CircularBuffer; +//! # impl CircularBuffer { +//! # pub fn peek(&mut self) -> Option<&u8> { None } +//! # pub fn pop(&mut self) -> Option { None } +//! # pub fn push(&mut self, _: u8) -> Result<(), ()> { Ok(()) } +//! # } +//! +//! # fn main() {} +//! ``` + #![deny(missing_docs)] #![no_std] From 20550b1b1ff998c6a2754a69600a69fd5573686e Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sun, 24 Nov 2019 16:11:14 +0000 Subject: [PATCH 07/10] Update crate docs. --- embedded-hal-delay/src/lib.rs | 6 +++++- embedded-hal-digital/src/lib.rs | 2 +- embedded-hal-i2c/src/lib.rs | 7 ++++++- embedded-hal-serial/src/lib.rs | 8 +++++++- embedded-hal-spi/src/lib.rs | 9 ++++++++- embedded-hal-timer/src/lib.rs | 8 +++++++- 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/embedded-hal-delay/src/lib.rs b/embedded-hal-delay/src/lib.rs index 23a9bb5bd..64f168fed 100644 --- a/embedded-hal-delay/src/lib.rs +++ b/embedded-hal-delay/src/lib.rs @@ -1,4 +1,8 @@ -//! Delays +//! # embedded-hal-delay +//! +//! Traits for busy-waiting for specified periods of time. You should use the +//! [`embedded-hal`](https://crates.io/crates/embedded-hal) crate if you want +//! a stable version. //! //! # What's the difference between these traits and the `timer::CountDown` trait? //! diff --git a/embedded-hal-digital/src/lib.rs b/embedded-hal-digital/src/lib.rs index bd8695653..43046f77c 100644 --- a/embedded-hal-digital/src/lib.rs +++ b/embedded-hal-digital/src/lib.rs @@ -1,6 +1,6 @@ //! # embedded-hal-digital //! -//! Contains digital GPIO pin traits. You should use the +//! Traits for writing and reading digital GPIO pins. You should use the //! [`embedded-hal`](https://crates.io/crates/embedded-hal) crate if you want //! a stable version. diff --git a/embedded-hal-i2c/src/lib.rs b/embedded-hal-i2c/src/lib.rs index 0ea2ed330..2d64342cf 100644 --- a/embedded-hal-i2c/src/lib.rs +++ b/embedded-hal-i2c/src/lib.rs @@ -1,6 +1,11 @@ //! # embedded-hal-i2c //! -//! Traits for I2C (Inter-IC) Interface Masters +//! Traits for driving a Inter-IC (I2C) bus so as to access the other devices +//! on that bus. You should use the +//! [`embedded-hal`](https://crates.io/crates/embedded-hal) crate if you want +//! a stable version. +//! +//! This is currently only available as a blocking API. #![deny(missing_docs)] #![no_std] diff --git a/embedded-hal-serial/src/lib.rs b/embedded-hal-serial/src/lib.rs index c3fd11886..6d915a3d4 100644 --- a/embedded-hal-serial/src/lib.rs +++ b/embedded-hal-serial/src/lib.rs @@ -1,4 +1,10 @@ -//! Serial interface +//! # embedded-hal-serial +//! +//! Traits for driving a Serial interface (also known as a UART). You should use the +//! [`embedded-hal`](https://crates.io/crates/embedded-hal) crate if you want +//! a stable version. +//! +//! Available in both blocking and non-blocking variants. #![deny(missing_docs)] #![no_std] diff --git a/embedded-hal-spi/src/lib.rs b/embedded-hal-spi/src/lib.rs index a93a63225..dc44636a5 100644 --- a/embedded-hal-spi/src/lib.rs +++ b/embedded-hal-spi/src/lib.rs @@ -1,4 +1,11 @@ -//! Serial Peripheral Interface +//! # embedded-hal-spi +//! +//! Traits for driving a Serial Peripheral Interface (SPI) device for the +//! purposes of accessing other devices on that bus. You should use the +//! [`embedded-hal`](https://crates.io/crates/embedded-hal) crate if you want +//! a stable version. +//! +//! Available in both blocking and non-blocking variants. #![deny(missing_docs)] #![no_std] diff --git a/embedded-hal-timer/src/lib.rs b/embedded-hal-timer/src/lib.rs index fc1aed9c1..53a0afcc8 100644 --- a/embedded-hal-timer/src/lib.rs +++ b/embedded-hal-timer/src/lib.rs @@ -1,4 +1,10 @@ -//! Timers +//! # embedded-hal-timer +//! +//! Traits for measuring elapsed periods of time. You should use the +//! [`embedded-hal`](https://crates.io/crates/embedded-hal) crate if you want +//! a stable version. +//! +//! This API is non-blocking. #![deny(missing_docs)] #![no_std] From be491e2490f1d189458600bb6e16a9f37d7296c9 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sun, 24 Nov 2019 19:14:03 +0000 Subject: [PATCH 08/10] Only run tests on x86-64 --- ci/script.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ci/script.sh b/ci/script.sh index a115d519f..e3f872358 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -2,8 +2,11 @@ set -euxo pipefail main() { cargo check --target $TARGET - cargo test --target $TARGET - cargo fmt -- --check + cargo check --target $TARGET --features unproven + + if [ "$TARGET" = "x86_64-unknown-linux-gnu" ]; then + cargo test --target $TARGET --features unproven + fi } -main +main \ No newline at end of file From 8bc4d98fa0b8372d176b76455191fc393a316b5d Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sun, 24 Nov 2019 19:23:08 +0000 Subject: [PATCH 09/10] Added dev dependencies - tests now pass. --- embedded-hal/Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/embedded-hal/Cargo.toml b/embedded-hal/Cargo.toml index a1976fd17..9477c6ffd 100644 --- a/embedded-hal/Cargo.toml +++ b/embedded-hal/Cargo.toml @@ -35,3 +35,7 @@ path = "../embedded-hal-spi" path = "../embedded-hal-timer" # version = "1.0" +[dev-dependencies] +nb = "0.1.1" +stm32f3 = { version = "0.8", features = ["stm32f303", "rt"] } +futures = "0.1.17" From ca4f8bddf93803cf4147828bc8b5f275f4d22523 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sun, 24 Nov 2019 19:27:30 +0000 Subject: [PATCH 10/10] Enable format checks. --- ci/script.sh | 2 ++ embedded-hal/src/lib.rs | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ci/script.sh b/ci/script.sh index e3f872358..5a2b62f1a 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -7,6 +7,8 @@ main() { if [ "$TARGET" = "x86_64-unknown-linux-gnu" ]; then cargo test --target $TARGET --features unproven fi + + cargo fmt -- --check } main \ No newline at end of file diff --git a/embedded-hal/src/lib.rs b/embedded-hal/src/lib.rs index e5afdc3a6..173bcb8fb 100644 --- a/embedded-hal/src/lib.rs +++ b/embedded-hal/src/lib.rs @@ -682,7 +682,6 @@ //! # fn main() {} //! ``` - #![deny(missing_docs)] #![no_std]