diff --git a/rp2040-hal/Cargo.toml b/rp2040-hal/Cargo.toml index a6b14d7..6c1d68e 100644 --- a/rp2040-hal/Cargo.toml +++ b/rp2040-hal/Cargo.toml @@ -12,7 +12,7 @@ license = "MIT OR Apache-2.0" [dependencies] cortex-m = "0.7.2" embedded-hal = { version = "0.2.5", features = ["unproven"] } -eh1_0_alpha = { version = "=1.0.0-alpha.5", package="embedded-hal", optional=true } +eh1_0_alpha = { version = "=1.0.0-alpha.6", package="embedded-hal", optional=true } embedded-time = "0.12.0" itertools = { version = "0.10.1", default-features = false } nb = "1.0" diff --git a/rp2040-hal/src/i2c.rs b/rp2040-hal/src/i2c.rs index 3778419..e0994b2 100644 --- a/rp2040-hal/src/i2c.rs +++ b/rp2040-hal/src/i2c.rs @@ -79,6 +79,31 @@ pub enum Error { AddressReserved(u16), } +#[cfg(feature = "eh1_0_alpha")] +impl eh1_0_alpha::i2c::Error for Error { + fn kind(&self) -> eh1_0_alpha::i2c::ErrorKind { + match &self { + Error::Abort(v) if v & 1<<12 != 0 // ARB_LOST + => eh1_0_alpha::i2c::ErrorKind::ArbitrationLoss, + Error::Abort(v) if v & 1<<7 != 0 // ABRT_SBYTE_ACKDET + => eh1_0_alpha::i2c::ErrorKind::Bus, + Error::Abort(v) if v & 1<<6 != 0 // ABRT_HS_ACKDET + => eh1_0_alpha::i2c::ErrorKind::Bus, + Error::Abort(v) if v & 1<<4 != 0 // ABRT_GCALL_NOACK + => eh1_0_alpha::i2c::ErrorKind::NoAcknowledge(eh1_0_alpha::i2c::NoAcknowledgeSource::Address), + Error::Abort(v) if v & 1<<3 != 0 // ABRT_TXDATA_NOACK + => eh1_0_alpha::i2c::ErrorKind::NoAcknowledge(eh1_0_alpha::i2c::NoAcknowledgeSource::Data), + Error::Abort(v) if v & 1<<2 != 0 // ABRT_10ADDR2_NOACK + => eh1_0_alpha::i2c::ErrorKind::NoAcknowledge(eh1_0_alpha::i2c::NoAcknowledgeSource::Address), + Error::Abort(v) if v & 1<<1 != 0 // ABRT_10ADDR1_NOACK + => eh1_0_alpha::i2c::ErrorKind::NoAcknowledge(eh1_0_alpha::i2c::NoAcknowledgeSource::Address), + Error::Abort(v) if v & 1<<0 != 0 // ABRT_7B_ADDR_NOACK + => eh1_0_alpha::i2c::ErrorKind::NoAcknowledge(eh1_0_alpha::i2c::NoAcknowledgeSource::Address), + _ => eh1_0_alpha::i2c::ErrorKind::Other, + } + } +} + /// SCL pin pub trait SclPin: Sealed {} diff --git a/rp2040-hal/src/i2c/controller.rs b/rp2040-hal/src/i2c/controller.rs index 8d70e00..212bf58 100644 --- a/rp2040-hal/src/i2c/controller.rs +++ b/rp2040-hal/src/i2c/controller.rs @@ -278,7 +278,7 @@ impl, PINS> Write for I2C { impl, PINS> eh1::Write for I2C { type Error = Error; - fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { + fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { Write::write(self, addr, bytes) } } diff --git a/rp2040-hal/src/spi.rs b/rp2040-hal/src/spi.rs index 131d6cc..babc486 100644 --- a/rp2040-hal/src/spi.rs +++ b/rp2040-hal/src/spi.rs @@ -186,6 +186,29 @@ impl Spi { } } +/// Same as core::convert::Infallible, but implementing spi::Error +/// +/// For eh 1.0.0-alpha.6, Infallible doesn't implement spi::Error, +/// so use a locally defined type instead. +/// This should be removed with the next release of e-h. +/// (https://github.com/rust-embedded/embedded-hal/pull/328) +#[cfg(feature = "eh1_0_alpha")] +pub enum SpiInfallible {} + +#[cfg(feature = "eh1_0_alpha")] +impl core::fmt::Debug for SpiInfallible { + fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match *self {} + } +} + +#[cfg(feature = "eh1_0_alpha")] +impl eh1::Error for SpiInfallible { + fn kind(&self) -> eh1::ErrorKind { + match *self {} + } +} + macro_rules! impl_write { ($type:ident, [$($nr:expr),+]) => { @@ -221,16 +244,16 @@ macro_rules! impl_write { #[cfg(feature = "eh1_0_alpha")] impl eh1::nb::FullDuplex<$type> for Spi { - type Error = Infallible; + type Error = SpiInfallible; - fn read(&mut self) -> Result<$type, nb::Error> { + fn read(&mut self) -> Result<$type, nb::Error> { if !self.is_readable() { return Err(nb::Error::WouldBlock); } Ok(self.device.sspdr.read().data().bits() as $type) } - fn write(&mut self, word: $type) -> Result<(), nb::Error> { + fn write(&mut self, word: $type) -> Result<(), nb::Error> { // Write to TX FIFO whilst ignoring RX, then clean up afterward. When RX // is full, PL022 inhibits RX pushes, and sets a sticky flag on // push-on-full, but continues shifting. Safe if SSPIMSC_RORIM is not set. diff --git a/rp2040-hal/src/uart.rs b/rp2040-hal/src/uart.rs index a842321..0bd3f49 100644 --- a/rp2040-hal/src/uart.rs +++ b/rp2040-hal/src/uart.rs @@ -82,6 +82,18 @@ pub enum ReadErrorType { Framing, } +#[cfg(feature = "eh1_0_alpha")] +impl eh1_0_alpha::serial::Error for ReadErrorType { + fn kind(&self) -> eh1_0_alpha::serial::ErrorKind { + match self { + ReadErrorType::Overrun => eh1_0_alpha::serial::ErrorKind::Overrun, + ReadErrorType::Break => eh1_0_alpha::serial::ErrorKind::Other, + ReadErrorType::Parity => eh1_0_alpha::serial::ErrorKind::Parity, + ReadErrorType::Framing => eh1_0_alpha::serial::ErrorKind::FrameFormat, + } + } +} + /// State of the UART Peripheral. pub trait State {} @@ -516,6 +528,29 @@ impl eh1::Read for UartPeripheral { } } +/// Same as core::convert::Infallible, but implementing spi::Error +/// +/// For eh 1.0.0-alpha.6, Infallible doesn't implement spi::Error, +/// so use a locally defined type instead. +/// This should be removed with the next release of e-h. +/// (https://github.com/rust-embedded/embedded-hal/pull/328) +#[cfg(feature = "eh1_0_alpha")] +pub enum SerialInfallible {} + +#[cfg(feature = "eh1_0_alpha")] +impl core::fmt::Debug for SerialInfallible { + fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match *self {} + } +} + +#[cfg(feature = "eh1_0_alpha")] +impl eh1_0_alpha::serial::Error for SerialInfallible { + fn kind(&self) -> eh1_0_alpha::serial::ErrorKind { + match *self {} + } +} + impl Write for UartPeripheral { type Error = Infallible; @@ -534,7 +569,7 @@ impl Write for UartPeripheral { #[cfg(feature = "eh1_0_alpha")] impl eh1::Write for UartPeripheral { - type Error = Infallible; + type Error = SerialInfallible; fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { if self.write_raw(&[word]).is_err() { @@ -545,7 +580,10 @@ impl eh1::Write for UartPeripheral { } fn flush(&mut self) -> nb::Result<(), Self::Error> { - self.transmit_flushed() + self.transmit_flushed().map_err(|e| match e { + WouldBlock => WouldBlock, + Other(v) => match v {}, + }) } }