Skip to content

Update reference implementation implementation to stm32f1xx-hal and update examples #251

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

Merged
merged 3 commits into from
Oct 6, 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
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ nb = "1"
[dev-dependencies]
futures = "0.1.17"

[dev-dependencies.stm32f1]
version = "0.12"
features = ["stm32f103", "rt"]
231 changes: 52 additions & 179 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@
//!
//! # Reference implementation
//!
//! The [`stm32f30x-hal`] crate contains a reference implementation of this HAL.
//! The [`stm32f1xx-hal`] crate contains a reference implementation of this HAL.
//!
//! [`stm32f30x-hal`]: https://crates.io/crates/stm32f30x-hal/0.1.0
//! [`stm32f1xx-hal`]: https://crates.io/crates/stm32f1xx-hal
//!
//! # Platform agnostic drivers
//!
Expand All @@ -64,7 +64,7 @@
//! Here's how a HAL trait may look like:
//!
//! ```
//! extern crate nb;
//! use nb;
//!
//! /// A serial interface
//! pub trait Serial {
Expand All @@ -90,7 +90,7 @@
//! those cases `nb::Result<_, Infallible>` is used.
//!
//! ```
//! extern crate nb;
//! use nb;
//!
//! # use std as core;
//! use ::core::convert::Infallible;
Expand All @@ -113,22 +113,20 @@
//!
//! [`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.
//! Shown below is an implementation of some of the HAL traits for the [`stm32f1xx-hal`] crate. This
//! single implementation will work for *any* microcontroller in the STM32F1xx family.
//!
//! [`stm32f3`]: https://crates.io/crates/stm32f3
//! [`stm32f1`]: https://crates.io/crates/stm32f1
//!
//! ```not_run
//! // crate: stm32f3xx-hal
//! // An implementation of the `embedded-hal` traits for STM32F3xx microcontrollers
//! // crate: stm32f1xx-hal
//! // An implementation of the `embedded-hal` traits for STM32F1xx microcontrollers
//!
//! extern crate embedded_hal as hal;
//! extern crate nb;
//! use embedded_hal as hal;
//! use nb;
//!
//! // device crate
//! extern crate stm32f3;
//!
//! use stm32f3::stm32f303::USART1;
//! use stm32f1::stm32f103::USART1;
//!
//! /// A serial interface
//! // NOTE generic over the USART peripheral
Expand Down Expand Up @@ -185,26 +183,20 @@
//!
//! ## 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.
//! Thanks to the [`nb`] crate the HAL API can be used in a blocking manner
//! with the [`block!`] macro or with `futures`.
//!
//! [`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
//! [`block!`]: https://docs.rs/nb/1.0.0/nb/macro.block.html
//!
//! ### 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 crate::stm32f1xx_hal::Serial1;
//! use embedded_hal::serial::Write;
//! use nb::block;
//!
//! # fn main() {
//! let mut serial: Serial1 = {
Expand All @@ -219,11 +211,12 @@
//! }
//! # }
//!
//! # mod stm32f30x_hal {
//! # mod stm32f1xx_hal {
//! # use nb;
//! # use core::convert::Infallible;
//! # pub struct Serial1;
//! # impl Serial1 {
//! # pub fn try_write(&mut self, _: u8) -> ::nb::Result<(), Infallible> {
//! # pub fn try_write(&mut self, _: u8) -> nb::Result<(), Infallible> {
//! # Ok(())
//! # }
//! # }
Expand All @@ -238,20 +231,15 @@
//! the case for many embedded targets.
//!
//! ```no_run
//! extern crate embedded_hal as hal;
//! extern crate futures;
//!
//! #[macro_use(try_nb)]
//! extern crate nb;
//!
//! use hal::prelude::*;
//! use embedded_hal as hal;
//! use crate::hal::prelude::*;
//! use futures::{
//! future,
//! future::{self, Loop},
//! Async,
//! Future,
//! };
//! use futures::future::Loop;
//! use stm32f30x_hal::{Led, Serial1, Timer6};
//! use nb;
//! use stm32f1xx_hal::{Led, Serial1, Timer6};
//! use core::convert::Infallible;
//!
//! /// `futures` version of `CountDown.try_wait`
Expand All @@ -263,7 +251,11 @@
//! {
//! let mut timer = Some(timer);
//! future::poll_fn(move || {
//! try_nb!(timer.as_mut().unwrap().try_wait());
//! match timer.as_mut().unwrap().try_wait() {
//! Err(nb::Error::Other(e)) => return Err(e),
//! Err(nb::Error::WouldBlock) => return Ok(Async::NotReady),
//! Ok(_) => (),
//! };
//!
//! Ok(Async::Ready(timer.take().unwrap()))
//! })
Expand All @@ -278,7 +270,11 @@
//! {
//! let mut serial = Some(serial);
//! future::poll_fn(move || {
//! let byte = try_nb!(serial.as_mut().unwrap().try_read());
//! let byte = match serial.as_mut().unwrap().try_read() {
//! Err(nb::Error::Other(e)) => return Err(e),
//! Err(nb::Error::WouldBlock) => return Ok(Async::NotReady),
//! Ok(x) => x,
//! };
//!
//! Ok(Async::Ready((serial.take().unwrap(), byte)))
//! })
Expand All @@ -293,7 +289,11 @@
//! {
//! let mut serial = Some(serial);
//! future::poll_fn(move || {
//! try_nb!(serial.as_mut().unwrap().try_write(byte));
//! match serial.as_mut().unwrap().try_write(byte) {
//! Err(nb::Error::Other(e)) => return Err(e),
//! Err(nb::Error::WouldBlock) => return Ok(Async::NotReady),
//! Ok(_) => (),
//! };
//!
//! Ok(Async::Ready(serial.take().unwrap()))
//! })
Expand Down Expand Up @@ -345,10 +345,11 @@
//! }
//! }
//!
//! # mod stm32f30x_hal {
//! # mod stm32f1xx_hal {
//! # use crate::hal;
//! # use core::convert::Infallible;
//! # pub struct Timer6;
//! # impl ::hal::timer::CountDown for Timer6 {
//! # impl hal::timer::CountDown for Timer6 {
//! # type Error = Infallible;
//! # type Time = ();
//! #
Expand All @@ -357,11 +358,11 @@
//! # }
//! #
//! # pub struct Serial1;
//! # impl ::hal::serial::Read<u8> for Serial1 {
//! # impl hal::serial::Read<u8> for Serial1 {
//! # type Error = Infallible;
//! # fn try_read(&mut self) -> ::nb::Result<u8, Infallible> { Err(::nb::Error::WouldBlock) }
//! # }
//! # impl ::hal::serial::Write<u8> for Serial1 {
//! # impl hal::serial::Write<u8> for Serial1 {
//! # type Error = Infallible;
//! # fn try_flush(&mut self) -> ::nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) }
//! # fn try_write(&mut self, _: u8) -> ::nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) }
Expand All @@ -375,94 +376,6 @@
//! # }
//! ```
//!
//! ### `await`
//!
//! Same example as above but using `await!` instead of `futures`
//! (same remark concerning the availability of `libstd` on the
//! target).
//!
//! ```no_run
//! #![feature(generator_trait)]
//! #![feature(generators)]
//!
//! extern crate embedded_hal as hal;
//!
//! #[macro_use(r#await)]
//! extern crate nb;
//!
//! use core::ops::Generator;
//! use core::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.try_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.try_read()).unwrap();
//! nb::r#await!(serial.try_write(byte)).unwrap();
//! }
//! });
//!
//! // Event loop
//! loop {
//! Pin::new(&mut blinky).resume(());
//! Pin::new(&mut loopback).resume(());
//! # break;
//! }
//! }
//!
//! # mod stm32f30x_hal {
//! # use core::convert::Infallible;
//! # pub struct Serial1;
//! # impl Serial1 {
//! # pub fn try_read(&mut self) -> ::nb::Result<u8, Infallible> { Err(::nb::Error::WouldBlock) }
//! # pub fn try_write(&mut self, _: u8) -> ::nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) }
//! # }
//! # pub struct Timer6;
//! # impl Timer6 {
//! # pub fn try_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
Expand All @@ -479,10 +392,8 @@
//! - Write a whole buffer to a serial device in blocking a fashion.
//!
//! ```
//! extern crate embedded_hal as hal;
//! #[macro_use(block)]
//! extern crate nb;
//!
//! use embedded_hal as hal;
//! use nb::block;
//! use hal::prelude::*;
//!
//! fn write_all<S>(serial: &mut S, buffer: &[u8]) -> Result<(), S::Error>
Expand All @@ -502,8 +413,8 @@
//! - Blocking serial read with timeout
//!
//! ```
//! extern crate embedded_hal as hal;
//! extern crate nb;
//! use embedded_hal as hal;
//! use nb;
//!
//! use hal::prelude::*;
//!
Expand Down Expand Up @@ -552,50 +463,12 @@
//! # fn main() {}
//! ```
//!
//! - Asynchronous SPI transfer
//!
//! ```no_run
//! #![feature(conservative_impl_trait)]
//! #![feature(generators)]
//! #![feature(generator_trait)]
//!
//! extern crate embedded_hal as hal;
//! #[macro_use(r#await)]
//! extern crate nb;
//!
//! use core::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<S, B>(
//! mut spi: S,
//! mut buffer: [u8; 16], // NOTE this should be generic over the size of the array
//! ) -> impl Generator<Return = Result<(S, [u8; 16]), S::Error>, Yield = ()>
//! where
//! S: hal::spi::FullDuplex<u8>,
//! {
//! move || {
//! let n = buffer.len();
//! for i in 0..n {
//! nb::r#await!(spi.try_send(buffer[i]))?;
//! buffer[i] = nb::r#await!(spi.try_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 embedded_hal as hal;
//! use nb;
//!
//! use hal::prelude::*;
//! use ::core::convert::Infallible;
Expand Down Expand Up @@ -666,7 +539,7 @@
//! # fn deref_mut(&mut self) -> &mut T { self.0 }
//! # }
//! # struct Serial1;
//! # impl ::hal::serial::Write<u8> for Serial1 {
//! # impl hal::serial::Write<u8> for Serial1 {
//! # type Error = Infallible;
//! # fn try_write(&mut self, _: u8) -> nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) }
//! # fn try_flush(&mut self) -> nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) }
Expand Down