251: Update reference implementation implementation to stm32f1xx-hal and update examples r=therealprof a=eldruin

I think the `stm32f1xx-hal` is a good candidate for a reference implementation.
I have also updated the examples accordingly and modernized them a bit.

An additional possibility would be to remove the `futures` examples as well, since async handling will be different.

Closes #156 

Co-authored-by: Diego Barrios Romero <eldruin@gmail.com>
This commit is contained in:
bors[bot]
2020-10-06 20:02:02 +00:00
committed by GitHub
2 changed files with 55 additions and 179 deletions

View File

@@ -20,3 +20,6 @@ nb = "1"
[dev-dependencies]
futures = "0.1.17"
[dev-dependencies.stm32f1]
version = "0.12"
features = ["stm32f103", "rt"]

View File

@@ -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
//!
@@ -64,7 +64,7 @@
//! Here's how a HAL trait may look like:
//!
//! ```
//! extern crate nb;
//! use nb;
//!
//! /// A serial interface
//! pub trait Serial {
@@ -90,7 +90,7 @@
//! those cases `nb::Result<_, Infallible>` is used.
//!
//! ```
//! extern crate nb;
//! use nb;
//!
//! # use std as core;
//! use ::core::convert::Infallible;
@@ -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
@@ -185,13 +183,10 @@
//!
//! ## 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
//!
@@ -199,12 +194,9 @@
//! 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 = {
@@ -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(())
//! # }
//! # }
@@ -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`
@@ -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()))
//! })
@@ -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)))
//! })
@@ -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()))
//! })
@@ -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 = ();
//! #
@@ -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) }
@@ -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
@@ -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>
@@ -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::*;
//!
@@ -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;
@@ -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) }