From 97340755b42372ef21195735390bb9f2892db635 Mon Sep 17 00:00:00 2001 From: mlehurau Date: Mon, 31 Jul 2023 16:01:08 -0400 Subject: [PATCH 1/4] Update embedded-hal --- Cargo.toml | 4 +- src/serial.rs | 1 + src/spi.rs | 118 +++++++++++++++++++++++++------------------------- 3 files changed, 63 insertions(+), 60 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1de3a72..af4f4c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,8 +22,8 @@ spi = ["spidev"] default = [ "gpio_cdev", "gpio_sysfs", "i2c", "spi" ] [dependencies] -embedded-hal = "=1.0.0-alpha.10" -embedded-hal-nb = "=1.0.0-alpha.2" +embedded-hal = "=1.0.0-alpha.11" +embedded-hal-nb = "=1.0.0-alpha.3" gpio-cdev = { version = "0.5.1", optional = true } sysfs_gpio = { version = "0.6.1", optional = true } i2cdev = { version = "0.5.1", optional = true } diff --git a/src/serial.rs b/src/serial.rs index 8b81354..35ead87 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -81,6 +81,7 @@ impl fmt::Display for SerialError { impl std::error::Error for SerialError {} impl embedded_hal::serial::Error for SerialError { + #[allow(clippy::match_single_binding)] fn kind(&self) -> embedded_hal::serial::ErrorKind { use embedded_hal::serial::ErrorKind::*; // TODO: match any errors here if we can find any that are relevant diff --git a/src/spi.rs b/src/spi.rs index 4a55ace..a9ffaba 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -8,20 +8,25 @@ use std::io; use std::ops; use std::path::Path; +use crate::Delay; +use spidev::SpidevTransfer; + /// Newtype around [`spidev::Spidev`] that implements the `embedded-hal` traits /// -/// [`spidev::Spidev`]: https://docs.rs/spidev/0.5.0/spidev/struct.Spidev.html -pub struct Spidev(pub spidev::Spidev); +/// [`spidev::Spidev`]: https://docs.rs/spidev/0.5.spidev/spidev/struct.Spidev.html +pub struct Spidev(pub spidev::Spidev, Delay); impl Spidev { /// See [`spidev::Spidev::open`][0] for details. /// - /// [0]: https://docs.rs/spidev/0.5.0/spidev/struct.Spidev.html#method.open + /// [0]: https://docs.rs/spidev/0.5.spidev/spidev/struct.Spidev.html#method.open pub fn open

(path: P) -> Result where P: AsRef, { - spidev::Spidev::open(path).map(Spidev).map_err(|e| e.into()) + spidev::Spidev::open(path) + .map(|spidev| Spidev(spidev, Delay {})) + .map_err(|e| e.into()) } } @@ -41,11 +46,9 @@ impl ops::DerefMut for Spidev { mod embedded_hal_impl { use super::*; + use embedded_hal::delay::DelayUs; use embedded_hal::spi::ErrorType; - use embedded_hal::spi::{ - Operation as SpiOperation, SpiBus, SpiBusFlush, SpiBusRead, SpiBusWrite, SpiDevice, - SpiDeviceRead, SpiDeviceWrite, - }; + use embedded_hal::spi::{Operation as SpiOperation, SpiBus, SpiDevice}; use spidev::SpidevTransfer; use std::io::{Read, Write}; @@ -53,25 +56,15 @@ mod embedded_hal_impl { type Error = SPIError; } - impl SpiBusFlush for Spidev { - fn flush(&mut self) -> Result<(), Self::Error> { - self.0.flush().map_err(|err| SPIError { err }) - } - } - - impl SpiBusRead for Spidev { + impl SpiBus for Spidev { fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { self.0.read_exact(words).map_err(|err| SPIError { err }) } - } - impl SpiBusWrite for Spidev { fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { self.0.write_all(words).map_err(|err| SPIError { err }) } - } - impl SpiBus for Spidev { fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { self.0 .transfer(&mut SpidevTransfer::read_write(write, read)) @@ -84,33 +77,9 @@ mod embedded_hal_impl { .transfer(&mut SpidevTransfer::read_write(&tx, words)) .map_err(|err| SPIError { err }) } - } - - impl SpiDeviceRead for Spidev { - fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> { - let mut transfers: Vec<_> = operations - .iter_mut() - .map(|op| SpidevTransfer::read(op)) - .collect(); - self.0 - .transfer_multiple(&mut transfers) - .map_err(|err| SPIError { err })?; - self.flush()?; - Ok(()) - } - } - impl SpiDeviceWrite for Spidev { - fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> { - let mut transfers: Vec<_> = operations - .iter() - .map(|op| SpidevTransfer::write(op)) - .collect(); - self.0 - .transfer_multiple(&mut transfers) - .map_err(|err| SPIError { err })?; - self.flush()?; - Ok(()) + fn flush(&mut self) -> Result<(), Self::Error> { + self.0.flush().map_err(|err| SPIError { err }) } } @@ -119,30 +88,62 @@ mod embedded_hal_impl { &mut self, operations: &mut [SpiOperation<'_, u8>], ) -> Result<(), Self::Error> { - let mut transfers: Vec<_> = operations - .iter_mut() - .map(|op| match op { - SpiOperation::Read(buf) => SpidevTransfer::read(buf), - SpiOperation::Write(buf) => SpidevTransfer::write(buf), - SpiOperation::Transfer(read, write) => SpidevTransfer::read_write(write, read), + let mut spidev_ops: Vec = vec![]; + let mut spidev_transfers: Vec = vec![]; + + for op in operations { + match op { + SpiOperation::Read(buf) => spidev_transfers.push(SpidevTransfer::read(buf)), + SpiOperation::Write(buf) => spidev_transfers.push(SpidevTransfer::write(buf)), + SpiOperation::Transfer(read, write) => { + spidev_transfers.push(SpidevTransfer::read_write(write, read)) + } SpiOperation::TransferInPlace(buf) => { let tx = unsafe { let p = buf.as_ptr(); std::slice::from_raw_parts(p, buf.len()) }; - SpidevTransfer::read_write(tx, buf) + spidev_transfers.push(SpidevTransfer::read_write(tx, buf)) } - }) - .collect(); - self.0 - .transfer_multiple(&mut transfers) - .map_err(|err| SPIError { err })?; - self.flush()?; + SpiOperation::DelayUs(us) => { + if !spidev_transfers.is_empty() { + let mut transfers: Vec = vec![]; + std::mem::swap(&mut transfers, &mut spidev_transfers); + spidev_ops.push(Operation::Transfers(transfers)); + } + spidev_ops.push(Operation::Delay(us.to_owned())); + } + } + } + + if !spidev_transfers.is_empty() { + spidev_ops.push(Operation::Transfers(spidev_transfers)); + } + + for op in spidev_ops { + match op { + Operation::Transfers(mut transfers) => { + self.0 + .transfer_multiple(&mut transfers) + .map_err(|err| SPIError { err })?; + self.flush()?; + } + Operation::Delay(us) => { + self.1.delay_us(us); + } + } + } + Ok(()) } } } +enum Operation<'a, 'b> { + Transfers(Vec>), + Delay(u32), +} + /// Error type wrapping [io::Error](io::Error) to implement [embedded_hal::spi::ErrorKind] #[derive(Debug)] pub struct SPIError { @@ -163,6 +164,7 @@ impl From for SPIError { } impl embedded_hal::spi::Error for SPIError { + #[allow(clippy::match_single_binding)] fn kind(&self) -> embedded_hal::spi::ErrorKind { use embedded_hal::spi::ErrorKind; // TODO: match any errors here if we can find any that are relevant From 91800ce90e6b6ea087b5fc169776f5c116a59972 Mon Sep 17 00:00:00 2001 From: mlehurau Date: Tue, 8 Aug 2023 09:46:23 -0400 Subject: [PATCH 2/4] Use Spidev 0.5.2 This allows using the delay transfer support. --- Cargo.toml | 2 +- src/spi.rs | 72 ++++++++++++++---------------------------------------- 2 files changed, 20 insertions(+), 54 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index af4f4c0..e3658c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ sysfs_gpio = { version = "0.6.1", optional = true } i2cdev = { version = "0.5.1", optional = true } nb = "1" serialport = { version = "4.2.0", default-features = false } -spidev = { version = "0.5.1", optional = true } +spidev = { version = "0.5.2", optional = true } nix = "0.23.1" [dev-dependencies] diff --git a/src/spi.rs b/src/spi.rs index a9ffaba..2ac2a57 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -8,25 +8,20 @@ use std::io; use std::ops; use std::path::Path; -use crate::Delay; -use spidev::SpidevTransfer; - /// Newtype around [`spidev::Spidev`] that implements the `embedded-hal` traits /// -/// [`spidev::Spidev`]: https://docs.rs/spidev/0.5.spidev/spidev/struct.Spidev.html -pub struct Spidev(pub spidev::Spidev, Delay); +/// [`spidev::Spidev`]: https://docs.rs/spidev/0.5.2/spidev/struct.Spidev.html +pub struct Spidev(pub spidev::Spidev); impl Spidev { /// See [`spidev::Spidev::open`][0] for details. /// - /// [0]: https://docs.rs/spidev/0.5.spidev/spidev/struct.Spidev.html#method.open + /// [0]: https://docs.rs/spidev/0.5.2/spidev/struct.Spidev.html#method.open pub fn open

(path: P) -> Result where P: AsRef, { - spidev::Spidev::open(path) - .map(|spidev| Spidev(spidev, Delay {})) - .map_err(|e| e.into()) + spidev::Spidev::open(path).map(Spidev).map_err(|e| e.into()) } } @@ -46,10 +41,10 @@ impl ops::DerefMut for Spidev { mod embedded_hal_impl { use super::*; - use embedded_hal::delay::DelayUs; use embedded_hal::spi::ErrorType; use embedded_hal::spi::{Operation as SpiOperation, SpiBus, SpiDevice}; use spidev::SpidevTransfer; + use std::convert::TryInto; use std::io::{Read, Write}; impl ErrorType for Spidev { @@ -88,62 +83,33 @@ mod embedded_hal_impl { &mut self, operations: &mut [SpiOperation<'_, u8>], ) -> Result<(), Self::Error> { - let mut spidev_ops: Vec = vec![]; - let mut spidev_transfers: Vec = vec![]; - - for op in operations { - match op { - SpiOperation::Read(buf) => spidev_transfers.push(SpidevTransfer::read(buf)), - SpiOperation::Write(buf) => spidev_transfers.push(SpidevTransfer::write(buf)), - SpiOperation::Transfer(read, write) => { - spidev_transfers.push(SpidevTransfer::read_write(write, read)) - } + let mut transfers: Vec<_> = operations + .iter_mut() + .map(|op| match op { + SpiOperation::Read(buf) => SpidevTransfer::read(buf), + SpiOperation::Write(buf) => SpidevTransfer::write(buf), + SpiOperation::Transfer(read, write) => SpidevTransfer::read_write(write, read), SpiOperation::TransferInPlace(buf) => { let tx = unsafe { let p = buf.as_ptr(); std::slice::from_raw_parts(p, buf.len()) }; - spidev_transfers.push(SpidevTransfer::read_write(tx, buf)) + SpidevTransfer::read_write(tx, buf) } SpiOperation::DelayUs(us) => { - if !spidev_transfers.is_empty() { - let mut transfers: Vec = vec![]; - std::mem::swap(&mut transfers, &mut spidev_transfers); - spidev_ops.push(Operation::Transfers(transfers)); - } - spidev_ops.push(Operation::Delay(us.to_owned())); - } - } - } - - if !spidev_transfers.is_empty() { - spidev_ops.push(Operation::Transfers(spidev_transfers)); - } - - for op in spidev_ops { - match op { - Operation::Transfers(mut transfers) => { - self.0 - .transfer_multiple(&mut transfers) - .map_err(|err| SPIError { err })?; - self.flush()?; - } - Operation::Delay(us) => { - self.1.delay_us(us); + SpidevTransfer::delay((*us).try_into().unwrap_or(u16::MAX)) } - } - } - + }) + .collect(); + self.0 + .transfer_multiple(&mut transfers) + .map_err(|err| SPIError { err })?; + self.flush()?; Ok(()) } } } -enum Operation<'a, 'b> { - Transfers(Vec>), - Delay(u32), -} - /// Error type wrapping [io::Error](io::Error) to implement [embedded_hal::spi::ErrorKind] #[derive(Debug)] pub struct SPIError { From 5878590954a4ecf9def4fad0b5b1ac01ea5b5a92 Mon Sep 17 00:00:00 2001 From: mlehurau Date: Tue, 8 Aug 2023 10:05:21 -0400 Subject: [PATCH 3/4] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7959974..15aeec0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - [breaking-change] Replace serial-rs with the serialport-rs crate. `Serial::open` now needs a baud-rate argument as well. -- Updated to `embedded-hal` `1.0.0-alpha.10` release ([API changes](https://github.com/rust-embedded/embedded-hal/blob/master/embedded-hal/CHANGELOG.md#v100-alpha10---2023-04-04)) +- Updated to `embedded-hal` `1.0.0-alpha.11` release ([API changes](https://github.com/rust-embedded/embedded-hal/blob/master/embedded-hal/CHANGELOG.md#v100-alpha11---2023-07-04)) +- Updated to `spidev` `0.5.2` release([API changes](https://github.com/rust-embedded/rust-spidev/blob/master/CHANGELOG.md#052--2023-08-02)) ## [v0.4.0-alpha.3] - 2022-08-04 From 847e93e44e6a81e7e76afd8a14c943fa1d8238b0 Mon Sep 17 00:00:00 2001 From: mlehurau Date: Wed, 6 Sep 2023 14:48:25 -0400 Subject: [PATCH 4/4] Document delay operations are capped --- src/spi.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/spi.rs b/src/spi.rs index 2ac2a57..8da6a76 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -10,7 +10,10 @@ use std::path::Path; /// Newtype around [`spidev::Spidev`] that implements the `embedded-hal` traits /// +/// [Delay operations][delay] are capped to 65535 microseconds. +/// /// [`spidev::Spidev`]: https://docs.rs/spidev/0.5.2/spidev/struct.Spidev.html +/// [delay]: embedded_hal::spi::Operation::DelayUs pub struct Spidev(pub spidev::Spidev); impl Spidev { @@ -79,6 +82,12 @@ mod embedded_hal_impl { } impl SpiDevice for Spidev { + ///Perform a transaction against the device. [Read more][transaction] + /// + /// [Delay operations][delay] are capped to 65535 microseconds. + /// + /// [transaction]: SpiDevice::transaction + /// [delay]: SpiOperation::DelayUs fn transaction( &mut self, operations: &mut [SpiOperation<'_, u8>],