From 1a511f90dafa4643c5fd41cde44f497d4fd0fae2 Mon Sep 17 00:00:00 2001 From: Ales Katona Date: Sat, 25 Jun 2022 10:33:56 -0700 Subject: [PATCH 1/3] support embedded-hal v1.0.0-alpha.7 --- .github/workflows/ci.yaml | 4 +- CHANGELOG.md | 2 + Cargo.toml | 8 +- README.md | 2 +- src/delay.rs | 93 ++---------- src/gpio.rs | 13 +- src/i2c.rs | 280 +++++++++++++++++++++++++++++++----- src/prelude.rs | 7 +- src/serial.rs | 19 +-- src/spi.rs | 4 +- src/spi/bus.rs | 49 ++++--- src/spi/exclusive_device.rs | 57 ++++---- src/spi/shared_device.rs | 64 +++++---- src/stdout.rs | 2 +- 14 files changed, 393 insertions(+), 211 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2addd1a..4366937 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -11,8 +11,8 @@ jobs: continue-on-error: ${{ matrix.experimental || false }} strategy: matrix: - # All generated code should be running on stable now, MRSV is 1.42.0 - rust: [nightly, stable, 1.42.0] + # All generated code should be running on stable now, MRSV is 1.59.0 + rust: [nightly, stable, 1.59.0] include: # Nightly is only for reference and allowed to fail diff --git a/CHANGELOG.md b/CHANGELOG.md index 9966133..fa3c7fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +- Updated to support `embedded-hal` version `1.0.0-alpha.7` + - Refactored `e310x-hal::spi` module, splitting the abstraction into `SpiBus` and `SpiExclusiveDevice/SpiSharedDevice` to allow multiple devices on a single SPI bus to co-exist ## [v0.9.3] - 2021-08-15 diff --git a/Cargo.toml b/Cargo.toml index e79aed9..26334fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "e310x-hal" -version = "0.9.3" +version = "0.10.0-alpha.1" authors = ["David Craven "] repository = "https://github.com/riscv-rust/e310x-hal" categories = ["embedded", "hardware-support", "no-std"] @@ -10,10 +10,10 @@ license = "ISC" edition = "2018" [dependencies] -embedded-hal = { version = "0.2.6", features = ["unproven"] } +embedded-hal = "=1.0.0-alpha.7" nb = "1.0.0" -riscv = "0.7.0" -e310x = { version = "0.9.0", features = ["rt"] } +riscv = "0.8.0" +e310x = { version = "0.9.1", features = ["rt"] } [features] g002 = ["e310x/g002"] diff --git a/README.md b/README.md index 81455da..bf2f875 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This project is developed and maintained by the [RISC-V team][team]. ## Minimum Supported Rust Version (MSRV) -This crate is guaranteed to compile on stable Rust 1.42.0 and up. It *might* +This crate is guaranteed to compile on stable Rust 1.59.0 and up. It *might* compile with older versions but that may change in any new patch release. ## License diff --git a/src/delay.rs b/src/delay.rs index 4778bf1..30b42e6 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -2,7 +2,8 @@ use crate::clock::Clocks; use crate::core::clint::{MTIME, MTIMECMP}; -use embedded_hal::blocking::delay::{DelayMs, DelayUs}; +use core::convert::Infallible; +use embedded_hal::delay::blocking::DelayUs; use riscv::register::{mie, mip}; /// Machine timer (mtime) as a busyloop delay provider @@ -17,65 +18,16 @@ impl Delay { } } -impl DelayUs for Delay { - fn delay_us(&mut self, us: u32) { +impl DelayUs for Delay { + type Error = Infallible; + + fn delay_us(&mut self, us: u32) -> Result<(), Infallible> { let ticks = (us as u64) * TICKS_PER_SECOND / 1_000_000; let mtime = MTIME; let t = mtime.mtime() + ticks; while mtime.mtime() < t {} - } -} - -// This is a workaround to allow `delay_us(42)` construction without specifying a type. -impl DelayUs for Delay { - #[inline(always)] - fn delay_us(&mut self, us: i32) { - assert!(us >= 0); - self.delay_us(us as u32); - } -} - -impl DelayUs for Delay { - #[inline(always)] - fn delay_us(&mut self, us: u16) { - self.delay_us(u32::from(us)); - } -} - -impl DelayUs for Delay { - #[inline(always)] - fn delay_us(&mut self, us: u8) { - self.delay_us(u32::from(us)); - } -} - -impl DelayMs for Delay { - fn delay_ms(&mut self, ms: u32) { - self.delay_us(ms * 1000); - } -} - -// This is a workaround to allow `delay_ms(42)` construction without specifying a type. -impl DelayMs for Delay { - #[inline(always)] - fn delay_ms(&mut self, ms: i32) { - assert!(ms >= 0); - self.delay_ms(ms as u32); - } -} - -impl DelayMs for Delay { - #[inline(always)] - fn delay_ms(&mut self, ms: u16) { - self.delay_ms(u32::from(ms)); - } -} - -impl DelayMs for Delay { - #[inline(always)] - fn delay_ms(&mut self, ms: u8) { - self.delay_ms(u32::from(ms)); + Ok(()) } } @@ -95,9 +47,11 @@ impl Sleep { } } -impl DelayMs for Sleep { - fn delay_ms(&mut self, ms: u32) { - let ticks = (ms as u64) * (self.clock_freq as u64) / 1000; +impl DelayUs for Sleep { + type Error = Infallible; + + fn delay_us(&mut self, us: u32) -> Result<(), Infallible> { + let ticks = (us as u64) * (self.clock_freq as u64) / 1_000_000; let t = MTIME.mtime() + ticks; self.mtimecmp.set_mtimecmp(t); @@ -126,28 +80,7 @@ impl DelayMs for Sleep { unsafe { mie::clear_mtimer(); } - } -} - -// This is a workaround to allow `delay_ms(42)` construction without specifying a type. -impl DelayMs for Sleep { - #[inline(always)] - fn delay_ms(&mut self, ms: i32) { - assert!(ms >= 0); - self.delay_ms(ms as u32); - } -} - -impl DelayMs for Sleep { - #[inline(always)] - fn delay_ms(&mut self, ms: u16) { - self.delay_ms(u32::from(ms)); - } -} -impl DelayMs for Sleep { - #[inline(always)] - fn delay_ms(&mut self, ms: u8) { - self.delay_ms(u32::from(ms)); + Ok(()) } } diff --git a/src/gpio.rs b/src/gpio.rs index 63239f0..be0b294 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -142,7 +142,8 @@ macro_rules! gpio { use core::marker::PhantomData; use core::convert::Infallible; - use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, + use embedded_hal::digital::ErrorType; + use embedded_hal::digital::blocking::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin}; use e310x::$GPIOX; use super::{Unknown, IOF0, IOF1, Drive, Floating, GpioExt, Input, Invert, @@ -275,9 +276,11 @@ macro_rules! gpio { } } - impl InputPin for $PXi> { + impl ErrorType for $PXi> { type Error = Infallible; + } + impl InputPin for $PXi> { fn is_high(&self) -> Result { Ok($GPIOX::input_value(Self::INDEX)) @@ -298,9 +301,11 @@ macro_rules! gpio { } } - impl OutputPin for $PXi> { + impl ErrorType for $PXi> { type Error = Infallible; + } + impl OutputPin for $PXi> { fn set_high(&mut self) -> Result<(), Infallible> { $GPIOX::set_output_value(Self::INDEX, true); Ok(()) @@ -313,8 +318,6 @@ macro_rules! gpio { } impl ToggleableOutputPin for $PXi> { - type Error = Infallible; - /// Toggles the pin state. fn toggle(&mut self) -> Result<(), Infallible> { $GPIOX::toggle_pin(Self::INDEX); diff --git a/src/i2c.rs b/src/i2c.rs index d969add..e0e049a 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -16,7 +16,8 @@ use crate::time::Bps; use core::mem; use core::ops::Deref; use e310x::{i2c0, I2C0}; -use embedded_hal::blocking::i2c::{Read, Write, WriteRead}; +use embedded_hal::i2c::blocking::{self as i2c, Operation}; +use embedded_hal::i2c::{ErrorKind, ErrorType, NoAcknowledgeSource}; /// SDA pin - DO NOT IMPLEMENT THIS TRAIT pub unsafe trait SdaPin {} @@ -26,19 +27,6 @@ pub unsafe trait SclPin {} unsafe impl SdaPin for gpio0::Pin12> {} unsafe impl SclPin for gpio0::Pin13> {} -/// I2C error -#[derive(Debug, Eq, PartialEq)] -pub enum Error { - /// Invalid peripheral state - InvalidState, - - /// Arbitration lost - ArbitrationLost, - - /// No ACK received - NoAck, -} - /// Transmission speed pub enum Speed { /// 100Kbps @@ -121,7 +109,7 @@ impl, PINS> I2c { } fn read_sr(&self) -> i2c0::sr::R { - unsafe { mem::transmute(self.i2c.sr().read()) } + self.i2c.sr().read() } fn write_byte(&self, byte: u8) { @@ -132,7 +120,7 @@ impl, PINS> I2c { self.i2c.txr_rxr.read().data().bits() } - fn wait_for_interrupt(&self) -> Result<(), Error> { + fn wait_for_interrupt(&self) -> Result<(), ErrorKind> { loop { let sr = self.read_sr(); @@ -141,7 +129,7 @@ impl, PINS> I2c { self.write_cr(|w| w.sto().set_bit()); self.wait_for_complete(); - return Err(Error::ArbitrationLost); + return Err(ErrorKind::ArbitrationLoss); } if sr.if_().bit_is_set() { @@ -153,11 +141,11 @@ impl, PINS> I2c { } } - fn wait_for_read(&self) -> Result<(), Error> { + fn wait_for_read(&self) -> Result<(), ErrorKind> { self.wait_for_interrupt() } - fn wait_for_write(&self) -> Result<(), Error> { + fn wait_for_write(&self) -> Result<(), ErrorKind> { self.wait_for_interrupt()?; if self.read_sr().rx_ack().bit_is_set() { @@ -165,7 +153,7 @@ impl, PINS> I2c { self.write_cr(|w| w.sto().set_bit()); self.wait_for_complete(); - return Err(Error::NoAck); + return Err(ErrorKind::NoAcknowledge(NoAcknowledgeSource::Unknown)); } Ok(()) @@ -179,14 +167,16 @@ impl, PINS> I2c { const FLAG_READ: u8 = 1; const FLAG_WRITE: u8 = 0; -impl, PINS> Read for I2c { - type Error = Error; +impl ErrorType for I2c { + type Error = ErrorKind; +} +impl, PINS> i2c::I2c for I2c { fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { self.reset(); if self.read_sr().busy().bit_is_set() { - return Err(Error::InvalidState); + return Err(ErrorKind::Other); } // Write address + R @@ -212,16 +202,12 @@ impl, PINS> Read for I2c { } Ok(()) } -} - -impl, PINS> Write for I2c { - type Error = Error; fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { self.reset(); if self.read_sr().busy().bit_is_set() { - return Err(Error::InvalidState); + return Err(ErrorKind::Other); } // Write address + W @@ -244,10 +230,39 @@ impl, PINS> Write for I2c { } Ok(()) } -} -impl, PINS> WriteRead for I2c { - type Error = Error; + fn write_iter>( + &mut self, + address: u8, + bytes: B, + ) -> Result<(), Self::Error> { + self.reset(); + + if self.read_sr().busy().bit_is_set() { + return Err(ErrorKind::Other); + } + + // Write address + W + self.write_byte((address << 1) + FLAG_WRITE); + + // Generate start condition and write command + self.write_cr(|w| w.sta().set_bit().wr().set_bit()); + self.wait_for_write()?; + + // Write bytes + let mut bytes = bytes.into_iter().peekable(); + while let Some(byte) = bytes.next() { + self.write_byte(byte); + + if bytes.peek().is_some() { + self.write_cr(|w| w.wr().set_bit()); // all others + } else { + self.write_cr(|w| w.wr().set_bit().sto().set_bit()); // last one + } + self.wait_for_write()?; + } + Ok(()) + } fn write_read( &mut self, @@ -258,7 +273,7 @@ impl, PINS> WriteRead for I2c, PINS> WriteRead for I2c>( + &mut self, + address: u8, + bytes: B, + buffer: &mut [u8], + ) -> Result<(), Self::Error> { + self.reset(); + + if self.read_sr().busy().bit_is_set() { + return Err(ErrorKind::Other); + } + + let mut bytes = bytes.into_iter().peekable(); + if bytes.peek().is_some() && buffer.is_empty() { + self.write_iter(address, bytes) + } else if !buffer.is_empty() && bytes.peek().is_none() { + self.read(address, buffer) + } else if bytes.peek().is_none() && buffer.is_empty() { + Ok(()) + } else { + // Write address + W + self.write_byte((address << 1) + FLAG_WRITE); + + // Generate start condition and write command + self.write_cr(|w| w.sta().set_bit().wr().set_bit()); + self.wait_for_write()?; + + // Write bytes + for byte in bytes { + self.write_byte(byte); + + self.write_cr(|w| w.wr().set_bit()); + self.wait_for_write()?; + } + + // Write address + R + self.write_byte((address << 1) + FLAG_READ); + + // Generate repeated start condition and write command + self.write_cr(|w| w.sta().set_bit().wr().set_bit()); + self.wait_for_write()?; + + // Read bytes + let buffer_len = buffer.len(); + for (i, byte) in buffer.iter_mut().enumerate() { + if i != buffer_len - 1 { + // W + ACK + self.write_cr(|w| w.rd().set_bit().ack().clear_bit()); + } else { + // W + NACK + STOP + self.write_cr(|w| w.rd().set_bit().ack().set_bit().sto().set_bit()); + } + self.wait_for_read()?; + + *byte = self.read_byte(); + } + + Ok(()) + } + } + + fn transaction<'a>( + &mut self, + address: u8, + operations: &mut [Operation<'a>], + ) -> Result<(), Self::Error> { + self.reset(); + + if self.read_sr().busy().bit_is_set() { + return Err(ErrorKind::Other); + } + + let last_op = operations.len() - 1; + let mut last_flag = 0xFF; + for (i, op) in operations.iter_mut().enumerate() { + match op { + Operation::Read(bytes) => { + if last_flag != FLAG_READ { + // Write address + R + self.write_byte((address << 1) + FLAG_READ); + + // Generate repeated start condition and write command + self.write_cr(|w| w.sta().set_bit().wr().set_bit()); + self.wait_for_write()?; + last_flag = FLAG_READ; + } + + // Read bytes + let last_byte = bytes.len() - 1; + for (j, byte) in bytes.iter_mut().enumerate() { + if i != last_op || j != last_byte { + // W + ACK + self.write_cr(|w| w.rd().set_bit().ack().clear_bit()); + } else { + // W + NACK + STOP + self.write_cr(|w| w.rd().set_bit().ack().set_bit().sto().set_bit()); + } + self.wait_for_read()?; + + *byte = self.read_byte(); + } + } + Operation::Write(bytes) => { + if last_flag != FLAG_WRITE { + // Write address + W + self.write_byte((address << 1) + FLAG_WRITE); + + // Generate start condition and write command + self.write_cr(|w| w.sta().set_bit().wr().set_bit()); + self.wait_for_write()?; + last_flag = FLAG_WRITE; + } + + // Write bytes + for (j, byte) in bytes.iter().enumerate() { + self.write_byte(*byte); + + if i != last_op || j != bytes.len() - 1 { + self.write_cr(|w| w.wr().set_bit()); + } else { + self.write_cr(|w| w.wr().set_bit().sto().set_bit()); + } + self.wait_for_write()?; + } + } + } + } + + Ok(()) + } + + fn transaction_iter<'a, O: IntoIterator>>( + &mut self, + address: u8, + operations: O, + ) -> Result<(), Self::Error> { + self.reset(); + + if self.read_sr().busy().bit_is_set() { + return Err(ErrorKind::Other); + } + + let mut last_flag = 0xFF; + let mut operations = operations.into_iter().peekable(); + while let Some(op) = operations.next() { + match op { + Operation::Read(bytes) => { + if last_flag != FLAG_READ { + // Write address + R + self.write_byte((address << 1) + FLAG_READ); + + // Generate repeated start condition and write command + self.write_cr(|w| w.sta().set_bit().wr().set_bit()); + self.wait_for_write()?; + last_flag = FLAG_READ; + } + + // Read bytes + let last_byte = bytes.len() - 1; + for (j, byte) in bytes.iter_mut().enumerate() { + if operations.peek().is_some() || j != last_byte { + // W + ACK + self.write_cr(|w| w.rd().set_bit().ack().clear_bit()); + } else { + // W + NACK + STOP + self.write_cr(|w| w.rd().set_bit().ack().set_bit().sto().set_bit()); + } + self.wait_for_read()?; + + *byte = self.read_byte(); + } + } + Operation::Write(bytes) => { + if last_flag != FLAG_WRITE { + // Write address + W + self.write_byte((address << 1) + FLAG_WRITE); + + // Generate start condition and write command + self.write_cr(|w| w.sta().set_bit().wr().set_bit()); + self.wait_for_write()?; + last_flag = FLAG_WRITE; + } + + // Write bytes + for (j, byte) in bytes.iter().enumerate() { + self.write_byte(*byte); + + if operations.peek().is_some() || j != bytes.len() - 1 { + self.write_cr(|w| w.wr().set_bit()); + } else { + self.write_cr(|w| w.wr().set_bit().sto().set_bit()); + } + self.wait_for_write()?; + } + } + } + } + + Ok(()) + } } diff --git a/src/prelude.rs b/src/prelude.rs index c6ccd12..a26b75f 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -7,9 +7,4 @@ pub use crate::rtc::RtcExt as _e310x_hal_rtc_RtcExt; pub use crate::stdout::Write as _e310x_hal_stdout_Write; pub use crate::time::U32Ext as _e310x_hal_time_U32Ext; pub use crate::wdog::WdogExt as _e310x_hal_wdog_WdogExt; -pub use embedded_hal::digital::v2::{ - InputPin as _embedded_hal_digital_v2_InputPin, OutputPin as _embedded_hal_digital_v2_OutputPin, - StatefulOutputPin as _embedded_hal_digital_v2_StatefulOutputPin, - ToggleableOutputPin as _embedded_hal_digital_v2_ToggleableOutputPin, -}; -pub use embedded_hal::prelude::*; +pub use embedded_hal::digital::blocking::StatefulOutputPin as _embedded_hal_digital_StatefulOutputPin; diff --git a/src/serial.rs b/src/serial.rs index 0184679..c88c2ac 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -13,7 +13,6 @@ //! - RX: Pin 23 IOF0 //! - Interrupt::UART1 -use core::convert::Infallible; use core::ops::Deref; use embedded_hal::serial; @@ -114,10 +113,12 @@ impl Serial { } } -impl serial::Read for Rx { - type Error = Infallible; +impl serial::ErrorType for Rx { + type Error = serial::ErrorKind; +} - fn read(&mut self) -> nb::Result { +impl serial::nb::Read for Rx { + fn read(&mut self) -> nb::Result { let rxdata = self.uart.rxdata.read(); if rxdata.empty().bit_is_set() { @@ -128,10 +129,12 @@ impl serial::Read for Rx { } } -impl serial::Write for Tx { - type Error = Infallible; +impl serial::ErrorType for Tx { + type Error = serial::ErrorKind; +} - fn write(&mut self, byte: u8) -> nb::Result<(), Infallible> { +impl serial::nb::Write for Tx { + fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { let txdata = self.uart.txdata.read(); if txdata.full().bit_is_set() { @@ -144,7 +147,7 @@ impl serial::Write for Tx { } } - fn flush(&mut self) -> nb::Result<(), Infallible> { + fn flush(&mut self) -> nb::Result<(), Self::Error> { if self.uart.ip.read().txwm().bit_is_set() { // FIFO count is below the receive watermark (1) Ok(()) diff --git a/src/spi.rs b/src/spi.rs index d508849..5c447a2 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -24,7 +24,7 @@ //! - Interrupt::QSPI2 //! //! # Exclusive Bus usage example -//!``` +//!```ignore //! let pins = (mosi, miso, sck, cs0); //! let spi_bus = SpiBus::new(p.QSPI1, pins); //! @@ -35,7 +35,7 @@ //!``` //! //! # Shared Bus usage example -//!``` +//!```ignore //! let pins = (mosi, miso, sck); //! let spi_bus = SpiBus::shared(p.QSPI1, pins); //! diff --git a/src/spi/bus.rs b/src/spi/bus.rs index 94ea72b..921d74b 100644 --- a/src/spi/bus.rs +++ b/src/spi/bus.rs @@ -1,7 +1,7 @@ -use core::convert::Infallible; -use embedded_hal::blocking::spi::Operation; -pub use embedded_hal::blocking::spi::{Transfer, Write, WriteIter}; -pub use embedded_hal::spi::{FullDuplex, Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; +use embedded_hal::spi::blocking::Operation; +pub use embedded_hal::spi::blocking::{Read, Transfer, TransferInplace, Write, WriteIter}; +pub use embedded_hal::spi::nb::FullDuplex; +pub use embedded_hal::spi::{ErrorKind, Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; use nb; @@ -103,7 +103,7 @@ where // ex-traits now only accessible via devices - pub(crate) fn read(&mut self) -> nb::Result { + pub(crate) fn read(&mut self) -> nb::Result { let rxdata = self.spi.rxdata.read(); if rxdata.empty().bit_is_set() { @@ -113,7 +113,7 @@ where } } - pub(crate) fn send(&mut self, byte: u8) -> nb::Result<(), Infallible> { + pub(crate) fn send(&mut self, byte: u8) -> nb::Result<(), ErrorKind> { let txdata = self.spi.txdata.read(); if txdata.full().bit_is_set() { @@ -124,16 +124,16 @@ where } } - pub(crate) fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Infallible> { + pub(crate) fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), ErrorKind> { let mut iwrite = 0; let mut iread = 0; // Ensure that RX FIFO is empty self.wait_for_rxfifo(); - while iwrite < words.len() || iread < words.len() { - if iwrite < words.len() && self.spi.txdata.read().full().bit_is_clear() { - let byte = unsafe { words.get_unchecked(iwrite) }; + while iwrite < write.len() || iread < read.len() { + if iwrite < write.len() && self.spi.txdata.read().full().bit_is_clear() { + let byte = write.get(iwrite).unwrap_or(&0); iwrite += 1; self.spi.txdata.write(|w| unsafe { w.data().bits(*byte) }); } @@ -141,16 +141,18 @@ where if iread < iwrite { let data = self.spi.rxdata.read(); if data.empty().bit_is_clear() { - unsafe { *words.get_unchecked_mut(iread) = data.data().bits() }; + if let Some(d) = read.get_mut(iread) { + *d = data.data().bits() + }; iread += 1; } } } - Ok(words) + Ok(()) } - pub(crate) fn write(&mut self, words: &[u8]) -> Result<(), Infallible> { + pub(crate) fn transfer_inplace(&mut self, words: &mut [u8]) -> Result<(), ErrorKind> { let mut iwrite = 0; let mut iread = 0; @@ -165,8 +167,9 @@ where } if iread < iwrite { - // Read and discard byte, if any - if self.spi.rxdata.read().empty().bit_is_clear() { + let data = self.spi.rxdata.read(); + if data.empty().bit_is_clear() { + unsafe { *words.get_unchecked_mut(iread) = data.data().bits() }; iread += 1; } } @@ -175,7 +178,7 @@ where Ok(()) } - pub(crate) fn write_iter(&mut self, words: WI) -> Result<(), Infallible> + pub(crate) fn write_iter(&mut self, words: WI) -> Result<(), ErrorKind> where WI: IntoIterator, { @@ -211,14 +214,20 @@ where pub(crate) fn exec<'op>( &mut self, operations: &mut [Operation<'op, u8>], - ) -> Result<(), Infallible> { + ) -> Result<(), ErrorKind> { for op in operations { match op { - Operation::Transfer(words) => { - self.transfer(words)?; + Operation::Read(words) => { + self.transfer(words, &[])?; } Operation::Write(words) => { - self.write(words)?; + self.transfer(&mut [], words)?; + } + Operation::Transfer(read_words, write_words) => { + self.transfer(read_words, write_words)?; + } + Operation::TransferInplace(words) => { + self.transfer_inplace(words)?; } } } diff --git a/src/spi/exclusive_device.rs b/src/spi/exclusive_device.rs index d9e808e..367ac15 100644 --- a/src/spi/exclusive_device.rs +++ b/src/spi/exclusive_device.rs @@ -1,8 +1,7 @@ -use core::convert::Infallible; - -use embedded_hal::{ - blocking::spi::{Operation, Transactional, Transfer, Write, WriteIter}, - spi::FullDuplex, +use embedded_hal::spi::{ + blocking::{Operation, Transactional, Transfer, TransferInplace, Write, WriteIter}, + nb::FullDuplex, + ErrorKind, ErrorType, }; use crate::spi::SpiConfig; @@ -36,61 +35,71 @@ where } } -impl FullDuplex for SpiExclusiveDevice +impl ErrorType for SpiExclusiveDevice { + type Error = ErrorKind; +} + +impl FullDuplex for SpiExclusiveDevice where SPI: SpiX, PINS: Pins, { - type Error = Infallible; - - fn read(&mut self) -> nb::Result { + fn read(&mut self) -> nb::Result { self.bus.read() } - fn send(&mut self, byte: u8) -> nb::Result<(), Infallible> { + fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { self.bus.send(byte) } } -impl Transfer for SpiExclusiveDevice +impl Transfer for SpiExclusiveDevice where SPI: SpiX, PINS: Pins, { - type Error = Infallible; - - fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { + fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { self.bus.start_frame(); - let result = self.bus.transfer(words); + let result = self.bus.transfer(read, write); self.bus.end_frame(); result } } -impl Write for SpiExclusiveDevice +impl TransferInplace for SpiExclusiveDevice where SPI: SpiX, PINS: Pins, { - type Error = Infallible; + fn transfer_inplace<'w>(&mut self, words: &'w mut [u8]) -> Result<(), Self::Error> { + self.bus.start_frame(); + let result = self.bus.transfer_inplace(words); + self.bus.end_frame(); + result + } +} + +impl Write for SpiExclusiveDevice +where + SPI: SpiX, + PINS: Pins, +{ fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { self.bus.start_frame(); - let result = self.bus.write(words); + let result = self.bus.transfer(&mut [], words); self.bus.end_frame(); result } } -impl WriteIter for SpiExclusiveDevice +impl WriteIter for SpiExclusiveDevice where SPI: SpiX, PINS: Pins, { - type Error = Infallible; - fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> where WI: IntoIterator, @@ -103,14 +112,12 @@ where } } -impl Transactional for SpiExclusiveDevice +impl Transactional for SpiExclusiveDevice where SPI: SpiX, PINS: Pins, { - type Error = Infallible; - - fn exec<'op>(&mut self, operations: &mut [Operation<'op, u8>]) -> Result<(), Infallible> { + fn exec<'op>(&mut self, operations: &mut [Operation<'op, u8>]) -> Result<(), Self::Error> { self.bus.start_frame(); let result = self.bus.exec(operations); self.bus.end_frame(); diff --git a/src/spi/shared_device.rs b/src/spi/shared_device.rs index e611273..bf6c53d 100644 --- a/src/spi/shared_device.rs +++ b/src/spi/shared_device.rs @@ -1,8 +1,7 @@ -use core::convert::Infallible; - -use embedded_hal::{ - blocking::spi::{Operation, Transactional, Transfer, Write, WriteIter}, - spi::FullDuplex, +use embedded_hal::spi::{ + blocking::{Operation, Transactional, Transfer, TransferInplace, Write, WriteIter}, + nb::FullDuplex, + ErrorKind, ErrorType, }; use riscv::interrupt; @@ -40,15 +39,17 @@ where } } -impl FullDuplex for SpiSharedDevice<'_, SPI, PINS, CS> +impl ErrorType for SpiSharedDevice<'_, SPI, PINS, CS> { + type Error = ErrorKind; +} + +impl FullDuplex for SpiSharedDevice<'_, SPI, PINS, CS> where SPI: SpiX, PINS: Pins, CS: PinCS, { - type Error = Infallible; - - fn read(&mut self) -> nb::Result { + fn read(&mut self) -> nb::Result { interrupt::free(|cs| { let mut bus = self.bus.borrow(*cs).borrow_mut(); @@ -58,7 +59,7 @@ where }) } - fn send(&mut self, byte: u8) -> nb::Result<(), Infallible> { + fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { interrupt::free(|cs| { let mut bus = self.bus.borrow(*cs).borrow_mut(); @@ -69,22 +70,20 @@ where } } -impl Transfer for SpiSharedDevice<'_, SPI, PINS, CS> +impl Transfer for SpiSharedDevice<'_, SPI, PINS, CS> where SPI: SpiX, PINS: Pins, CS: PinCS, { - type Error = Infallible; - - fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { + fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { interrupt::free(move |cs| { let mut bus = self.bus.borrow(*cs).borrow_mut(); bus.configure(&self.config, Some(CS::CS_INDEX)); bus.start_frame(); - let result = bus.transfer(words); + let result = bus.transfer(read, write); bus.end_frame(); result @@ -92,14 +91,33 @@ where } } -impl Write for SpiSharedDevice<'_, SPI, PINS, CS> +impl TransferInplace for SpiSharedDevice<'_, SPI, PINS, CS> where SPI: SpiX, PINS: Pins, CS: PinCS, { - type Error = Infallible; + fn transfer_inplace<'w>(&mut self, words: &'w mut [u8]) -> Result<(), Self::Error> { + interrupt::free(move |cs| { + let mut bus = self.bus.borrow(*cs).borrow_mut(); + + bus.configure(&self.config, Some(CS::CS_INDEX)); + + bus.start_frame(); + let result = bus.transfer_inplace(words); + bus.end_frame(); + result + }) + } +} + +impl Write for SpiSharedDevice<'_, SPI, PINS, CS> +where + SPI: SpiX, + PINS: Pins, + CS: PinCS, +{ fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { interrupt::free(|cs| { let mut bus = self.bus.borrow(*cs).borrow_mut(); @@ -107,7 +125,7 @@ where bus.configure(&self.config, Some(CS::CS_INDEX)); bus.start_frame(); - let result = bus.write(words); + let result = bus.transfer(&mut [], words); bus.end_frame(); result @@ -115,14 +133,12 @@ where } } -impl WriteIter for SpiSharedDevice<'_, SPI, PINS, CS> +impl WriteIter for SpiSharedDevice<'_, SPI, PINS, CS> where SPI: SpiX, PINS: Pins, CS: PinCS, { - type Error = Infallible; - fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> where WI: IntoIterator, @@ -141,15 +157,13 @@ where } } -impl Transactional for SpiSharedDevice<'_, SPI, PINS, CS> +impl Transactional for SpiSharedDevice<'_, SPI, PINS, CS> where SPI: SpiX, PINS: Pins, CS: PinCS, { - type Error = Infallible; - - fn exec<'op>(&mut self, operations: &mut [Operation<'op, u8>]) -> Result<(), Infallible> { + fn exec<'op>(&mut self, operations: &mut [Operation<'op, u8>]) -> Result<(), Self::Error> { interrupt::free(|cs| { let mut bus = self.bus.borrow(*cs).borrow_mut(); diff --git a/src/stdout.rs b/src/stdout.rs index 004bcc8..516a280 100644 --- a/src/stdout.rs +++ b/src/stdout.rs @@ -10,7 +10,7 @@ where impl<'p, T> Write for Stdout<'p, T> where - T: embedded_hal::serial::Write, + T: embedded_hal::serial::nb::Write, { fn write_str(&mut self, s: &str) -> ::core::fmt::Result { for byte in s.as_bytes() { From 3ac7894db74ad25849f115834668acb97dd085e1 Mon Sep 17 00:00:00 2001 From: Ales Katona Date: Mon, 27 Jun 2022 10:50:37 -0700 Subject: [PATCH 2/3] bump version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 26334fa..5e7d698 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" [dependencies] embedded-hal = "=1.0.0-alpha.7" nb = "1.0.0" -riscv = "0.8.0" +riscv = "0.9.0-alpha.1" e310x = { version = "0.9.1", features = ["rt"] } [features] From 5c9175641cc69b8e25fba8ee6bd25998ece2b819 Mon Sep 17 00:00:00 2001 From: Ales Katona Date: Sat, 30 Jul 2022 16:13:13 -0700 Subject: [PATCH 3/3] fix transfer to wait for read bytes properly --- src/spi/bus.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/spi/bus.rs b/src/spi/bus.rs index 921d74b..d2a5d60 100644 --- a/src/spi/bus.rs +++ b/src/spi/bus.rs @@ -131,7 +131,8 @@ where // Ensure that RX FIFO is empty self.wait_for_rxfifo(); - while iwrite < write.len() || iread < read.len() { + // go through entire write buffer and read back (even if read buffer is empty) + while iwrite < write.len() || iread < write.len() { if iwrite < write.len() && self.spi.txdata.read().full().bit_is_clear() { let byte = write.get(iwrite).unwrap_or(&0); iwrite += 1;