diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d20d181..6d7f6b30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed +- [breaking-change] Depend on `embedded-error` to provide universal error types - [breaking-change] Updated synopsys-usb-otg dependency to v0.2.0. - Cleanups to the Sdio driver, some hw independent functionality moved to the new sdio-host library. - [breaking-change] Sdio is disabled by default, enable with the `sdio` feature flag. diff --git a/Cargo.toml b/Cargo.toml index e90fd66c..ecb48268 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ stm32f4 = "0.11" synopsys-usb-otg = { version = "0.2.0", features = ["cortex-m"], optional = true } sdio-host = { version = "0.5.0", optional = true } embedded-dma = "0.1.0" +embedded-error = "0.6" [dependencies.bare-metal] version = "0.2.5" diff --git a/src/gpio.rs b/src/gpio.rs index ee63ed83..618ddfc0 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -242,7 +242,7 @@ macro_rules! gpio { /// GPIO pub mod $gpiox { use core::marker::PhantomData; - use core::convert::Infallible; + use crate::prelude::*; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable}; use crate::pac::$GPIOX; @@ -294,7 +294,7 @@ macro_rules! gpio { } impl OutputPin for $PXx> { - type Error = Infallible; + type Error = GpioError; fn set_high(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register @@ -323,7 +323,7 @@ macro_rules! gpio { impl toggleable::Default for $PXx> {} impl InputPin for $PXx> { - type Error = Infallible; + type Error = GpioError; fn is_high(&self) -> Result { self.is_low().map(|v| !v) @@ -336,7 +336,7 @@ macro_rules! gpio { } impl InputPin for $PXx> { - type Error = Infallible; + type Error = GpioError; fn is_high(&self) -> Result { self.is_low().map(|v| !v) @@ -755,7 +755,7 @@ macro_rules! gpio { } impl OutputPin for $PXi> { - type Error = Infallible; + type Error = GpioError; fn set_high(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register @@ -784,7 +784,7 @@ macro_rules! gpio { impl toggleable::Default for $PXi> {} impl InputPin for $PXi> { - type Error = Infallible; + type Error = GpioError; fn is_high(&self) -> Result { self.is_low().map(|v| !v) @@ -797,7 +797,7 @@ macro_rules! gpio { } impl InputPin for $PXi> { - type Error = Infallible; + type Error = GpioError; fn is_high(&self) -> Result { self.is_low().map(|v| !v) diff --git a/src/i2c.rs b/src/i2c.rs index fdde665d..2e50f72c 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -1,6 +1,8 @@ use core::ops::Deref; use embedded_hal::blocking::i2c::{Read, Write, WriteRead}; +use crate::prelude::*; + use crate::{bb, pac::i2c1}; #[cfg(any( @@ -546,16 +548,6 @@ impl PinScl for PF14> {} #[cfg(any(feature = "stm32f413", feature = "stm32f423",))] impl PinScl for PF15> {} -#[derive(Debug)] -pub enum Error { - OVERRUN, - NACK, - TIMEOUT, - BUS, - CRC, - ARBITRATION, -} - #[cfg(any( feature = "stm32f401", feature = "stm32f405", @@ -786,39 +778,39 @@ where self.i2c.cr1.modify(|_, w| w.pe().set_bit()); } - fn check_and_clear_error_flags(&self) -> Result { + fn check_and_clear_error_flags(&self) -> Result { // Note that flags should only be cleared once they have been registered. If flags are // cleared otherwise, there may be an inherent race condition and flags may be missed. let sr1 = self.i2c.sr1.read(); if sr1.timeout().bit_is_set() { self.i2c.sr1.modify(|_, w| w.timeout().clear_bit()); - return Err(Error::TIMEOUT); + return Err(I2cError::Timeout); } if sr1.pecerr().bit_is_set() { self.i2c.sr1.modify(|_, w| w.pecerr().clear_bit()); - return Err(Error::CRC); + return Err(I2cError::PacketErrorChecking); } if sr1.ovr().bit_is_set() { self.i2c.sr1.modify(|_, w| w.ovr().clear_bit()); - return Err(Error::OVERRUN); + return Err(I2cError::Overrun); } if sr1.af().bit_is_set() { self.i2c.sr1.modify(|_, w| w.af().clear_bit()); - return Err(Error::NACK); + return Err(I2cError::NACK); } if sr1.arlo().bit_is_set() { self.i2c.sr1.modify(|_, w| w.arlo().clear_bit()); - return Err(Error::ARBITRATION); + return Err(I2cError::ArbitrationLoss); } if sr1.berr().bit_is_set() { self.i2c.sr1.modify(|_, w| w.berr().clear_bit()); - return Err(Error::BUS); + return Err(I2cError::Bus); } Ok(sr1) @@ -830,18 +822,18 @@ where } trait I2cCommon { - fn write_bytes(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error>; + fn write_bytes(&mut self, addr: u8, bytes: &[u8]) -> Result<(), I2cError>; - fn send_byte(&self, byte: u8) -> Result<(), Error>; + fn send_byte(&self, byte: u8) -> Result<(), I2cError>; - fn recv_byte(&self) -> Result; + fn recv_byte(&self) -> Result; } impl I2cCommon for I2c where I2C: Deref, { - fn write_bytes(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { + fn write_bytes(&mut self, addr: u8, bytes: &[u8]) -> Result<(), I2cError> { // Send a START condition self.i2c.cr1.modify(|_, w| w.start().set_bit()); @@ -882,7 +874,7 @@ where Ok(()) } - fn send_byte(&self, byte: u8) -> Result<(), Error> { + fn send_byte(&self, byte: u8) -> Result<(), I2cError> { // Wait until we're ready for sending while { // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. @@ -901,7 +893,7 @@ where Ok(()) } - fn recv_byte(&self) -> Result { + fn recv_byte(&self) -> Result { while { // Check for any potential error conditions. self.check_and_clear_error_flags()?; @@ -918,7 +910,7 @@ impl WriteRead for I2c where I2C: Deref, { - type Error = Error; + type Error = I2cError; fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { self.write_bytes(addr, bytes)?; @@ -932,7 +924,7 @@ impl Write for I2c where I2C: Deref, { - type Error = Error; + type Error = I2cError; fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { self.write_bytes(addr, bytes)?; @@ -952,7 +944,7 @@ impl Read for I2c where I2C: Deref, { - type Error = Error; + type Error = I2cError; fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { if let Some((last, buffer)) = buffer.split_last_mut() { @@ -1003,7 +995,7 @@ where // Fallthrough is success Ok(()) } else { - Err(Error::OVERRUN) + Err(Self::Error::Overrun) } } } @@ -1073,19 +1065,19 @@ where (self.i2c, self.pins) } - fn check_and_clear_error_flags(&self, isr: &fmpi2c::isr::R) -> Result<(), Error> { + fn check_and_clear_error_flags(&self, isr: &fmpi2c::isr::R) -> Result<(), I2cError> { // If we received a NACK, then this is an error if isr.nackf().bit_is_set() { self.i2c .icr .write(|w| w.stopcf().set_bit().nackcf().set_bit()); - return Err(Error::NACK); + return Err(I2cError::NACK); } Ok(()) } - fn send_byte(&self, byte: u8) -> Result<(), Error> { + fn send_byte(&self, byte: u8) -> Result<(), I2cError> { // Wait until we're ready for sending while { let isr = self.i2c.isr.read(); @@ -1100,7 +1092,7 @@ where Ok(()) } - fn recv_byte(&self) -> Result { + fn recv_byte(&self) -> Result { while { let isr = self.i2c.isr.read(); self.check_and_clear_error_flags(&isr)?; @@ -1117,9 +1109,9 @@ impl WriteRead for FMPI2c where I2C: Deref, { - type Error = Error; + type Error = I2cError; - fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { + fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { // Set up current slave address for writing and disable autoending self.i2c.cr2.modify(|_, w| unsafe { w.sadd1_7() @@ -1187,9 +1179,9 @@ impl Read for FMPI2c where I2C: Deref, { - type Error = Error; + type Error = I2cError; - fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { + fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { // Set up current address for reading self.i2c.cr2.modify(|_, w| unsafe { w.sadd1_7() @@ -1223,9 +1215,9 @@ impl Write for FMPI2c where I2C: Deref, { - type Error = Error; + type Error = I2cError; - fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { // Set up current slave address for writing and enable autoending self.i2c.cr2.modify(|_, w| unsafe { w.sadd1_7() diff --git a/src/prelude.rs b/src/prelude.rs index f4dd80fc..09ab4bf1 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,3 +1,4 @@ +pub use embedded_error::*; pub use embedded_hal::digital::v2::InputPin as _embedded_hal_digital_v2_InputPin; pub use embedded_hal::digital::v2::OutputPin as _embedded_hal_digital_v2_OutputPin; pub use embedded_hal::digital::v2::StatefulOutputPin as _embedded_hal_digital_v2_StatefulOutputPin; diff --git a/src/serial.rs b/src/serial.rs index 2c723926..8f97e2da 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -7,6 +7,8 @@ use embedded_hal::prelude::*; use embedded_hal::serial; use nb::block; +use crate::prelude::*; + #[cfg(any( feature = "stm32f401", feature = "stm32f405", @@ -377,21 +379,6 @@ use crate::rcc::Clocks; use crate::dma::traits::PeriAddress; -/// Serial error -#[derive(Debug)] -pub enum Error { - /// Framing error - Framing, - /// Noise error - Noise, - /// RX buffer overrun - Overrun, - /// Parity check error - Parity, - #[doc(hidden)] - _Extensible, -} - /// Interrupt event pub enum Event { /// New data has been received @@ -1545,9 +1532,9 @@ macro_rules! halUsartImpl { } impl serial::Read for Serial<$USARTX, PINS> { - type Error = Error; + type Error = SerialError; - fn read(&mut self) -> nb::Result { + fn read(&mut self) -> nb::Result { let mut rx: Rx<$USARTX> = Rx { _usart: PhantomData, }; @@ -1556,9 +1543,9 @@ macro_rules! halUsartImpl { } impl serial::Read for Rx<$USARTX> { - type Error = Error; + type Error = SerialError; - fn read(&mut self) -> nb::Result { + fn read(&mut self) -> nb::Result { // NOTE(unsafe) atomic read with no side effects let sr = unsafe { (*$USARTX::ptr()).sr.read() }; @@ -1572,13 +1559,13 @@ macro_rules! halUsartImpl { } Err(if sr.pe().bit_is_set() { - nb::Error::Other(Error::Parity) + nb::Error::Other(Self::Error::Parity) } else if sr.fe().bit_is_set() { - nb::Error::Other(Error::Framing) + nb::Error::Other(Self::Error::FrameFormat) } else if sr.nf().bit_is_set() { - nb::Error::Other(Error::Noise) + nb::Error::Other(Self::Error::Noise) } else if sr.ore().bit_is_set() { - nb::Error::Other(Error::Overrun) + nb::Error::Other(Self::Error::Overrun) } else if sr.rxne().bit_is_set() { // NOTE(read_volatile) see `write_volatile` below return Ok(unsafe { ptr::read_volatile(&(*$USARTX::ptr()).dr as *const _ as *const _) }); @@ -1598,7 +1585,7 @@ macro_rules! halUsartImpl { } impl serial::Write for Serial<$USARTX, PINS> { - type Error = Error; + type Error = SerialError; fn flush(&mut self) -> nb::Result<(), Self::Error> { let mut tx: Tx<$USARTX> = Tx { @@ -1625,7 +1612,7 @@ macro_rules! halUsartImpl { } impl serial::Write for Tx<$USARTX> { - type Error = Error; + type Error = SerialError; fn flush(&mut self) -> nb::Result<(), Self::Error> { // NOTE(unsafe) atomic read with no side effects @@ -1654,7 +1641,7 @@ macro_rules! halUsartImpl { } impl blocking::serial::Write for Tx<$USARTX> { - type Error = Error; + type Error = SerialError; fn bwrite_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { for &b in bytes { @@ -1681,7 +1668,7 @@ macro_rules! halUsartImpl { } impl blocking::serial::Write for Serial<$USARTX, PINS> { - type Error = Error; + type Error = SerialError; fn bwrite_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { let mut tx: Tx<$USARTX> = Tx { diff --git a/src/spi.rs b/src/spi.rs index f1265a38..9644ee07 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -5,6 +5,8 @@ use crate::bb; use embedded_hal::spi; pub use embedded_hal::spi::{Mode, Phase, Polarity}; +use crate::prelude::*; + #[cfg(any( feature = "stm32f401", feature = "stm32f405", @@ -351,19 +353,6 @@ use crate::gpio::{Alternate, AF5, AF6}; use crate::rcc::Clocks; use crate::time::Hertz; -/// SPI error -#[derive(Debug)] -pub enum Error { - /// Overrun occurred - Overrun, - /// Mode fault occurred - ModeFault, - /// CRC error - Crc, - #[doc(hidden)] - _Extensible, -} - pub trait Pins {} pub trait PinSck {} pub trait PinMiso {} @@ -1030,17 +1019,17 @@ impl spi::FullDuplex for Spi where SPI: Deref, { - type Error = Error; + type Error = SpiError; - fn read(&mut self) -> nb::Result { + fn read(&mut self) -> nb::Result { let sr = self.spi.sr.read(); Err(if sr.ovr().bit_is_set() { - nb::Error::Other(Error::Overrun) + nb::Error::Other(Self::Error::Overrun) } else if sr.modf().bit_is_set() { - nb::Error::Other(Error::ModeFault) + nb::Error::Other(Self::Error::ModeFault) } else if sr.crcerr().bit_is_set() { - nb::Error::Other(Error::Crc) + nb::Error::Other(Self::Error::CRCError) } else if sr.rxne().bit_is_set() { // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows // reading a half-word) @@ -1050,15 +1039,15 @@ where }) } - fn send(&mut self, byte: u8) -> nb::Result<(), Error> { + fn send(&mut self, byte: u8) -> nb::Result<(), Self::Error> { let sr = self.spi.sr.read(); Err(if sr.ovr().bit_is_set() { - nb::Error::Other(Error::Overrun) + nb::Error::Other(Self::Error::Overrun) } else if sr.modf().bit_is_set() { - nb::Error::Other(Error::ModeFault) + nb::Error::Other(Self::Error::ModeFault) } else if sr.crcerr().bit_is_set() { - nb::Error::Other(Error::Crc) + nb::Error::Other(Self::Error::CRCError) } else if sr.txe().bit_is_set() { // NOTE(write_volatile) see note above unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, byte) }