Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[towards 1.0]: Fallible proven traits #192

Merged
merged 22 commits into from
Mar 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- A nonblocking trait for interfacing with random number generation hardware.

### Changed
- The current versions of `InputPin` have been proven. These are `digital::v1::InputPin`
and `digital::v2::InputPin`.
- All traits have been marked as proven (`unproven` feature has been removed).
- All trait methods have been made fallible.
- All trait methods have been renamed `try_*` (i.e. `try_send`) for consistency.
- The minimum supported Rust version is 1.35 due to [this issue](https://github.com/rust-lang/rust/issues/54973).

## [v0.2.3] - 2019-05-09

Expand Down
9 changes: 2 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,10 @@ readme = "README.md"
repository = "https://github.com/rust-embedded/embedded-hal"
version = "0.2.3"

[dependencies.nb]
version = "0.1.1"
[dependencies]
nb = { version = "0.1.1", features = ["unstable"] }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unstable ? That has a weird sound to it considering that we're aiming to stabilize this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because currently the unproven feature requires nb/unstable. The state of the unstable feature should be discussed for nb's 1.0 release.


[dev-dependencies]
stm32f3 = { version = "0.8", features = ["stm32f303", "rt"] }
futures = "0.1.17"

[features]
unproven = ["nb/unstable"]

[package.metadata.docs.rs]
features = ["unproven"]
3 changes: 1 addition & 2 deletions ci/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ set -euxo pipefail

main() {
cargo check --target $TARGET
cargo check --target $TARGET --features unproven
cargo fmt -- --check

if [ $TRAVIS_RUST_VERSION = nightly ]; then
cargo test --target $TARGET --features unproven
cargo test --target $TARGET
fi
}

Expand Down
22 changes: 7 additions & 15 deletions src/adc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! 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.
Expand All @@ -10,7 +9,7 @@ use nb;
/// between the physical interface and the ADC sampling buffer.
///
/// ```
/// # use std::marker::PhantomData;
/// # use core::marker::PhantomData;
/// # use embedded_hal::adc::Channel;
///
/// struct Adc1; // Example ADC with single bank of 8 channels
Expand All @@ -21,7 +20,7 @@ use nb;
/// impl Channel<Adc1> for Gpio1Pin1<Analog> {
/// type ID = u8; // ADC channels are identified numerically
///
/// fn channel() -> u8 { 7_u8 } // GPIO pin 1 is connected to ADC channel 7
/// const CHANNEL: u8 = 7_u8; // GPIO pin 1 is connected to ADC channel 7
/// }
///
/// struct Adc2; // ADC with two banks of 16 channels
Expand All @@ -32,10 +31,9 @@ use nb;
/// impl Channel<Adc2> for Gpio2PinA<AltFun> {
/// type ID = (u8, u8); // ADC channels are identified by bank number and channel number
///
/// fn channel() -> (u8, u8) { (0, 3) } // bank 0 channel 3
/// const CHANNEL: (u8, u8) = (0, 3); // bank 0 channel 3
/// }
/// ```
#[cfg(feature = "unproven")]
pub trait Channel<ADC> {
/// Channel ID type
///
Expand All @@ -46,12 +44,7 @@ pub trait Channel<ADC> {

/// 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;
const CHANNEL: Self::ID;
}

/// ADCs that sample on single channels per request, and do so at the time of the request.
Expand All @@ -76,16 +69,15 @@ pub trait Channel<ADC> {
/// {
/// type Error = ();
///
/// fn read(&mut self, _pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
/// let chan = 1 << PIN::channel();
/// fn try_read(&mut self, _pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
/// 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<ADC, Word, Pin: Channel<ADC>> {
/// Error type returned by ADC methods
type Error;
Expand All @@ -94,5 +86,5 @@ pub trait OneShot<ADC, Word, Pin: Channel<ADC>> {
///
/// 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<Word, Self::Error>;
fn try_read(&mut self, pin: &mut Pin) -> nb::Result<Word, Self::Error>;
}
10 changes: 8 additions & 2 deletions src/blocking/delay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,21 @@
/// `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<UXX> {
/// Enumeration of `DelayMs` errors
type Error;

/// Pauses execution for `ms` milliseconds
fn delay_ms(&mut self, ms: UXX);
fn try_delay_ms(&mut self, ms: UXX) -> Result<(), Self::Error>;
thejpster marked this conversation as resolved.
Show resolved Hide resolved
}

/// 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<UXX> {
/// Enumeration of `DelayMs` errors
type Error;

/// Pauses execution for `us` microseconds
fn delay_us(&mut self, us: UXX);
fn try_delay_us(&mut self, us: UXX) -> Result<(), Self::Error>;
}
12 changes: 5 additions & 7 deletions src/blocking/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub trait Read {
/// - `MAK` = master acknowledge
/// - `NMAK` = master no acknowledge
/// - `SP` = stop condition
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error>;
fn try_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error>;
}

/// Blocking write
Expand All @@ -52,11 +52,10 @@ pub trait Write {
/// - `SAK` = slave acknowledge
/// - `Bi` = ith byte of data
/// - `SP` = stop condition
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error>;
fn try_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error>;
}

/// Blocking write (iterator version)
#[cfg(feature = "unproven")]
pub trait WriteIter {
/// Error type
type Error;
Expand All @@ -66,7 +65,7 @@ pub trait WriteIter {
/// # I2C Events (contract)
///
/// Same as `Write`
fn write<B>(&mut self, addr: u8, bytes: B) -> Result<(), Self::Error>
fn try_write<B>(&mut self, addr: u8, bytes: B) -> Result<(), Self::Error>
where
B: IntoIterator<Item = u8>;
}
Expand Down Expand Up @@ -98,7 +97,7 @@ pub trait WriteRead {
/// - `MAK` = master acknowledge
/// - `NMAK` = master no acknowledge
/// - `SP` = stop condition
fn write_read(
fn try_write_read(
&mut self,
address: u8,
bytes: &[u8],
Expand All @@ -107,7 +106,6 @@ pub trait WriteRead {
}

/// Blocking write (iterator version) + read
#[cfg(feature = "unproven")]
pub trait WriteIterRead {
/// Error type
type Error;
Expand All @@ -118,7 +116,7 @@ pub trait WriteIterRead {
/// # I2C Events (contract)
///
/// Same as the `WriteRead` trait
fn write_iter_read<B>(
fn try_write_iter_read<B>(
&mut self,
address: u8,
bytes: B,
Expand Down
5 changes: 1 addition & 4 deletions src/blocking/rng.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
//! 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;
Expand All @@ -15,5 +12,5 @@ pub trait Read {
///
/// 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>;
fn try_read(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error>;
}
16 changes: 8 additions & 8 deletions src/blocking/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ pub trait Write<Word> {
/// 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.
/// everything has been sent, call [`try_bflush`] after this function returns.
///
/// [`bflush`]: #tymethod.bflush
fn bwrite_all(&mut self, buffer: &[Word]) -> Result<(), Self::Error>;
/// [`try_bflush`]: #tymethod.bflush
fn try_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>;
fn try_bflush(&mut self) -> Result<(), Self::Error>;
}

/// Blocking serial write
Expand All @@ -38,16 +38,16 @@ pub mod write {
{
type Error = S::Error;

fn bwrite_all(&mut self, buffer: &[Word]) -> Result<(), Self::Error> {
fn try_bwrite_all(&mut self, buffer: &[Word]) -> Result<(), Self::Error> {
for word in buffer {
block!(self.write(word.clone()))?;
block!(self.try_write(word.clone()))?;
}

Ok(())
}

fn bflush(&mut self) -> Result<(), Self::Error> {
block!(self.flush())?;
fn try_bflush(&mut self) -> Result<(), Self::Error> {
block!(self.try_flush())?;
Ok(())
}
}
Expand Down
26 changes: 12 additions & 14 deletions src/blocking/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub trait Transfer<W> {
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>;
fn try_transfer<'w>(&mut self, words: &'w mut [W]) -> Result<&'w [W], Self::Error>;
}

/// Blocking write
Expand All @@ -15,17 +15,16 @@ pub trait Write<W> {
type Error;

/// Sends `words` to the slave, ignoring all the incoming words
fn write(&mut self, words: &[W]) -> Result<(), Self::Error>;
fn try_write(&mut self, words: &[W]) -> Result<(), Self::Error>;
}

/// Blocking write (iterator version)
#[cfg(feature = "unproven")]
pub trait WriteIter<W> {
/// Error type
type Error;

/// Sends `words` to the slave, ignoring all the incoming words
fn write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error>
fn try_write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error>
where
WI: IntoIterator<Item = W>;
}
Expand All @@ -43,10 +42,10 @@ pub mod transfer {
{
type Error = S::Error;

fn transfer<'w>(&mut self, words: &'w mut [W]) -> Result<&'w [W], S::Error> {
fn try_transfer<'w>(&mut self, words: &'w mut [W]) -> Result<&'w [W], S::Error> {
for word in words.iter_mut() {
block!(self.send(word.clone()))?;
*word = block!(self.read())?;
block!(self.try_send(word.clone()))?;
*word = block!(self.try_read())?;
}

Ok(words)
Expand All @@ -66,10 +65,10 @@ pub mod write {
{
type Error = S::Error;

fn write(&mut self, words: &[W]) -> Result<(), S::Error> {
fn try_write(&mut self, words: &[W]) -> Result<(), S::Error> {
for word in words {
block!(self.send(word.clone()))?;
block!(self.read())?;
block!(self.try_send(word.clone()))?;
block!(self.try_read())?;
}

Ok(())
Expand All @@ -78,7 +77,6 @@ pub mod write {
}

/// Blocking write (iterator version)
#[cfg(feature = "unproven")]
pub mod write_iter {
/// Default implementation of `blocking::spi::WriteIter<W>` for implementers of
/// `spi::FullDuplex<W>`
Expand All @@ -91,13 +89,13 @@ pub mod write_iter {
{
type Error = S::Error;

fn write_iter<WI>(&mut self, words: WI) -> Result<(), S::Error>
fn try_write_iter<WI>(&mut self, words: WI) -> Result<(), S::Error>
where
WI: IntoIterator<Item = W>,
{
for word in words.into_iter() {
block!(self.send(word.clone()))?;
block!(self.read())?;
block!(self.try_send(word.clone()))?;
block!(self.try_read())?;
}

Ok(())
Expand Down
Loading