From 4acac3141c45d284eb747c0973072feb676a512e Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 10 Mar 2020 14:16:21 +1300 Subject: [PATCH 1/5] Add transactional spi implementation. Requires embedded-hal patch with feature/spi-transactions branch and transactional-spi feature --- Cargo.toml | 5 +++++ src/lib.rs | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ab5168f..abf8e92 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,10 +7,12 @@ license = "MIT OR Apache-2.0" name = "linux-embedded-hal" repository = "https://github.com/japaric/linux-embedded-hal" version = "0.3.0" +edition = "2018" [features] gpio_sysfs = ["sysfs_gpio"] gpio_cdev = ["gpio-cdev"] +transactional-spi = [] # Guard for transactional SPI feature (https://github.com/rust-embedded/embedded-hal/pull/191) default = [ "gpio_cdev", "gpio_sysfs" ] @@ -32,3 +34,6 @@ openpty = "0.1.0" # we don't need the `Error` implementation default-features = false version = "0.2.2" + +[patch.crates-io] +#embedded-hal = { git = "https://github.com/ryankurte/embedded-hal", branch = "feature/spi-transactions" } diff --git a/src/lib.rs b/src/lib.rs index af89635..fdf45fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,6 @@ #![deny(missing_docs)] extern crate cast; -extern crate core; extern crate embedded_hal as hal; pub extern crate i2cdev; pub extern crate nb; @@ -202,7 +201,10 @@ impl hal::blocking::i2c::WriteRead for I2cdev { buffer: &mut [u8], ) -> Result<(), Self::Error> { self.set_address(address)?; - let mut messages = [LinuxI2CMessage::write(bytes), LinuxI2CMessage::read(buffer)]; + let mut messages = [ + LinuxI2CMessage::write(bytes), + LinuxI2CMessage::read(buffer), + ]; self.inner.transfer(&mut messages).map(drop) } } @@ -257,6 +259,40 @@ impl hal::blocking::spi::Write for Spidev { } } +#[cfg(feature = "transactional-spi")] +pub use hal::blocking::spi::{Operation as SpiOperation}; + +#[cfg(feature = "transactional-spi")] +impl hal::blocking::spi::Transactional for Spidev { + type Error = io::Error; + + fn try_exec<'a>(&mut self, operations: &mut [SpiOperation<'a, u8>]) -> Result<(), Self::Error> { + + // Map types from generic to linux objects + let mut messages: Vec<_> = operations.iter_mut().map(|a| { + match a { + SpiOperation::Write(w) => SpidevTransfer::write(w), + SpiOperation::Transfer(r) => { + // TODO: is spidev okay with the same array pointer + // being used twice? If not, need some kind of vector + // pool that will outlive the transfer + let w = unsafe { + let p = r.as_ptr(); + std::slice::from_raw_parts(p, r.len()) + }; + + SpidevTransfer::read_write(w, r) + }, + } + }).collect(); + + // Execute transfer + self.0.transfer_multiple(&mut messages)?; + + Ok(()) + } +} + impl ops::Deref for Spidev { type Target = spidev::Spidev; From 75467ef628205b5c53cae6c4aa6d674682fae7d5 Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 29 Oct 2020 08:49:56 +1300 Subject: [PATCH 2/5] update for transactional landed in e-h master --- Cargo.toml | 6 +++--- src/lib.rs | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index abf8e92..0ac54dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,12 +12,11 @@ edition = "2018" [features] gpio_sysfs = ["sysfs_gpio"] gpio_cdev = ["gpio-cdev"] -transactional-spi = [] # Guard for transactional SPI feature (https://github.com/rust-embedded/embedded-hal/pull/191) default = [ "gpio_cdev", "gpio_sysfs" ] [dependencies] -embedded-hal = "=1.0.0-alpha.1" +embedded-hal = "=1.0.0-alpha.2" gpio-cdev = { version = "0.3", optional = true } sysfs_gpio = { version = "0.5", optional = true } @@ -36,4 +35,5 @@ default-features = false version = "0.2.2" [patch.crates-io] -#embedded-hal = { git = "https://github.com/ryankurte/embedded-hal", branch = "feature/spi-transactions" } +embedded-hal = { git = "https://github.com/rust-embedded/embedded-hal" } + diff --git a/src/lib.rs b/src/lib.rs index fdf45fe..9ca6307 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -259,10 +259,9 @@ impl hal::blocking::spi::Write for Spidev { } } -#[cfg(feature = "transactional-spi")] pub use hal::blocking::spi::{Operation as SpiOperation}; -#[cfg(feature = "transactional-spi")] +/// Transactional implementation batches SPI operations into a single transaction impl hal::blocking::spi::Transactional for Spidev { type Error = io::Error; @@ -273,9 +272,8 @@ impl hal::blocking::spi::Transactional for Spidev { match a { SpiOperation::Write(w) => SpidevTransfer::write(w), SpiOperation::Transfer(r) => { - // TODO: is spidev okay with the same array pointer - // being used twice? If not, need some kind of vector - // pool that will outlive the transfer + // Clone read to write pointer + // SPIdev is okay with having w == r but this is tricky to achieve in safe rust let w = unsafe { let p = r.as_ptr(); std::slice::from_raw_parts(p, r.len()) From 86b8c2bd9c4c913befd33e9cf707db831f074362 Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 6 Nov 2020 07:41:30 +1300 Subject: [PATCH 3/5] bump e-h version, drop patch --- Cargo.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0ac54dd..1dc8929 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ gpio_cdev = ["gpio-cdev"] default = [ "gpio_cdev", "gpio_sysfs" ] [dependencies] -embedded-hal = "=1.0.0-alpha.2" +embedded-hal = "=1.0.0-alpha.3" gpio-cdev = { version = "0.3", optional = true } sysfs_gpio = { version = "0.5", optional = true } @@ -34,6 +34,3 @@ openpty = "0.1.0" default-features = false version = "0.2.2" -[patch.crates-io] -embedded-hal = { git = "https://github.com/rust-embedded/embedded-hal" } - From 687ab98fe900002218eeb70c9dd3c89e2604f583 Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 13 Nov 2020 12:13:32 +1300 Subject: [PATCH 4/5] changes for edition 2018 --- Cargo.toml | 7 +++++-- src/cdev_pin.rs | 4 ++-- src/lib.rs | 52 +++++++++++++++++++++++------------------------- src/serial.rs | 7 +++---- src/sysfs_pin.rs | 4 ++-- src/timer.rs | 2 +- 6 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1dc8929..a79cfec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,14 @@ [package] -authors = ["Jorge Aparicio "] +authors = [ + "The Embedded Linux Team ", + "Jorge Aparicio " +] categories = ["embedded", "hardware-support"] description = "Implementation of the `embedded-hal` traits for Linux devices" keywords = ["Linux", "hal"] license = "MIT OR Apache-2.0" name = "linux-embedded-hal" -repository = "https://github.com/japaric/linux-embedded-hal" +repository = "https://github.com/rust-embedded/linux-embedded-hal" version = "0.3.0" edition = "2018" diff --git a/src/cdev_pin.rs b/src/cdev_pin.rs index 88a6345..1d213e8 100644 --- a/src/cdev_pin.rs +++ b/src/cdev_pin.rs @@ -15,7 +15,7 @@ impl CdevPin { } } -impl hal::digital::OutputPin for CdevPin { +impl embedded_hal::digital::OutputPin for CdevPin { type Error = gpio_cdev::errors::Error; fn try_set_low(&mut self) -> Result<(), Self::Error> { @@ -27,7 +27,7 @@ impl hal::digital::OutputPin for CdevPin { } } -impl hal::digital::InputPin for CdevPin { +impl embedded_hal::digital::InputPin for CdevPin { type Error = gpio_cdev::errors::Error; fn try_is_high(&self) -> Result { diff --git a/src/lib.rs b/src/lib.rs index 9ca6307..bc24a93 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,19 +12,19 @@ #![deny(missing_docs)] -extern crate cast; -extern crate embedded_hal as hal; -pub extern crate i2cdev; -pub extern crate nb; -pub extern crate serial_core; -pub extern crate serial_unix; -pub extern crate spidev; +use cast; +pub use i2cdev; +pub use nb; +pub use serial_core; +pub use serial_unix; +pub use spidev; #[cfg(feature = "gpio_sysfs")] -pub extern crate sysfs_gpio; +pub use sysfs_gpio; #[cfg(feature = "gpio_cdev")] -pub extern crate gpio_cdev; +pub use gpio_cdev; + use core::convert::Infallible; use std::io::{self, Write}; @@ -61,7 +61,7 @@ pub use sysfs_pin::SysfsPin; /// Empty struct that provides delay functionality on top of `thread::sleep` pub struct Delay; -impl hal::blocking::delay::DelayUs for Delay { +impl embedded_hal::blocking::delay::DelayUs for Delay { type Error = Infallible; fn try_delay_us(&mut self, n: u8) -> Result<(), Self::Error> { @@ -70,7 +70,7 @@ impl hal::blocking::delay::DelayUs for Delay { } } -impl hal::blocking::delay::DelayUs for Delay { +impl embedded_hal::blocking::delay::DelayUs for Delay { type Error = Infallible; fn try_delay_us(&mut self, n: u16) -> Result<(), Self::Error> { @@ -79,7 +79,7 @@ impl hal::blocking::delay::DelayUs for Delay { } } -impl hal::blocking::delay::DelayUs for Delay { +impl embedded_hal::blocking::delay::DelayUs for Delay { type Error = Infallible; fn try_delay_us(&mut self, n: u32) -> Result<(), Self::Error> { @@ -91,7 +91,7 @@ impl hal::blocking::delay::DelayUs for Delay { } } -impl hal::blocking::delay::DelayUs for Delay { +impl embedded_hal::blocking::delay::DelayUs for Delay { type Error = Infallible; fn try_delay_us(&mut self, n: u64) -> Result<(), Self::Error> { @@ -103,7 +103,7 @@ impl hal::blocking::delay::DelayUs for Delay { } } -impl hal::blocking::delay::DelayMs for Delay { +impl embedded_hal::blocking::delay::DelayMs for Delay { type Error = Infallible; fn try_delay_ms(&mut self, n: u8) -> Result<(), Self::Error> { @@ -112,7 +112,7 @@ impl hal::blocking::delay::DelayMs for Delay { } } -impl hal::blocking::delay::DelayMs for Delay { +impl embedded_hal::blocking::delay::DelayMs for Delay { type Error = Infallible; fn try_delay_ms(&mut self, n: u16) -> Result<(), Self::Error> { @@ -121,7 +121,7 @@ impl hal::blocking::delay::DelayMs for Delay { } } -impl hal::blocking::delay::DelayMs for Delay { +impl embedded_hal::blocking::delay::DelayMs for Delay { type Error = Infallible; fn try_delay_ms(&mut self, n: u32) -> Result<(), Self::Error> { @@ -130,7 +130,7 @@ impl hal::blocking::delay::DelayMs for Delay { } } -impl hal::blocking::delay::DelayMs for Delay { +impl embedded_hal::blocking::delay::DelayMs for Delay { type Error = Infallible; fn try_delay_ms(&mut self, n: u64) -> Result<(), Self::Error> { @@ -173,7 +173,7 @@ impl I2cdev { } } -impl hal::blocking::i2c::Read for I2cdev { +impl embedded_hal::blocking::i2c::Read for I2cdev { type Error = i2cdev::linux::LinuxI2CError; fn try_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { @@ -182,7 +182,7 @@ impl hal::blocking::i2c::Read for I2cdev { } } -impl hal::blocking::i2c::Write for I2cdev { +impl embedded_hal::blocking::i2c::Write for I2cdev { type Error = i2cdev::linux::LinuxI2CError; fn try_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { @@ -191,7 +191,7 @@ impl hal::blocking::i2c::Write for I2cdev { } } -impl hal::blocking::i2c::WriteRead for I2cdev { +impl embedded_hal::blocking::i2c::WriteRead for I2cdev { type Error = i2cdev::linux::LinuxI2CError; fn try_write_read( @@ -240,7 +240,7 @@ impl Spidev { } } -impl hal::blocking::spi::Transfer for Spidev { +impl embedded_hal::blocking::spi::Transfer for Spidev { type Error = io::Error; fn try_transfer<'b>(&mut self, buffer: &'b mut [u8]) -> io::Result<&'b [u8]> { @@ -251,7 +251,7 @@ impl hal::blocking::spi::Transfer for Spidev { } } -impl hal::blocking::spi::Write for Spidev { +impl embedded_hal::blocking::spi::Write for Spidev { type Error = io::Error; fn try_write(&mut self, buffer: &[u8]) -> io::Result<()> { @@ -259,10 +259,10 @@ impl hal::blocking::spi::Write for Spidev { } } -pub use hal::blocking::spi::{Operation as SpiOperation}; +pub use embedded_hal::blocking::spi::{Operation as SpiOperation}; /// Transactional implementation batches SPI operations into a single transaction -impl hal::blocking::spi::Transactional for Spidev { +impl embedded_hal::blocking::spi::Transactional for Spidev { type Error = io::Error; fn try_exec<'a>(&mut self, operations: &mut [SpiOperation<'a, u8>]) -> Result<(), Self::Error> { @@ -285,9 +285,7 @@ impl hal::blocking::spi::Transactional for Spidev { }).collect(); // Execute transfer - self.0.transfer_multiple(&mut messages)?; - - Ok(()) + self.0.transfer_multiple(&mut messages) } } diff --git a/src/serial.rs b/src/serial.rs index a2ee551..102849c 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -5,7 +5,6 @@ use std::path::Path; use nb; -use hal; use serial_core; use serial_unix::TTYPort; @@ -30,7 +29,7 @@ fn translate_io_errors(err: std::io::Error) -> nb::Error { } } -impl hal::serial::Read for Serial { +impl embedded_hal::serial::Read for Serial { type Error = IoErrorKind; fn try_read(&mut self) -> nb::Result { @@ -44,7 +43,7 @@ impl hal::serial::Read for Serial { } } -impl hal::serial::Write for Serial { +impl embedded_hal::serial::Write for Serial { type Error = IoErrorKind; fn try_write(&mut self, word: u8) -> nb::Result<(), Self::Error> { @@ -61,7 +60,7 @@ impl hal::serial::Write for Serial { mod test { use std::path::Path; - use hal::serial::{Read, Write}; + use embedded_hal::serial::{Read, Write}; use std::io::{Read as IoRead, Write as IoWrite}; use super::*; diff --git a/src/sysfs_pin.rs b/src/sysfs_pin.rs index cf6bb97..10d8b8c 100644 --- a/src/sysfs_pin.rs +++ b/src/sysfs_pin.rs @@ -26,7 +26,7 @@ impl SysfsPin { } } -impl hal::digital::OutputPin for SysfsPin { +impl embedded_hal::digital::OutputPin for SysfsPin { type Error = sysfs_gpio::Error; fn try_set_low(&mut self) -> Result<(), Self::Error> { @@ -38,7 +38,7 @@ impl hal::digital::OutputPin for SysfsPin { } } -impl hal::digital::InputPin for SysfsPin { +impl embedded_hal::digital::InputPin for SysfsPin { type Error = sysfs_gpio::Error; fn try_is_high(&self) -> Result { diff --git a/src/timer.rs b/src/timer.rs index a64677d..0b26b19 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -3,7 +3,7 @@ use core::convert::Infallible; use std::time::{Duration, Instant}; -use hal::timer::{CountDown, Periodic}; +use embedded_hal::timer::{CountDown, Periodic}; /// A periodic timer based on [`std::time::Instant`][instant], which is a /// monotonically nondecreasing clock. From d7d7783c1701cc37c720bd1815b9ac0f52cba152 Mon Sep 17 00:00:00 2001 From: ryan Date: Mon, 16 Nov 2020 09:29:34 +1300 Subject: [PATCH 5/5] fix update from master --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index be8131f..32ee25d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,7 @@ use std::time::Duration; use std::{ops, thread}; use cast::{u32, u64}; -use hal::blocking::i2c::Operation as I2cOperation; +use embedded_hal::blocking::i2c::Operation as I2cOperation; use i2cdev::core::{I2CDevice, I2CMessage, I2CTransfer}; use i2cdev::linux::LinuxI2CMessage; use spidev::SpidevTransfer; @@ -210,7 +210,7 @@ impl embedded_hal::blocking::i2c::WriteRead for I2cdev { } } -impl hal::blocking::i2c::Transactional for I2cdev { +impl embedded_hal::blocking::i2c::Transactional for I2cdev { type Error = i2cdev::linux::LinuxI2CError; fn try_exec(&mut self, address: u8, operations: &mut [I2cOperation]) -> Result<(), Self::Error>